Skip to main content

Get started

How LUZ is organised

Packages that depend in one direction, CSS in cascade layers inside one called luz, and one optional script.

Package boundaries

Each package depends on the ones above it in this list, never on the ones below.

The name stands for Light, Usable & Zero-dependency: light in weight (plain CSS and ES modules, nothing to build for the people who use it), usable by everyone (native HTML, three color modes, tested for accessibility), and with zero runtime dependencies.

@luz-ds/tokens   -> primitive and semantic tokens (standalone)
      ↓ required by
@luz-ds/core     -> components, objects, bare-element styles, optional JS
      ↓ required by
@luz-ds/catalog     -> search, cookie-consent, theme-time, lang-switch, submenu, announcement, and the patterns of a landing page, a blog or newspaper, a web application and a documentation site
  • The catalog needs core and tokens; core needs tokens; tokens needs nothing.
  • Tokens, core and catalog share one version. There are no packages for one kind of site: the patterns of a landing page, a blog, an application or a documentation site are components of the catalog, one file each.
  • The packages say so as peer dependencies. The core and catalog scripts warn in the console when a level is missing.

The documentation follows the packages, with one area more: Kinds of site puts together, for each kind, the prompt for an LLM and the recipes of its parts, made of the packages above and of the patterns of that kind in the catalog.

What each package needs

Find the part you want, and install the package of its row and the ones below it.

Which package holds each part of a page
PieceClasses or attributesPackageNotes
Color modes, semantic tokens, ET Book
--luz-*, data-theme
tokens
Nothing else is needed
Reset and styles of bare HTML elements
h1, p, a, ul…
core
In base.css and luz.css
Components
.luz-btn, .luz-field, .luz-card, .luz-table, .luz-tabs…
core
Also one file each, in components/
Modal
.luz-modal on a <dialog>
core
The script is a fallback for browsers without command and commandfor
Layout objects
.o-container, .o-grid, .o-stack, .o-media
core
Spacing comes from the space tokens
An app layout with a sidebar column
.o-shell, .o-main
core
A plain <footer> as a direct child of .o-shell goes across the bottom; its look is yours, or a kind of site's footer
A page with no sidebar, a sticky bar, an action group
.o-page, .o-sticky, .o-actions
core
Instead of .o-shell, for a page with no sidebar: the page and its bars
Color mode: Auto, light, dark and high contrast
<luz-theme-mode>
core
luz.js loads its script, theme-mode.js, when the page has one; without it the radios still work and Auto follows the system: Color mode
Skip link, band, image frame
.luz-skip-link, .luz-band, .luz-image
core
The image frame keeps a ratio and crops the picture to it; with no picture it is a flat surface
The header, hero, sections and footer of a landing page
.luz-site-header, .luz-hero, .luz-main, .luz-section, .luz-stat, .luz-site-footer, .luz-glow
catalog
One file each, components/<block>.css. On core's objects (.o-page, .o-sticky, .o-container, .o-grid--split) and the catalog's navbar. A feature grid is ul.o-grid.o-grid--split, core's
The header, page header, article header, table of contents and footer of a blog or a newspaper
.luz-site-header (--publication), .luz-masthead, .luz-page-header, .luz-article-header, .luz-article, .luz-toc, .luz-site-footer
catalog
One file each, components/<block>.css; the table of contents is in article.css. On core's objects and the catalog's navbar. Post cards, listings and the author box are core's card: see Blog or newspaper
The header and the dashboard of a web application
.luz-app-bar (__product, __actions, __account), .luz-dashboard (__head, __title, __panel)
catalog
One file each, components/app-bar.css and components/dashboard.css. On core's shell, sticky bar, grid and card, and the catalog's sidebar. No script. See App header and Dashboard
The shell, page head, rail, example, do and don't, pager and page foot of a documentation site
.luz-docs-layout, .luz-doc-header, .luz-page-rail, .luz-example, .luz-do-dont, .luz-pager, .luz-page-footer
catalog
One file each, components/<block>.css. On core's shell, code block and tables, and the catalog's sidebar. No script. See Shell
The links of a header
.luz-navbar
catalog
One file, components/navbar.css. A popover panel at 768 px and below, opened by a .luz-nav-toggle, with no script. luz.css does not include it
A sidebar, its brand and its menu button
.luz-sidebar (__brand, __logo, __brand-name, __version), .luz-nav-toggle
catalog
One file, components/sidebar.css. The drawer is a native popover and needs no script. catalog.js loads sidebar.js, the scroll spy, when the page has a sidebar; a page that loads only core has no scroll spy
A command in a framed block
.luz-terminal
catalog
One file, components/terminal.css. No script of its own: the copy button is core's
A timeline of dated events
<luz-timeline>, .luz-timeline
catalog
catalog.js loads its script, timeline.js, when the page has one; without it the timeline is a list
Submenu, announcement
<luz-submenu>, <luz-announcement>
catalog
Tags with no script and no class: the submenu is a native <details> in a header's links, the announcement a <section>
Cookie consent
<luz-cookie-consent>, .luz-cookie-consent
catalog
catalog.js loads its script, cookie-consent.js, when the page has one; a band fixed at the bottom of the window; without the script it stays hidden
Color mode with the time of day, and the slider of the day
<luz-theme-time>
catalog
catalog.js loads its script, theme-time.js, when the page has one, and theme-time-bar.js for a variant="bar"; without them core's radios still work and Auto follows the system
Language switch
<luz-lang-switch>
catalog
No script
Site search
<luz-search>, .luz-search
catalog
Needs the script (catalog.js, which loads search.js when the page has one) and an index file; without them it is a link
Print styles
Nothing to add
core
In luz.css; catalog adds its own print rules
A zone in a page that already has a design
data-luz
core
luz.conditional.css, instead of luz.css
Checking what you or an AI agent wrote
npx @luz-ds/check@0.3.0, the luz-check command
check
A tool with no CSS and no layer, and no other package needed: it reads your HTML and CSS offline. See Working with AI
  • Two ways to lay out a page, both core's. .o-shell with .o-main: a sidebar column beside the main area. .o-page: a header, the content and a footer in one column. Pick one for the grid of the page: the first when it has a sidebar, the second when it has none. A landing or CMS header and footer work with both; these docs use .o-shell.
  • The catalog needs core, and core needs tokens, so a row at a level also needs every package under it. The patterns of a landing page, a blog, an app and a documentation site are catalog components, so they need core and tokens too.

