---
title: CSS customization
description: The CSS custom properties, class names and loading order you can use to restyle the CartPops drawer and launcher.
sidebar:
  label: CSS customization
  icon: paintbrush
---

Most of the look of CartPops comes from settings (Design, Drawer and Launcher screens). Use CSS for what the settings do not cover. CartPops exposes its look through CSS custom properties, and its markup uses a stable `cpops-` prefix.

## Where Custom CSS loads

Add your CSS in **WooCommerce** > **CartPops** > **Advanced** > **General** > **Custom CSS** > **Additional CSS**.

CartPops prints it as an inline stylesheet after its own drawer stylesheet, so your rules win over CartPops' rules at equal specificity. CartPops strips HTML tags from it. It is added only when CartPops is enabled and the field is not empty. The stylesheet handle is `cartpops-drawer-custom-css`, and it depends on `cartpops-cart-drawer-style`. To change what it depends on, see the [`cartpops_custom_css_style_dependencies` filter](/developers/php-filters#cartpops_custom_css_style_dependencies).

You can also put CSS in your theme. Load it after CartPops' stylesheets and test it, because the drawer resets inherited styles.

## The drawer ignores your theme

Inside the drawer, CartPops resets inherited styles so that theme and page builder rules do not leak in. Your own markup printed by a [PHP action](/developers/php-actions) is reset as well. Style it with a class and write the rule under `.cpops-drawer`.

Some elements, such as buttons, headings and links, are reset with a selector that includes `:not(#_)`, which gives the rule the weight of an ID. If your rule for one of those elements loses, repeat the pattern:

```css custom.css
.cpops-drawer:not(#_) .cpops-btn--checkout {
	text-transform: uppercase;
}
```

## Custom properties

CartPops reads its colors, sizes and timing from CSS custom properties. This works in two layers.

### Set from your settings, printed on the drawer

The Design and Drawer settings are printed as an inline `style` attribute on the drawer wrapper, `.cpops-modal`. An inline value on an element beats a value you set on `:root` or `body`, because the drawer elements inherit from the wrapper. To override one of these variables, target the wrapper and use `!important`:

```css custom.css
.cpops-modal {
	--cpops-primary: #e11d48 !important;
	--cpops-button-primary-bg: #e11d48 !important;
	--cpops-drawer-width: 420px !important;
}
```

| Property | Controls |
| --- | --- |
| `--cpops-primary`, `--cpops-primary-text` | Accent color and text on it. |
| `--cpops-secondary`, `--cpops-secondary-text` | Secondary color and its text. |
| `--cpops-background`, `--cpops-surface` | Drawer background and secondary surface. |
| `--cpops-text-primary`, `--cpops-text-secondary`, `--cpops-text-tertiary` | Text colors. |
| `--cpops-border` | Borders. |
| `--cpops-input-bg`, `--cpops-input-border`, `--cpops-input-text` | Form fields such as the coupon input. |
| `--cpops-button-primary-bg`, `--cpops-button-primary-text` | Primary button, such as checkout. |
| `--cpops-button-secondary-bg`, `--cpops-button-secondary-text` | Secondary buttons. |
| `--cpops-quantity-button-bg`, `--cpops-quantity-button-text` | Quantity plus and minus buttons. |
| `--cpops-quantity-input-bg`, `--cpops-quantity-input-border`, `--cpops-quantity-input-text` | Quantity value. |
| `--cpops-recs-background`, `--cpops-recs-border`, `--cpops-recs-text` | Recommendation cards. |
| `--cpops-recs-button-bg`, `--cpops-recs-button-text` | Recommendation add button. |
| `--cpops-sale`, `--cpops-success`, `--cpops-danger` | Sale price, success and error colors. |
| `--cpops-overlay` | The overlay behind the drawer. Applies to `.cpops-overlay`. |
| `--cpops-border-radius`, `--cpops-button-border-radius` | Corner radius. |
| `--cpops-drawer-width`, `--cpops-drawer-width-mobile` | Drawer width on desktop and on mobile. |
| `--cpops-animation-duration` | Open and close animation time. |
| `--cpops-dark-background`, `--cpops-dark-surface`, `--cpops-dark-text-primary`, `--cpops-dark-text-secondary`, `--cpops-dark-border`, `--cpops-dark-input-bg`, `--cpops-dark-input-border`, `--cpops-dark-overlay` | The dark palette. |

In dark mode (`data-dark-mode="dark"`, or `auto` with a dark system theme), CartPops swaps in its dark palette with `!important`. To recolor it, set the `--cpops-dark-*` variables on `.cpops-modal` with `!important`, as above, instead of the plain variables.

CartPops Pro also prints `--cpops-meter-*` variables for the shipping meter colors, for example `--cpops-meter-bar-start`, `--cpops-meter-bar-end`, `--cpops-meter-bg` and `--cpops-meter-text`. They follow the same rule.

### Not printed by CartPops, so `:root` works

These have defaults in CartPops' stylesheet, and nothing prints over them. Set them anywhere, such as `:root`.

| Property | Default | Controls |
| --- | --- | --- |
| `--cpops-z-index` | `999999` | Stacking. The overlay uses this value, the drawer one more, and the launcher one less. |
| `--cpops-font-family` | A system font stack | Font in the drawer and the launcher count. |
| `--cpops-font-size` | `16px` when unset | Base font size in the drawer. |

```css custom.css
:root {
	--cpops-z-index: 100000;
	--cpops-font-family: "Inter", sans-serif;
}
```

### Launcher

The launcher uses `--cpops-launcher-bg`, `--cpops-launcher-icon`, `--cpops-launcher-badge-bg` and `--cpops-launcher-badge-text`. They are printed on the launcher wrapper from the Launcher screen colors. The floating launcher also reads `--cpops-launcher-size` (default `56px`) and `--cpops-launcher-offset-x` and `--cpops-launcher-offset-y` (default `24px`), which are printed only when you change them. Override them on the button itself:

