Layers

Everything Havelcss ships sits in a cascade layer. That one decision is why you never have to fight it: your own rules win without !⁠important and without out-specifying anything.

The stack

Strongest first. Whatever is higher up overrides what is below it:

  1. Your rules — anything outside a layer
  2. havelcss.utilities — [hidden], .sr-only, .ellipsis, .skip-link
  3. havelcss.components — dialog, popover, tooltip, cards, the class-based variants
  4. havelcss.elements — the bare HTML elements
  5. havelcss.base — box-sizing, focus ring, responsive media
  6. havelcss.tokens — the custom properties everything else reads

The declaration itself lists them the other way round, weakest first, because that is the order the cascade reads:

@layer havelcss.tokens, havelcss.base, havelcss.elements, havelcss.components, havelcss.utilities;

Unlayered always wins

A layered rule loses to an unlayered one whatever its specificity, and however the two are ordered in the file. So this is enough, no matter how Havelcss happens to select that button:

button {
	border-radius: 0;
}

That is the whole contract. You do not need to know Havelcss' selectors, you do not need to be more specific than them, and you never need !⁠important to get past them.

Slotting in your own layers

If your project uses layers of its own, put them where you want them. A @layer statement is allowed in front of the imports, which is the place for it:

@layer havelcss.tokens, havelcss.base, havelcss.elements, app.theme, havelcss.components, havelcss.utilities;
@import 'havelcss';

Repeat the whole order there, with your layer in between. A shortened list looks tempting but does the opposite of what it says:

/* does not work */
@layer havelcss.elements, app.theme, havelcss.components;

A layer is ordered by where it is first seen. The short list fixes the three layers it names. The two it leaves out, tokens and base, are then appended behind them, so havelcss.base would end up overriding havelcss.components instead of losing to it.

Single modules bring the order along

Every module repeats the full declaration, so picking one file out of styles/ keeps the order intact and you can import them in any sequence. There is no separate file to remember, and nothing breaks quietly when a module arrives first or alone.

The one exception

@property registrations are global by definition. Layers do not apply to them at all, which is why the registered defaults in properties.css sit outside the stack above.