> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shoppex.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Appearance

> Match the Elements checkout to your page with appearance values, and what custom CSS may change.

The block uses your shop's checkout design from the **Style Center**. Each page can change a small set of values on top of it with `appearance`: colour mode, colours, font, size, radius and density. The block checks every value. It never takes raw CSS from your page.

```html theme={"system"}
<div
  data-shoppex-element="checkout"
  data-shoppex-shop-id="YOUR_SHOP"
  data-shoppex-product-id="YOUR_PRODUCT_ID"
  data-shoppex-mode="test"
  data-shoppex-appearance='{"mode":"dark","colors":{"accent":"#22C55E"},"radius":10}'
></div>
```

With `Shoppex.mount`, pass `appearance` as an object, and call `update({ appearance })` to restyle the open block.

## Values

A key you leave out keeps the Style Center value.

| Key | Values | What it changes | Check |
| - | - | - | - |
| `mode` | `'light'`, `'dark'`, `'auto'` | Colour scheme. `auto` follows the buyer's system setting, also while the block is open. | One of the three |
| `transparent` | `true`, `false` | The block's background becomes transparent, so your page shows through. Cards keep their fill. | Boolean |
| `colors.accent` | Hex colour | Brand colour and the pay button. The button text becomes white or near-black, whichever reads better. | Button text contrast at least 4.5:1 |
| `colors.text` | Hex colour | Body text. | Contrast to the surface at least 4.5:1 |
| `colors.textMuted` | Hex colour | Secondary text. | Contrast to the surface at least 3:1 |
| `colors.surface` | Hex colour | Card and field surface. | Text contrast at least 4.5:1 |
| `colors.border` | Hex colour | Borders. | Hex |
| `colors.danger`, `colors.success`, `colors.warning` | Hex colour | Status colours. | Hex |
| `font` | `'inherit'`, a font name from the list below, or `{ google: 'Name' }` | Font family. | See [Fonts](#fonts) |
| `fontSize` | Whole number, 12 to 18 | Base font size in pixels. | Range |
| `radius` | Whole number, 0 to 24 | Corner radius of buttons and fields in pixels. Cards get 4 pixels more, up to 28. | Range |
| `density` | `'compact'`, `'comfortable'` | Spacing. | One of the two |

Hex colours are `#rgb` or `#rrggbb`. With `mode: 'auto'`, a colour must pass its contrast check in both light and dark.

### Fonts

* **A font from the list:** `Inter`, `Geist`, `Manrope`, `Plus Jakarta Sans`, `DM Sans`, `Space Grotesk`, `Sora`, `IBM Plex Sans`, `JetBrains Mono`, `Arial`, `System UI`.
* **A Google font:** `{ google: 'Source Serif 4' }`. Letters, digits, spaces, `+`, `-` and `_`, up to 60 characters. Shoppex builds the Google Fonts address.
* **`'inherit'`:** the script reads the first font family of the block's container and the block uses it if it is on the list above or on Google Fonts. A font your page loads from its own files is not available inside the frame. Then the block keeps the Style Center font and sends a warning.

## Values the block does not use

A value that fails its check is not applied. That key keeps the Style Center value, and your page gets a `warning` event once per key:

```json theme={"system"}
{
  "code": "appearance_value_rejected",
  "detail": { "key": "colors.accent", "value": "#FDE047", "reason": "contrast_too_low" }
}
```

| `reason` | Meaning |
| - | - |
| `unknown_key` | The key is not in the table above. |
| `invalid_value` | The value is not one of the allowed values. |
| `not_an_object` | `appearance` or `colors` is not an object. |
| `not_hex` | The colour is not `#rgb` or `#rrggbb`. |
| `not_integer` | The number is not a whole number. |
| `out_of_range` | The number is outside its range. |
| `contrast_too_low` | The colour fails its contrast check. |
| `invalid_font_name` | The font name has characters a font name cannot have. |
| `font_not_available` | Google Fonts does not have the font of your page (`font: 'inherit'`). |
| `page_font_unknown` | The block got `font: 'inherit'` without a font name, because the script could not read a font family from the container. |

`Shoppex.mount` and `update` refuse an appearance with a top-level key that is not in the table before anything reaches the block: `mount` reports `invalid_options`, and `update` logs the reason and changes nothing.

## Order of precedence

1. Your page's `appearance` sets the keys it names.
2. Everything else comes from the checkout design: once the buyer has an invoice, from the design saved with that invoice, before that from your shop's Style Center.
3. The Shoppex default fills what is still unset.

Card fields from the payment providers follow the same colours, font and radius where the provider supports it.

## Examples

**Light, with your brand colour:**

```html theme={"system"}
<div
  data-shoppex-element="checkout"
  data-shoppex-shop-id="YOUR_SHOP"
  data-shoppex-product-id="YOUR_PRODUCT_ID"
  data-shoppex-mode="test"
  data-shoppex-appearance='{"mode":"light","colors":{"accent":"#4F46E5"},"radius":8}'
></div>
```

**Dark:**

```html theme={"system"}
<div
  data-shoppex-element="checkout"
  data-shoppex-shop-id="YOUR_SHOP"
  data-shoppex-product-id="YOUR_PRODUCT_ID"
  data-shoppex-mode="test"
  data-shoppex-appearance='{"mode":"dark","colors":{"accent":"#22C55E"},"radius":10,"density":"compact"}'
></div>
```

**Transparent on a dark section of your page:**

```html theme={"system"}
<section style="background: #0B0B0F; padding: 24px">
  <div
    data-shoppex-element="checkout"
    data-shoppex-shop-id="YOUR_SHOP"
    data-shoppex-product-id="YOUR_PRODUCT_ID"
    data-shoppex-mode="test"
    data-shoppex-appearance='{"mode":"dark","transparent":true,"radius":12}'
  ></div>
</section>
```

## Custom CSS

`appearance` covers what most pages need. For more, add **Custom CSS** to your checkout design in the Style Center. It applies to the hosted checkout, the Buy Button and Elements. Custom CSS is checked against an allowlist when you save, and again when the checkout renders.

**Selectors.** Every selector is exactly one slot, `[data-spx-slot="…"]`. It can add one state, `[data-state="…"]`, and one of `:hover`, `:focus-visible` or `:disabled`. No element names, IDs, classes or descendants. Each part of a comma list is checked on its own. Rules sit at the top level or inside one `@media` or `@supports` block.

```css theme={"system"}
[data-spx-slot="button.primary"]:hover {
  background-color: #4338CA;
}
```

**Properties you can set:** colours, backgrounds, borders and border radius, `box-shadow`, outlines, `font-family`, `font-weight`, `font-style`, `font-size` (12 to 64 pixels), `letter-spacing`, `line-height`, `text-transform`, `text-decoration`, padding, margin, gaps, and colour transitions. Every other property is refused.

**Never allowed**, on any slot: `position`, `inset` and `top`/`right`/`bottom`/`left`, `z-index`, `transform`, `translate`, `scale`, `rotate`, `content`, `clip`, `clip-path`, `mask` and its family, `filter`, `backdrop-filter`, `pointer-events`, `visibility`, `display`, `animation` and its family, `opacity` and `mix-blend-mode`. Each of them can hide, move, cover or fake the total or the pay button.

**Protected slots** take only `color`, `background-color`, `font-family`, `font-weight`, `font-style` and `font-size`. They are the parts a buyer relies on: the product title and price, the total, the pay buttons, payment methods, payment notices, the terms and the status screens. A text colour on a protected slot must be fully opaque.

A theme saved before these rules keeps working: the checkout leaves out the rules that break them, and the Style Center shows which ones.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.