```css custom.css
.cpops-launcher {
	--cpops-launcher-bg: #111827;
	--cpops-launcher-badge-bg: #e11d48;
}
```

### The V1 variables still work

CartPops V1 printed its variables on `:root`, and V2 still reads them. If your CSS sets a V1 variable on `:root`, it keeps working, and it is the one case where `:root` beats the printed value. V2 also exposes the V1 names again inside the drawer, so old rules that only read `var(--color-cpops-...)` still resolve.

| V1 variable on `:root` | V2 variable it feeds |
| --- | --- |
| `--color-cpops-accent-color` | `--cpops-primary` |
| `--color-cpops-background-primary` | `--cpops-background` |
| `--color-cpops-text-primary` | `--cpops-text-primary` |
| `--color-cpops-border-color` | `--cpops-border` |
| `--color-cpops-button-primary-background` | `--cpops-button-primary-bg` |
| `--color-cpops-button-primary-text` | `--cpops-button-primary-text` |
| `--color-cpops-overlay-background` | `--cpops-overlay` |
| `--cpops-width-drawer-desktop` | `--cpops-drawer-width` |
| `--cpops-width-drawer-mobile` | `--cpops-drawer-width-mobile` |
| `--color-cpops-floating-cart-launcher-background` | `--cpops-launcher-bg` (floating launcher) |
| `--color-cpops-cart-launcher-background` | `--cpops-launcher-bg` (inline launchers) |

This is a selection. The full list is in [Upgrading to V2: for developers](/upgrading-to-v2/developers). Set a V1 variable on `:root` only, because setting it on a single element does not reconfigure V2. For new CSS, use the V2 names.

## Class names

These are the classes CartPops puts on its markup. They are not covered by a stability promise, so check your CSS after updates. The `cpops-` prefix is the same as in V1, but the structure is not.

| Class | Element |
| --- | --- |
| `.cpops-modal` | Outer wrapper, holding the overlay, the drawer and the printed custom properties. |
| `.cpops-overlay` | The overlay. Has `.cpops-overlay-visible` while the drawer is open. |
| `.cpops-drawer` | The drawer panel. Also `.cpops-drawer--right` or `.cpops-drawer--left`. Has `.cpops-drawer-open` while open and `.cpops-drawer-loading` while loading. |
| `.cpops-drawer__header`, `__title`, `__count`, `__close` | Header, title, item count and close button. |
| `.cpops-drawer__content`, `__items` | The scrolling body and the cart lines list. |
| `.cpops-drawer__empty` | The empty cart message. |
| `.cpops-drawer__footer` | Footer. Hidden through `.cpops-hidden` while the cart is empty. |
| `.cpops-cart-item` | One cart line. Its parts are `__image`, `__name`, `__price`, `__price-current` (the line total), `__price-regular` (the struck regular line total), `__price-each` (the unit price, shown when the quantity is more than one), `__remove`, `__meta` and `__extra-line`. |
| `.cpops-quantity`, `__btn`, `__value` | Quantity controls. |
| `.cpops-coupon`, `__toggle`, `__form`, `__input`, `__btn`, `__tags`, `__tag` | Coupon field and applied coupons. On short phone screens `__toggle` ("Have a coupon?") shows and the form stays collapsed until it is opened; `.cpops-coupon--open` marks it open. |
| `.cpops-totals`, `__row`, `__label`, `__value` | Totals. |
| `.cpops-btn`, `--primary`, `--secondary`, `--checkout` | Buttons. |
| `.cpops-secondary-action` | The Pro secondary action button. |
| `.cpops-drawer__view-cart`, `.cpops-powered-by` | View Cart link and Powered by link. |
| `.cpops-recs`, `__card`, `__add-btn`, `__list` | Recommendations. |
| `.cpops-launcher` | The launcher button. Also `--floating` or `--inline`, `--bottom_right` or `--bottom_left`, and `--count-bubble`, `--count-plain` or `--count-none`. |
| `.cpops-launcher__icon`, `__badge`, `__total` | Launcher icon, count and total. |
| `.cpops-hidden`, `.cpops-sr-only` | Utility classes. |

The drawer also carries `data-animation` (`slide`, `fade` or `none`), `data-dark-mode` (`auto`, `light` or `dark`) and `data-product-name-display`.

For old CSS, CartPops adds some V1 class names to the matching V2 element as aliases, such as `.cpops-drawer-header`, `.cpops-drawer-footer`, `.cpops-empty-cart`, `.cpops-modal-backdrop` and `.cartpops-cart__container`. Use the V2 names in new CSS.

## What changed from V1 selectors

- **IDs are gone.** `#cpops-drawer-modal`, `#cartpops-drawer` and `#cpops-floating-cart` do not exist. The drawer has a generated ID such as `cpops-drawer-1`. Use classes.
- **The structure changed.** Several V1 classes that sat on different nested elements now sit on one element, so descendant selectors between them break.
- **Some classes have no V2 equivalent.** Popup, bar and assistant classes, the recommendation slider, the V1 cart row internals and the V1 animation state classes are not recreated.
- **Open state.** The drawer is open when `.cpops-drawer` has `.cpops-drawer-open`. V1's `cpops-show` and `html.cpops-trigger-open` are gone.

The class and variable mappings are listed in [Upgrading to V2: for developers](/upgrading-to-v2/developers).

:::note[Coming from V1?]
Your V1 Custom CSS is carried over and still loads after the CartPops styles, but rules that depend on V1's markup may not match. See [Upgrading to V2: for developers](/upgrading-to-v2/developers).
:::
