Whakerexa > Getting started > CSS Variables

CSS Variables

Examples of use

Add a <style> element in the <head>, after the link to wexa.css. Because wexa uses @layer, your unlayered rules win automatically — no !important, no complex selectors needed.

Overrides in :root apply to all modes; overrides in .contrast apply only in contrast mode.

<style>
    :root {
        /* overrides apply to all modes */
        --border-width: 10px;
        --header-slidein: slideInFromBottom;
    }
    .contrast {
        /* overrides apply only in contrast mode */
        --border-width: 20px;
        --header-slidein: animDisabled;
    }
</style>

To override colors in light mode only, limit the selector so it does not match when .dark is active.

<style>
    :root:not(.dark) {
        --bg-color: rgb(250, 250, 240);
    }
    .dark {
        --bg-color: rgb(20, 18, 30);
    }
</style>

To create a full replacement theme, use @layer theme in a separate stylesheet loaded after wexa.css.

<!-- load after wexa.css -->
<link rel="stylesheet" href="theme_myapp.css" media="screen" />

Inside the theme file, use @layer theme to override defaults.

/* theme_myapp.css */
@layer theme {
    :root { --bg-color: rgb(245, 240, 230); }
    .dark  { --bg-color: rgb(30, 25, 20); }
}

Animations

A few ready-to-use animations are available:

Theme activation

The theme contract

A theme is loaded after wexa.css, and whatever it leaves undefined keeps the value wexa.css gives it. A theme is free to leave a whole group of variables alone: the default palette holds on its own. But a theme that defines one variable of a group answers for the group entire, in the two modes — a ground without the text laid on it, or a button without the color it takes under the pointer, leaves a page half dressed, and it is only seen in the mode nobody opened.

The themes of the framework are checked against this contract before every release: each group one of them touches is answered whole, in the two modes. A theme you write yourself is held to the same rule, and the groups it holds are listed below.

The groups, and what each one holds
GroupVariables
grounds--body-bg-color, --bg-color, --bg-color-alt
text--fg-color, --fg-color-alt
header--header-bg-color, --header-fg-color
nav--nav-bg-color, --nav-fg-color
footer--footer-bg-color, --footer-fg-color
buttons--buttons-bg-color, --buttons-bg-color-hover, --buttons-fg-color
accents--a-color, --li-color
borders--border-color, --border-color-alt
headings--h1-color to --h6-color
blockquote--blockquote-border-color, --blockquote-footer-color, --blockquote-bg-color, --blockquote-fg-color
table--table-border-color, --table-cell-bg-color, --table-row-stripped-bg-color, --table-head-bg-color, --table-head-fg-color, --table-caption-bg-color, --table-caption-fg-color
card--card-bg-color, --card-fg-color
dialog--dialog-bg-color, --dialog-fg-color
progress--progress-bg-color, --progress-fg-color
mark--mark-bg-color, --mark-fg-color
switch--switch-bg-color, --switch-slider-on-color, --switch-slider-off-color
custom pair--custom-color1, --custom-color2, which a component draws with and which contrast each other

What no group holds is read the same way in the two modes, and a theme gives it a value or does not: --img-bg-color, which keeps a light ground for an image whatever the mode, the sizes, and the colors of a state — --error-color and the ones beside it.

@layer base

Structural and typographic defaults. In contrast mode, font and spacing values are overridden by @layer accessibility — reflected in the "Contrast" column. An unlayered custom rule wins over both.

Layout
Variable name Default value Value in contrast view Value in dark view
fontsize-divisor 0.9
footer-height 20vh
header-height 60vh
size-divisor 0.8
Typography
Variable name Default value Value in contrast view Value in dark view
font-family-mono ui-monospace, 'DejaVu Sans Mono', 'Liberation Mono', 'Cascadia Mono', 'Segoe UI Mono', monospace
font-family-pre ui-monospace, 'DejaVu Sans Mono', 'Liberation Mono', 'Cascadia Mono', 'Segoe UI Mono', monospace
font-family-sans SansFont, Commissioner, 'Verdana', sans-serif ContrastFont, SansFont, 'Verdana', sans-serif
font-family-serif SerifFont, 'Noto Serif', 'Times New Roman', serif
font-size calc(16px / var(--fontsize-divisor)) calc(16px / var(--fontsize-divisor))
font-weight-black 750 800
font-weight-bold 600 750
font-weight-normal 400 500
font-weight-semibold 500 600
font-weight-semithin 300 400
font-weight-thin 200 300
hr-width 1px 2px
letter-spacing 0.04rem 0.12rem
line-height 1.2 1.5
outline-size 2px 3px
typography-spacing-horizontal calc(0.8 * 16px / var(--size-divisor)) calc(0.8 * 16px / var(--size-divisor))
typography-spacing-vertical calc(1.2 * 16px / var(--size-divisor)) calc(1.2 * 16px / var(--size-divisor))
word-spacing 0.06rem 0.16rem
Icons and outline
Variable name Default value Value in contrast view Value in dark view
checked-icon url("data:image/png
external-link-icon url("data:image/png
icon-contrast url("data:image/svg+xml
icon-theme url("data:image/svg+xml
input-search-icon url("data:image/png
outline-focus-style outset
outline-hover-style inset
outline-offset 0

@layer theme

Visual palette and decoration. The "Contrast" column shows values from the .contrast block within @layer theme. The "Dark" column shows values from the .dark block. An unlayered custom rule wins over all.

Borders and shape
Variable name Default value Value in contrast view Value in dark view
border-radius 3px 3px
border-width 1px 2px
dialog-border-radius 0.4rem 0.4rem
dialog-border-width 1px 2px
dialog-box-shadow -0.2rem 0.2rem 0.6rem 0.2rem rgba(128, 128, 128, 0.5)
table-border-width 1px 2px
Animation
Variable name Default value Value in contrast view Value in dark view
footer-slidein animDisabled animDisabled
header-slidein slideInFromBottom animDisabled
transition 0.4s ease-in-out

Print stylesheet

Print rules are in a dedicated print.css, loaded only when printing (media="print"). Add it to your page alongside wexa.css:

Because print.css is unlayered, it overrides all wexa layer rules automatically when printing.

<link rel="stylesheet" href="wexa_statics/css/wexa.css" media="screen" />
<link rel="stylesheet" href="wexa_statics/css/print.css" media="print" />

The following variables are reset for print:

Variable name Value in print
footer-slidein none
header-slidein none
transition none