Appearance
Customize checkout and payment field styling — themes, colors, CSS variables, rules, locale, layout, and server branding.
Pass an appearance object to hosted checkout (mount / open / CheckoutEmbed) or to
wajub.components(). The same object works everywhere.
For merchant-wide defaults (logo, colors, layout) set at payment creation, see Branding & theming.
Basic customization
wajub.mount('#checkout', {
sessionId,
appearance: {
theme: 'stripe',
primaryColor: '#6366f1',
colorScheme: 'auto',
labels: 'floating',
variables: {
colorText: '#0f172a',
fontSizeBase: '16px',
},
rules: {
'.Input': { borderRadius: '8px' },
'.Label': { fontWeight: '500' },
},
},
});Theme presets
Set appearance.theme to layer a built-in preset before your explicit keys:
| Preset | Description | Default highlights |
|---|---|---|
stripe | Clean default (Wajub standard) | Blue primary #0570de, 4px radius, system font, low shadow |
night | Dark UI | Dark background #0f172a, purple accent, colorScheme: dark, no shadow |
flat | Minimal, no elevation | shadow: none, borderRadius: 0 |
none | No preset — only your explicit keys apply | Empty base |
Explicit keys in appearance always override preset values.
AppearanceConfig — flat color keys
| Field | Type | Description |
|---|---|---|
theme | stripe · night · flat · none | Built-in preset (layered first) |
primaryColor | CSS color | Accent color, primary buttons, links |
secondaryColor | CSS color | Secondary accents |
backgroundColor | CSS color | Page / surface background |
fontFamily | CSS font stack | Global font |
borderRadius | CSS length | Default corner radius (e.g. 8px, 0) |
buttonTextColor | CSS color | Text on primary buttons |
inputBackgroundColor | CSS color | Form field background |
inputBorderColor | CSS color | Form field border |
textMutedColor | CSS color | Secondary / helper text |
successColor | CSS color | Success states and badges |
errorColor | CSS color | Error states and validation |
shadow | string | Elevation — "low" or "none" (presets set this) |
colorScheme | light · dark · auto | Color mode — auto follows system preference |
labels | above · floating | Field label placement |
disableAnimations | boolean | Disable motion / transitions when true |
Legacy alias
theme: { primaryColor, fontFamily, borderRadius } on mount config is
deprecated — use appearance directly.
appearance.variables — design tokens
Fine-grained tokens map to CSS custom properties inside the checkout iframe:
| Variable key | CSS custom property | Typical use |
|---|---|---|
colorPrimary | --wj-color-primary-500 | Primary accent |
colorBackground | --wj-color-bg-surface | Surface background |
colorText | --wj-color-text-primary | Body text |
colorTextSecondary | --wj-color-text-secondary | Muted text |
colorTextPlaceholder | --wj-color-text-tertiary | Placeholder text |
colorDanger | --wj-color-text-danger | Errors |
colorSuccess | --wj-color-text-success | Success |
fontFamily | --wj-font-family-sans | Font stack |
fontSizeBase | --wj-font-size-base | Base font size |
fontWeightNormal | --wj-font-weight-normal | Body weight |
fontWeightMedium | --wj-font-weight-medium | Medium weight |
fontWeightBold | --wj-font-weight-bold | Bold weight |
spacingUnit | --wj-spacing-unit | Base spacing unit |
borderRadius | --wj-radius | Corner radius token |
spacingGridRow | --wj-spacing-grid-row | Vertical grid gap |
spacingGridColumn | --wj-spacing-grid-column | Horizontal grid gap |
Flat keys like primaryColor and variables.colorPrimary can both apply — prefer
variables for token-level control.
appearance.rules — selector overrides
Target internal checkout classes with CSS declarations:
appearance: {
rules: {
'.Input': { borderRadius: '8px', borderColor: '#cbd5e1' },
'.Label': { fontWeight: '500', fontSize: '14px' },
'.Tab': { padding: '12px 16px' },
},
}Property names use camelCase — they are converted to kebab-case CSS (e.g. borderRadius →
border-radius). Use selectors that match the checkout DOM (.Input, .Label, .Tab,
.AccordionHeader, etc.).
Live updates
JavaScript (CheckoutInstance / ComponentInstance)
// Hosted checkout instance
checkout.update({ appearance: { primaryColor: '#0f172a' } });
checkout.update({ locale: 'en' });
checkout.update({ currency: 'USD' }); // when multi-currency enabled on session
// Payment field component
card.update({ appearance: { primaryColor: '#0f172a' } });
card.update({ layout: 'tabs' });CheckoutEmbed live props
In React, Vue, and Svelte, payment field components (CardComponent,
PaymentComponent, etc.) call instance.update() when
appearance, locale, or layout props change.
CheckoutEmbed only remounts when sessionId changes —
for live hosted-checkout updates, keep a ref to the instance and call
checkout.update() yourself, or remount with a new key.
Locale
wajub.mount('#checkout', { sessionId, locale: 'fr' });
checkout.update({ locale: 'en' });Supported: fr · en · es · pt · ar (RTL).
Session default locale applies when omitted. Server-side branding can also set default locale — see Branding & theming.
Layout (payment method display)
wajub.mount('#checkout', { sessionId, layout: 'tabs' });| Value | Description |
|---|---|
classic | Vertical list (default) |
compact | Compact list |
tabs | Tabs by category |
accordion | Collapsible sections |
Session default (checkout_layout / dashboard branding) applies when you omit layout.
component.update({ layout }) on payment fields posts the change to the iframe.
checkout.update({ layout }) on hosted checkout updates local config; for full layout
changes in embed mode, remount or change sessionId if the session layout is fixed server-side.
Display currency
When multi-currency is enabled on the session:
checkout.update({ currency: 'USD' });Loading placeholder
Before onReady, hosted checkout shows a loading state:
| Option | Default | Description |
|---|---|---|
loadingText | — | Custom placeholder text |
showLoading | true | Show / hide the placeholder |
Framework examples
<CheckoutEmbed
sessionId={sessionId}
className="rounded-xl border"
style={{ maxWidth: 640 }}
minHeight={520}
appearance={{ theme: 'stripe', primaryColor: '#6366f1', labels: 'floating' }}
layout="tabs"
locale="fr"
onReady={(instance) => { checkoutRef.current = instance; }}
/>function applyDarkMode(dark: boolean) {
checkoutRef.current?.update({
appearance: { colorScheme: dark ? 'dark' : 'light' },
});
}<CheckoutEmbed
:session-id="sessionId"
:appearance="{ primaryColor: '#6366f1' }"
layout="tabs"
locale="fr"
:min-height="520"
/>Framework-only props
| Prop | Packages | Description |
|---|---|---|
className / class | React, Svelte / Vue | Wrapper CSS class |
style | React | Wrapper inline styles |
minHeight | All | Container min-height in px (default 480) |
onInstance | React ComponentEmbed | Callback with ComponentInstance ref |
Server vs client styling
| Source | When to use | Scope |
|---|---|---|
| Dashboard / API branding | Merchant-wide defaults, logo, white-label | All sessions for that account |
Client appearance | Per-page overrides, A/B tests, dark mode toggle | Single embed instance |
Client appearance merges on top of session branding inside the iframe. See
Branding & theming for the full server-side field list and
white-label modes.