Understanding CSS Architecture: Part 3 - Modern Features

Part 3 of the series

CSS Architecture

Futuristic CSS code visualization

Modern CSS features are revolutionizing how we architect stylesheets. Features that previously required JavaScript or complex workarounds are now native to CSS.

Container Queries#

Container queries let components respond to their container's size, not just the viewport:

CSS
.card-container {
    container-type: inline-size;
    container-name: card;
}

.card {
    display: grid;
    gap: var(--space-sm);
}

/* When container is wide enough */
@container card (min-width: 400px) {
    .card {
        grid-template-columns: 200px 1fr;
    }
}

@container card (min-width: 600px) {
    .card {
        grid-template-columns: 300px 1fr;
        gap: var(--space-lg);
    }
}

This enables truly reusable components that adapt to any context.

The :has() Selector#

The :has() selector (parent selector) unlocks new patterns:

CSS
/* Style card differently when it has an image */
.card:has(img) {
    padding-top: 0;
}

/* Style form groups with invalid inputs */
.form-group:has(:invalid) {
    --input-border: var(--color-error);
}

/* Adjust layout when sidebar is present */
.layout:has(.sidebar) {
    grid-template-columns: 250px 1fr;
}

/* Style label when checkbox is checked */
label:has(input:checked) {
    font-weight: bold;
}

CSS Nesting#

Native CSS nesting reduces repetition:

CSS
.card {
    padding: var(--space-md);
    background: var(--color-surface);

    & .title {
        font-size: var(--text-lg);
        font-weight: bold;
    }

    & .body {
        color: var(--color-muted);
    }

    &:hover {
        box-shadow: var(--shadow-lg);
    }

    @media (min-width: 768px) {
        padding: var(--space-lg);
    }
}

Cascade Layers#

Layers give explicit control over cascade priority:

CSS
@layer reset, base, components, utilities;

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

@layer base {
    a { color: var(--color-link); }
}

@layer components {
    .btn { /* ... */ }
}

@layer utilities {
    .hidden { display: none; }
}

Layer order in the @layer statement determines priority—later layers override earlier ones.

Logical Properties#

Write direction-agnostic styles:

CSS
/* Old way - direction-specific */
.card {
    margin-left: 1rem;
    margin-right: 1rem;
    padding-top: 2rem;
    padding-bottom: 2rem;
}

/* New way - logical properties */
.card {
    margin-inline: 1rem;
    padding-block: 2rem;
}

This improves internationalization support automatically.

Subgrid#

Align nested grids to parent tracks:

CSS
.grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-md);
}

.grid-item {
    display: grid;
    grid-template-rows: subgrid;
    grid-row: span 3;
}

Architectural Implications#

These features change how we architect CSS:

  1. Fewer wrapper divs - :has() and container queries reduce structural markup
  2. More encapsulated components - Container queries make components truly portable
  3. Simpler specificity - Layers give explicit cascade control
  4. Less JavaScript - Many interactions now possible in pure CSS

Browser Support#

Check browser support before using:

  • Container Queries: All modern browsers
  • :has(): All modern browsers
  • Nesting: All modern browsers
  • Cascade Layers: All modern browsers

Conclusion#

Modern CSS features enable simpler, more maintainable architectures. Embrace these features to write less code that does more.

This concludes our CSS Architecture series. Happy styling!

Share:

Related Articles