# Themes

Source: https://iriscss.com/documentation/customize/themes/

Iris CSS follows the system light or dark setting. `data-theme` forces either one, on the page or on any element.

Every theme color is a `light-dark()` pair, and `:root` sets `color-scheme: light dark`. The browser picks the side that matches the user's setting, so dark mode needs no extra CSS. Add the `color-scheme` meta tag too, so the page background is right before the stylesheet loads.

```html
<meta name="color-scheme" content="light dark">
```

## Force a theme

Set `data-theme` on `<html>` to choose the theme for the whole page.

```html
<html lang="en" data-theme="dark">
```

## Theme one element

`data-theme` works on any element. The element repaints its text and background, and everything inside follows, nested themes included. The `.light` and `.dark` classes do the same.

```html
<div class="grid">
  <article class="card" data-theme="light">
    <h4>Light</h4>
    <p>Always light.</p>
    <button class="primary">Primary</button>
  </article>
  <article class="card" data-theme="dark">
    <h4>Dark</h4>
    <p>Always dark.</p>
    <button class="primary">Primary</button>
  </article>
</div>
```

## Theme toggle

A toggle only has to set `data-theme` and remember it. Read the saved value in the `<head>`, before the page paints, so it does not flash the wrong theme. This site uses the same script.

```html
<script>
  try {
    const theme = localStorage.getItem("theme");
    if (theme) document.documentElement.dataset.theme = theme;
  } catch {}
</script>

<button type="button" id="theme-toggle">Toggle theme</button>
<script>
  document.getElementById("theme-toggle").addEventListener("click", () => {
    const root = document.documentElement;
    const dark = root.dataset.theme
      ? root.dataset.theme === "dark"
      : matchMedia("(prefers-color-scheme: dark)").matches;
    root.dataset.theme = dark ? "light" : "dark";
    localStorage.setItem("theme", root.dataset.theme);
  });
</script>
```

## Your own theme colors

Override a theme color with your own `light-dark()` pair. A single color, without `light-dark()`, is used in both themes. A color set on `:root` reaches nested themes too. Browsers without `light-dark()` (Chrome before 123, Firefox before 120, Safari before 17.5) recompute colors on each nested theme, so there set it on `:root, [data-theme], .light, .dark` to cover them.

```css
:root {
  --i-color-background: light-dark(#fffdf7, #101418);
  --i-color-primary: light-dark(#6d28d9, #a78bfa);
  --i-color-primary-inverse: light-dark(#fff, #1e1b4b);
}
```

Each color family is a color and an `-inverse` color, the text that sits on top of it. Hover, border and focus colors are mixed from these two, so you never set them one by one. See [colors](https://iriscss.com/documentation/modifiers/colors/index.html.md) for the classes that use them.

## Variables

### Theme colors

| Variable | Default | Note |
| --- | --- | --- |
| `--i-color-text` | `light-dark(#373c44, #c2c7d0)` | Default colors |
| `--i-color-background` | `light-dark(var(--i-color-white), #13171f)` |  |
| `--i-color-light` | `var(--i-color-white)` | Light & dark colors |
| `--i-color-dark` | `var(--i-color-black)` |  |
| `--i-color-brand` | `light-dark(#b31fc6, #e12afb)` | Brand colors. The text ones reach 4.5:1 on the page and on tinted bands, such as the footer, in both themes. |
| `--i-color-brand-dark` | `#a800b7` |  |
| `--i-color-brand-light` | `#f4a8ff` |  |
| `--i-color-brand-name` | `light-dark(var(--i-color-brand-dark), #e47ef0)` |  |
| `--i-color-brand-accent` | `light-dark(#b31fc6, var(--i-color-brand-light))` |  |
| `--i-color-ink` | `light-dark(var(--i-color-black), var(--i-color-white))` | Mix targets. Hovers and colored text mix toward ink, tints mix toward paper |
| `--i-color-paper` | `light-dark(var(--i-color-white), #13171f)` |  |
| `--i-color-base` | `light-dark(#8e9fbc, #c2c7d0)` | Neutral color of buttons and links without a color class |
| `--i-color-focus` | `color-mix(in oklab, var(--i-color-base), var(--i-color-ink) 40%)` |  |
| `--i-color-primary` | `light-dark(#00d5be, #05cc47)` | Each family is a color and the text color used on top of it. Hover, border, focus and tint colors are derived where they are used. |
| `--i-color-primary-inverse` | `var(--i-color-slate-900)` |  |
| `--i-color-secondary` | `light-dark(#5d6b89, #525f7a)` |  |
| `--i-color-secondary-inverse` | `var(--i-color-white)` |  |
| `--i-color-contrast` | `light-dark(#1c2840, #eff1f4)` |  |
| `--i-color-contrast-inverse` | `light-dark(var(--i-color-white), var(--i-color-black))` |  |
| `--i-color-accent` | `#ffb900` |  |
| `--i-color-accent-inverse` | `var(--i-color-slate-900)` |  |
| `--i-color-info` | `var(--i-color-cyan)` |  |
| `--i-color-info-inverse` | `var(--i-color-slate-900)` |  |
| `--i-color-success` | `var(--i-color-green)` |  |
| `--i-color-success-inverse` | `var(--i-color-slate-900)` |  |
| `--i-color-warning` | `var(--i-color-yellow)` |  |
| `--i-color-warning-inverse` | `var(--i-color-slate-900)` |  |
| `--i-color-danger` | `var(--i-color-red-600)` |  |
| `--i-color-danger-inverse` | `var(--i-color-white)` |  |
| `--i-color-link` | `var(--i-color-blue-600)` |  |
| `--i-color-link-inverse` | `var(--i-color-white)` |  |
| `--i-variant` | `var(--i-color-base)` | Current color family. The color classes set it, buttons and links read it |
| `--i-variant-inverse` | `var(--i-color-paper)` |  |
| `--i-color-subtle` | `light-dark(#646b79, #848d9e)` | Subtle colors |
| `--i-color-subtle-border` | `light-dark(#e7eaf0, #202632)` |  |
| `--i-color-shadow` | `light-dark(#8191b5, #07090c)` | Box shadow, built from one color so it follows the theme |
| `--i-shadow` | `0.0145rem 0.029rem 0.174rem color-mix(in srgb, var(--i-color-shadow) 1.6%, transparent), 0.0335rem 0.067rem 0.402rem color-mix(in srgb, var(--i-color-shadow) 2.4%, transparent), 0.0625rem 0.125rem 0.75rem color-mix(in srgb, var(--i-color-shadow) 3.1%, transparent), 0.1125rem 0.225rem 1.35rem color-mix(in srgb, var(--i-color-shadow) 3.5%, transparent), 0.2085rem 0.417rem 2.502rem color-mix(in srgb, var(--i-color-shadow) 4.3%, transparent), 0.5rem 1rem 6rem color-mix(in srgb, var(--i-color-shadow) 5.9%, transparent), 0 0 0 0.0625rem color-mix(in srgb, var(--i-color-shadow) 1.6%, transparent)` |  |

### Selection and scrollbar

| Variable | Default | Note |
| --- | --- | --- |
| `--i-selection-color-background` | `light-dark(#05cc4740, #05cc4730)` |  |
| `--i-scrollbar-color-thumb` | `color-mix(in oklab, var(--i-color-subtle) 50%, transparent)` | Scrollbar |
| `--i-scrollbar-color-track` | `transparent` |  |
