Get started
Cascade layers
How LUZ sits in your cascade: one layer called luz, the order to declare, and how to override it with no !important.
Declare the order first
All of LUZ's CSS is inside one cascade layer, luz. Put it between your reset and your own styles, and declare that order before any stylesheet loads.
@layer reset, luz, app;
- The order of layers is the order in which their names first appear. A statement like this one, before everything else, fixes it.
- In HTML, put it in a
<style>before the<link>elements. In a stylesheet, make it the first line, before any@importof LUZ. - A later layer wins over an earlier one. So
appwins overluz, andluzoverreset. - You do not have to use these names. Use whatever layers you have:
luzis the only name LUZ adds.
Layers, and names with a dot such as luz.components, work in every current browser and have been available since March 2022 (MDN).
What is inside luz
Tokens, core and catalog put their rules in their own layers inside luz. They are listed here from first to last: a layer lower in the table wins over the ones above it.
| Layer | Package | What it holds |
|---|---|---|
luz.tokens | tokens | The --luz-* custom properties |
luz.themes | core | Your own looks (only custom properties; make one). LUZ ships none: its default look is in luz.tokens |
luz.settings | core | Z-index, layout and field text settings |
luz.generic | core | The reset |
luz.elements | core | Bare HTML elements, at specificity 0 |
luz.objects | core | Layout objects: .o-* |
luz.components | core | The components: .luz-* |
luz.utilities | core | Single-purpose helpers: .u-*. They win over components by order, not by !important |
luz.catalog | catalog | The catalog components, one stylesheet each: <luz-search>, <luz-cookie-consent>, <luz-theme-time>, <luz-lang-switch>, <luz-submenu>, <luz-announcement>, <luz-timeline> and their .luz-<tag>__* classes, the navbar, the sidebar and the terminal (.luz-navbar, .luz-sidebar, .luz-terminal), and the patterns of a kind of site, each named by its block: .luz-hero, .luz-site-header, .luz-page-rail and the others |
luz.print | core, catalog | What changes on paper, inside @media print: Print styles. Last, so it wins over the screen styles of every package |
The patterns of a kind of site used to have a layer each: luz.landing, luz.cms, luz.app and luz.docs. Those layers do not exist now, because their patterns are components of catalog. If your own @layer statement names one, remove it.
Every file LUZ publishes repeats the order of this list first, so it is the same whichever file a page loads first. These names are public: renaming one is a breaking change.
CSS without a layer wins
Styles that are not in any layer win over every layer, whatever the order in the source. So a plain rule of yours beats luz, and it also beats your own app layer.
- If your CSS is not in layers at all, nothing changes for you: it already wins over LUZ, with no
!important. - If you use layers, keep your rules in one: a plain rule that you forgot to put in a layer will override your own layers.
- A plain rule is the one place a layer order does not help. Put an override in
appor in no layer at all, and know which one you chose.
Override LUZ
Three overrides, from the smallest. Each wins over LUZ because app comes after luz.
@layer reset, luz, app;
@layer app {
/* A token: every component that reads it follows */
:root {
--luz-brand-fill: #0b5a8c;
}
/* A component: your rule, in your layer */
.luz-btn {
min-height: 3rem;
}
/* A catalog component */
luz-announcement {
font-size: 1rem;
}
}
- Prefer tokens. A token changes every component that reads it, in the mode it is set for. Check the colors you set with the contrast check.
- No
!importantand no longer selectors are needed: layer order decides first, and specificity only counts inside one layer. - Keep a color override in the right mode:
:rootinappwins over LUZ's dark mode too. Set the token per mode, for example in[data-theme="dark"].
Why one container layer
LUZ's layers used to be six top-level names: settings, generic, elements, objects, components and utilities. They are short and common, and other tools use some of the same names.
A page that loaded one of them next to LUZ merged its components or utilities with LUZ's, and the order between them was an accident.
- Inside
luz, LUZ's layer names cannot meet yours. - One name orders all of LUZ: you place
luzonce, and you do not have to know what is inside. - It works from a
<link>or a CDN, where a layer cannot be added from the outside.
You can still put your own layer between two of LUZ's by naming them in the first statement: @layer luz.components, mine, luz.utilities;.
Loading with @import
With a bundler that resolves package names, or with paths to the files, load them as they are. Do not add layer(luz) to the import: the files already declare their layers inside luz, and wrapping them would nest the names as luz.luz.components.
@layer reset, luz, app;
@import url("@luz-ds/tokens/css");
@import url("@luz-ds/core/css");
@import url("@luz-ds/catalog/components/search.css"); /* one per catalog component the page uses */
@import url("@luz-ds/catalog/components/hero.css"); /* a pattern of a kind of site is a catalog component too */
Your own stylesheet imports a file after the statement, so the order is set before LUZ loads.