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

# Custom CSS

> Inject custom stylesheets into the Swish UI shadow DOM.

For changes that go beyond [design tokens](https://swish.app/docs/guides/customize/appearance/design.md), inject custom CSS into the Swish UI shadow DOM. Pass an array of CSS strings or URLs under `ui.css`.

```js theme={null}
window.SwishOptions = {
  ui: {
    css: [".swish-drawer-header { border-bottom: 2px solid #e5e7eb; }"],
  },
};
```

You can also reference an external stylesheet hosted on your store:

```js theme={null}
window.SwishOptions = {
  ui: {
    css: [new URL("/swish-overrides.css", location.origin)],
  },
};
```

> [!WARNING]
>
> Custom CSS targets elements inside the shadow DOM. Class names and structure
> may change between Swish versions, so prefer design tokens when possible.

## Placement-level CSS

You can also inject CSS scoped to a specific placement using the `css` property on `swish.placements.create()`:

```js theme={null}
swish.placements.create({
  id: "styled-save-button",
  target: { selector: ".product-card" },
  mount: { mode: "append" },
  element: { name: "save-button" },
  css: `[swish-placement-element="styled-save-button"] { opacity: 0; transition: opacity 0.2s; }
    .product-card:hover [swish-placement-element="styled-save-button"] { opacity: 1; }`,
});
```

The `css` you pass is applied in two places, so both light-DOM and shadow-DOM selectors work in the same block:

* **On the page** — where the documented `[swish-placement-element="<id>"]` selector matches the placement's wrapper element, and parent selectors like `.product-card:hover [swish-placement-element="<id>"]` can reach across ancestors. This is the selector to reach for, and it is inherently scoped to the one placement.
* **Inside the button's shadow DOM** — where `:host` and the component's own internal selectors reach the button itself, which page-level CSS cannot cross into.

```js theme={null}
swish.placements.create({
  id: "rounded-save-button",
  target: { selector: ".product-card" },
  mount: { mode: "append" },
  element: { name: "save-button" },
  // `:host` and `.button` reach inside the component's shadow DOM.
  css: `:host { display: block; }
    .button { border-radius: 999px; }`,
});
```

> [!WARNING]
>
> Internal selectors such as `.button` are **not** scoped to the placement when
> they match at the page level. Prefer `[swish-placement-element="<id>"]` for
> anything the page can target, and reserve `:host` / internal selectors for
> styling the component itself. Internal class names and structure may change
> between Swish versions.

## Further reading

* [Design](https://swish.app/docs/guides/customize/appearance/design.md) for the design token API
* [Placements](https://swish.app/docs/guides/customize/placements/overview.md) for placement-level styling


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