CSS layers

Core's CSS comes in native cascade layers (@layer), in ITCSS order, inside one container layer called luz. The six below are the ones that hold its rules; the layers page lists them all, with tokens, catalog and print.

A later layer wins over an earlier one, and any CSS of yours that is not in a layer wins over all of LUZ, with no !important. How to order and override them.

packages/core/src/
  settings/_settings.css      luz.settings    z-index, layout widths, field text
  generic/_reset.css          luz.generic     the reset
  elements/*.css              luz.elements    bare HTML elements, zero specificity
  objects/_objects.css        luz.objects     layout: .o-*
  components/*.css            luz.components  the components: .luz-*
  utilities/_utilities.css    luz.utilities   single-purpose helpers: .u-*
  • The components layer holds 29 components.
  • dist/luz.css holds these six layers and luz.print. Tokens are in luz.tokens, catalog, with the navbar, the sidebar, the terminal, the timeline and the patterns of a kind of site, in luz.catalog; luz.themes is empty, kept for a look of your own. For a page that needs a few components only, load dist/base.css (settings, reset and elements), then dist/components/<name>.css for each one.
  • Rules for bare elements are wrapped in :where(), so any class wins over them.

The script

One optional entry point, luz.js, starts every behaviour on the page: color mode, copy buttons, dialogs, highlighting, players and tabs.

HTML
<script type="module" src="https://cdn.jsdelivr.net/npm/@luz-ds/core@0.3.0/dist/luz.min.js"></script>

To load less, import one module and call its init function. See JavaScript modules.

Minimal page

HTML
<!doctype html>
<html lang="en" data-theme="light">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Sign up – Acme</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@luz-ds/tokens@0.3.0/dist/luz-tokens.min.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@luz-ds/core@0.3.0/dist/luz.min.css">
</head>
<body>
  <main class="o-container">
    <h1>Sign up</h1>
    <form action="/signup/" method="post">
      <div class="luz-field">
        <label class="luz-field__label" for="email">Email</label>
        <input class="luz-input" id="email" name="email" type="email" autocomplete="email" required>
      </div>
      <button class="luz-btn luz-btn--primary" type="submit">Create account</button>
    </form>
  </main>
</body>
</html>