Skip to content

Styling

How to override the design tokens (colors, spacing, dark mode) and, when needed, the structural styles of the Payplug Elements.

The components ship with their stylesheet, payplug-elements.css, loaded automatically at startup alongside payplug-elements.js — nothing for you to include. It carries two things:

  • the structural CSS — layout, isolation, component skeletons;
  • the default theme — every visual value, expressed as --payplug-* design tokens (light and dark).

Isolation runs both ways. Your page’s styles don’t reach into the components: their roots reset everything, and an internal rule zeroes the margins of their elements — the ones a documentation theme applies to every paragraph and list, which otherwise pushed the logos and buttons out of place. Their styles don’t get out either (@scope).

Keep your own stylesheet out of @layer: an unlayered declaration beats a layered one whatever its specificity. That is what lets you override structural styles, and it is also what protects the components.

There are two customization surfaces, in order of preference: override tokens (covers colors, fonts, spacing, radii — and survives component updates), and override structural styles (an escape hatch for anything the tokens don’t reach, e.g. alignments or borders).

The default theme is declared at CSS specificity 0 (inside :where()). Any re-declaration on payplug-session — from any stylesheet, in any load order — wins. Dark values included: your override applies in both schemes unless you scope it yourself.

/* anywhere in your CSS */
payplug-session {
--payplug-color-accent: #c026d3;
--payplug-radius: 0;
}

You can also ship overrides as a standalone theme file and point the component at it — the link is injected for you and removed when the attribute is cleared:

<payplug-session theme="https://example.shop/checkout-theme.css"></payplug-session>

Dark tokens apply automatically from the OS preference (prefers-color-scheme). Force a scheme with the color-scheme attribute:

<payplug-session color-scheme="light"></payplug-session>
<!-- or "dark" -->

To give a token a dark-specific value, scope your own re-declaration the same way the default theme does:

@media (prefers-color-scheme: dark) {
payplug-session:not([color-scheme="light"]) {
--payplug-color-accent: #8ab4ff;
}
}
payplug-session[color-scheme="dark"] {
--payplug-color-accent: #8ab4ff;
}

Every knob below can be tried live in the playground’s theme panel, which also exports your overrides as a ready-made theme file.

Token Default (light) Default (dark)
--payplug-color-scheme light dark dark
--payplug-font-family system-ui, -apple-system, "Segoe UI", Roboto, sans-serif
--payplug-font-size-sm / -md / -lg 0.85rem / 0.95rem / 1.1rem
--payplug-gap 0.5rem
--payplug-line-height 1.3
--payplug-radius 6px
--payplug-color-text #1a1a2e #ececf2
--payplug-color-placeholder #6f6f80 #8f8fa0
--payplug-color-surface #ffffff #232334
--payplug-color-border #c9c9d4 #44454f
--payplug-color-accent #0555eb #5b8cff
--payplug-color-on-accent #ffffff #0b0b14
--payplug-color-danger #ff2600 #ff6b6b
--payplug-color-danger-surface 10% danger mixed into the surface (color-mix)
--payplug-color-success #188038 #5dc389
--payplug-color-failure #727272
--payplug-color-surface-muted 10% accent mixed into the surface (color-mix)
--payplug-selected-shadow inset 0 0 0 1px var(--payplug-color-accent)
--payplug-reassurance-border 1px dashed var(--payplug-color-border)
--payplug-progress-fill 45° accent hatch — a 28px square tile (full background shorthand, image + position/size). If you override it, keep an integer tile width and match the slide animation’s travel to it, or the loop shows a seam
--payplug-pill-radius 999px
--payplug-pill-background var(--payplug-color-surface-muted)
--payplug-dialog-backdrop rgb(0 0 0 / 0.45) — the modal scrim, scheme-independent

The stylesheet also declares --payplug-applepay-button-*, --payplug-ancv-button-* and --payplug-oney-button-*: those carry the payment brands’ fixed colors and are not theming knobs — brand guidelines, not yours to restyle.

--payplug-font-size-md is the components’ body size (set on every component root): text without an explicit size follows it, and -sm/-lg step from there.

--payplug-gap is the single spacing knob: every internal gap, margin and padding derives from it (calc(var(--payplug-gap) × n)), so changing it scales the whole layout proportionally.

Every inner element carries a stable, documented class following payplug-<component>__<part> (e.g. payplug-outcome__recap, payplug-method-submit, payplug-amount-picker__chip; factory-built pieces such as the transaction cards carry their own family, e.g. payplug-tx__amount). These classes are part of the public surface — you can target them directly.

Two things to know about how the structural CSS is written:

  1. It does not rely on inheritance. Each component root resets itself (all: initial), so styles you set on your page (or on payplug-session) do not cascade into the components — by design. The two supported entry points are the tokens above and the structural classes below.
  2. Its rules are scoped but low-specificity. Rules live in @scope blocks, which add no specificity — a rule like .payplug-tx { … } weighs a single class. Prefix your override with the component’s tag name and it wins:
/* soften the recap cards on the confirmation screen */
payplug-confirmation .payplug-tx {
border-left: none;
border-radius: 8px;
}

Some chrome is deliberately left to you — for instance payplug-confirmation ships with no background, border, radius or padding on its panel, so it inherits your page’s card style:

payplug-confirmation .payplug-outcome {
border: 1px solid var(--payplug-color-border);
border-radius: var(--payplug-radius);
padding: calc(var(--payplug-gap) * 2);
}

Note that your overrides can (and usually should) reuse the tokens, so they keep adapting to light/dark automatically.