Skip to content
V
For developers
Architecture, conventions, the core and security
Look and themes / SCSS structure

SCSS structure#

How the styles are divided, in what order they stack, and where to reach when building a new theme. Root: www/themes/<branch>/<theme>/desktop/assets/scss/.

The entry point and the order#

Everything starts in style.scss. The import order is binding — it decides who overrides whom:

@use "utilities";      // the whole of Bootstrap, self-hosted
@use "abstracts" as *; // tokens, functions, mixins  emits NO CSS at all
@use "base";           // reset, general styles, utility classes
@use "components";     // the system's UI components
@use "layout";         // header, footer, main, parts, sections
@use "modules";        // styles of Nette components, split per module
@use "custom";         //  the ONLY place for this theme's deviations
Layer What is in it Touch it?
utilities/ Bootstrap from node_modules no
abstracts/ tokens, functions, mixins (emits not one line of CSS) token values only
base/ reset, typography, skins, utility classes no
components/ buttons, cards, forms… — the shared design system no
layout/ structural parts of the page no
modules/ styles of Nette components, per module no
custom/ this theme's deviations yes, exclusively here

Deviations belong exclusively in custom/

Everything above it is a shared base other themes use too. An edit straight in components/ or base/ propagates to places nobody expects — and it surfaces only when an entirely different theme breaks.

Bootstrap: BOTH branches use it, but differently#

The front end does use Bootstrap — all of it

A widespread misconception. Front-end templates stand directly on its components: modal in forty templates, collapse and toast in twenty each, dropdown and offcanvas in fifteen each, carousel in nine. Hence the whole bundle, not a subset.

Front end Administration
Where from utilities/_bootstrap.scssnode_modules webpack → assets/dist/styles.css
What all of Bootstrap all of Bootstrap
When it loads first, before the theme before style.css (linked by _head.latte)
Why that way Bootstrap is the base, the theme overrides it the admin has its own components; utilities with !important must win

In the administration @use \"utilities\" is DELIBERATELY commented out

It added the grid and utility API a second time at the end. Measured, not guessed: removing it made style.css 79,857 B smaller and all 58 admin pages stayed pixel-identical. Do not restore it "for the sake of the cascade" — utilities carry !important, so they win from the first copy anyway.

Do not bring back the CDN link in either branch

Without an internet connection the styling would fall apart, and the version on a CDN changes under your hands. One source (node_modules), one version for both branches.

Your own display may override Bootstrap

A rule of the same specificity wins by order. Solve it with scope (nesting it under your own class), not with !important.

Tokens#

Two levels, each with its own job:

Level Where What for
Base abstracts/_vars.scss palette, typography, spacing, radii, shadows, z-index
Component next to the component itself the component's "local API" — what can be changed from outside
// components/_cards.scss — a token is the component's interface
.card {
  --card-bg: var(--color-surface);
  --card-radius: var(--border-radius);

  background: var(--card-bg);
  border-radius: var(--card-radius);
}

Never write a literal value into a component

A #2ecc8a inside a component means a new theme cannot be recoloured by changing a token. The value belongs in a token; the component reads the token.

A component token belongs in the component's scope

Not in :root. Then the code itself shows what the component offers — and a theme can override it without disturbing the others.

Component token values reference base tokens

--card-bg: var(--color-surface), not a concrete colour. Otherwise recolouring the palette only works halfway.

A new theme, step by step#

  1. Copy the skeleton from template1 — the whole of assets/scss/, layouts/, assets/js/.
  2. Rewrite custom/_vars-override.scss — only the tokens that differ from the system default (the primary colour with its full 100–900 scale, the typeface, the radius, section spacing).
  3. Sections into custom/sections/ — header, hero, footer; your theme's own look, not an edit of layout/.
  4. Page-level deviations into custom/pages/<module>/ — when one page behaves differently from the rest.
  5. Build it and walk the component catalogue — it shows everything the token change moved.

A new theme need not copy components

It inherits the whole design system and overrides only tokens. Reaching into components/ is almost always a sign that a token is missing — and adding one beats duplicating the component.

Building#

sass scss/style.scss css/style.css --style=compressed --watch

npx sass is not the same as sass

They are different compiler versions and can produce different output. Use the one the theme is normally built with.

Without a build, an SCSS change shows up nowhere

The site reads css/style.css, not the sources. A missing build looks like "my edit does not work" and nobody connects it with the fact that nobody compiled it.

Things to watch out for#

An older component may have no styles in a new theme

It looks like broken rendering, but the rules are simply absent. Before fixing anything, check in the catalogue whether the component was ever styled in the theme — otherwise you are fixing something that never worked and looking for the cause in the wrong place.

Design-kit classes are NOT theme classes

The design kit and the theme use different naming. A chunk of markup copied from the design will not pick up any styling — and missing styling looks exactly like a bug in the code. More in Design system.