Examples

Show me, do not merely explain

Principles matter. Examples end arguments. These before and after patterns show what architectural improvement looks like in real CSS, not only in confident documentation.

Deep selectors to shallow ownership

Before

Before, CSS code example
.page .content .card .header .title {
    margin-bottom: 1rem;
}

After

After, CSS code example
.product-card > .title {
    margin-block-end: var(--space);
}

Deep selectors couple CSS to markup structure. Short scoped selectors make ownership obvious and safe to change.

Utility overload to semantic components

Before

Before, HTML code example
<article class="p-l m-b-xl bg-dark text-light radius-m grid gap-m">
    ...
</article>

After

After, HTML code example
<article class="product-card product-card--featured">
    ...
</article>

Repeated utility stacks usually mean a component is trying to exist. Name it once instead of explaining it forever.

State disguised as modifiers

Before

Before, CSS code example
.button--loading {}
.button--active {}
.button--disabled {}

After

After, CSS code example
.button {}
.button.is_loading {}
.button.is_disabled {}

Permanent reusable variants are modifiers. Temporary UI behaviour should be visible as state.

Legacy migration example

Do not move old CSS into new components and call it progress. Create a legacy layer first, then improve active work safely.

CSS code example
@layer legacy, settings, base, utilities,
layout, components, theme, hacks;

Legacy should stay visible and low priority, not quietly spread.

Temporary fixes becoming permanent residents

If a hack will still exist in six months, it is probably a real fix pretending to be temporary.

CSS code example
@layer hacks {
    .checkout-banner {
        margin-top: -3px;
    }
}

Keep hacks visible. Hidden hacks become architecture by accident.

Next useful pages