Skip to content

Type to search the docs, API, and blog.

↑↓ navigate↵ openesc close
Zazz 0.7 alpha
API navigation

API

Cascade layers

Layer order decides what wins, so nothing in the kit needs specificity tricks.

The kit declares its layers once, in base/_layers.css, and every stylesheet writes into one of them:

@layer variables, reset, defaults, vendors, legacy, ui, overrides;

@layer legacy {
  @layer imports, components, utilities, migrations;
}

@layer ui {
  @layer components, plugins, utilities;
}
LayerHolds
variablestokens and every --ui-* hook default
resetthe element reset and the typography roles
defaultsa tier written without its base (--px--md: 8 alone), so anything above that sets the property keeps its value
vendorsthird-party CSS you import (Embla, a map widget)
legacy.*an existing app's stylesheets during a migration, in the order they used to cascade
ui.componentsthe primitives
ui.pluginskit additions that extend a primitive
ui.utilitiesstyle utilities and switches, at zero specificity
overridesyour rules; they beat everything above

A later layer wins regardless of selector specificity, so a utility beats a primitive rule without !important, and a one-line rule in overrides beats a utility. Never import a stylesheet into bare legacy or ui: un-sublayered rules form an implicit final sublayer that outranks the named ones.

Importing your own CSS

@import "./brand.css" layer(overrides);
@import "./old-app.css" layer(legacy.imports);

Unlayered CSS outranks every layer, so the kit keeps nothing unlayered. Import a legacy stylesheet into legacy.* rather than leaving it bare; left bare, it keeps winning over the kit until you move the rules.