CODE CRISPIES

@layer — Finally Control CSS Specificity Without `!important`

3 min read cssarchitecture

Every large CSS codebase eventually accumulates !important declarations. Bootstrap utilities use them. Tailwind's ! prefix exists for them. Frameworks add them defensively, then your overrides need their own !important, then someone else's reset wins anyway. Cascade layers stop the war.

The basic idea

@layer reset, base, components, utilities;

@layer reset {
  * { margin: 0; padding: 0; }
}

@layer base {
  body { font: 16px/1.5 system-ui, sans-serif; color: #1f2937; }
}

@layer components {
  .button { padding: .75rem 1rem; border-radius: 6px; }
}

@layer utilities {
  .mt-4 { margin-top: 1rem; }
}

The first line declares an order. Later layers always beat earlier layers, regardless of selector specificity. So an unstyled .mt-4 (one class) wins over .button.button-primary[data-state="active"] (huge specificity) — because it's in a layer declared later.

Anything outside layers wins over anything inside layers.

Why this changes everything

Before layers, the cascade was:

  1. !important
  2. inline styles
  3. id selectors
  4. class/attribute/pseudo-class selectors
  5. element selectors

You "won" by being more specific. The arms race: .btn.btn.btn-primarybody .btn.btn-primary!important → end of conversation.

With layers:

  1. !important (still nuclear)
  2. inline styles
  3. Unlayered styles
  4. Layers, in declared order (last wins)

Inside a layer, normal specificity still applies — but only against other rules in the same layer. Cross-layer comparisons obey the order. Predictable.

Real example: third-party + your overrides

/* In a single stylesheet */
@layer vendor, components, utilities, overrides;

@layer vendor {
  /* Bootstrap dump goes here */
  @import url("bootstrap.css");
}

@layer components {
  .card { background: #fff; padding: 1.5rem; }
}

@layer utilities {
  .p-0 { padding: 0; }
}

@layer overrides {
  .card { background: #f3f4f6; }
}

Your .card override in the overrides layer beats Bootstrap's, without needing !important or higher specificity. Even Bootstrap's .card.card-primary[data-bs-toggle] loses, because the layer order said so.

Three patterns I keep using

1. Reset that doesn't fight everything else

@layer reset, *;

@layer reset {
  * { margin: 0; padding: 0; box-sizing: border-box; }
}

The * in the layer-order means "every other layer goes after reset." Reset rules sit at the bottom, every named or unnamed layer wins.

2. Tailwind-style utilities that always win

@layer base, components, utilities;

@layer utilities {
  .text-center { text-align: center; }
  .hidden { display: none; }
}

Now .hidden works without the Tailwind ! prefix or !important. It's just last in the order.

3. Theming

@layer theme.light, theme.dark;

@layer theme.light {
  :root { --bg: white; --text: #111; }
}

@layer theme.dark {
  [data-theme="dark"] { --bg: #111; --text: #fafafa; }
}

Dot-notation creates sublayers. Useful for organization; works the same as flat layers for ordering.

Caveats

Browser support (2026-05)

Caniuse: all major browsers since Q1 2022. Chrome 99, Safari 15.4, Firefox 97. Three years of universal support.

What this kills

I removed every !important from a 2k-line stylesheet last quarter using nothing but cascade layers and shorter selectors. The cascade became readable again.


Hands-on CSS practice on Code Crispies — see the css-fundamentals module for selectors and specificity exercises with live preview.