Modern CSS Techniques

CSS custom properties, clamp(), and modern layout patterns


Modern CSS Techniques

CSS has evolved significantly. These modern features make styling more maintainable and powerful.

Custom Properties (CSS Variables)

:root {
    --color-primary: #3b82f6;
    --color-text: #1f2937;
    --spacing-md: 1rem;
    --radius: 8px;
}

.button {
    background: var(--color-primary);
    color: white;
    padding: var(--spacing-md);
    border-radius: var(--radius);
}

/* Override for dark mode */
@media (prefers-color-scheme: dark) {
    :root {
        --color-primary: #60a5fa;
        --color-text: #e5e7eb;
    }
}
CSS

Scoped Variables

.card {
    --card-padding: 1.5rem;
    padding: var(--card-padding);
}

.card.compact {
    --card-padding: 0.75rem;
}
CSS

The clamp() Function

clamp(min, preferred, max) creates fluid values:

.container {
    width: clamp(320px, 90%, 1200px);
    /* At least 320px, prefers 90% of parent, max 1200px */
}

h1 {
    font-size: clamp(1.5rem, 2.5vw + 1rem, 3.5rem);
}

.spacing {
    padding: clamp(1rem, 3vw, 3rem);
}
CSS

Container Queries

Style elements based on their container size, not the viewport:

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

@container (min-width: 400px) {
    .card {
        display: flex;
        gap: 1rem;
    }
}

@container (min-width: 600px) {
    .card {
        font-size: 1.1rem;
    }
}
CSS

Logical Properties

Write CSS that works for any text direction (LTR, RTL):

/* Instead of: */
margin-left: 1rem;
padding-right: 2rem;
border-top: 1px solid;

/* Use: */
margin-inline-start: 1rem;
padding-inline-end: 2rem;
border-block-start: 1px solid;
CSS

The :has() Selector

Style a parent based on its children:

/* Style a card differently if it contains an image */
.card:has(img) {
    grid-template-rows: 200px 1fr;
}

/* Style a form group when its input is focused */
.form-group:has(input:focus) {
    border-color: var(--color-primary);
}

/* Style a nav link when it contains the current page marker */
nav:has(.active) {
    border-bottom: 2px solid var(--color-primary);
}
CSS

Nesting

Native CSS nesting (no preprocessor needed):

.card {
    background: white;
    border-radius: 8px;

    & .title {
        font-size: 1.25rem;
        font-weight: bold;
    }

    & .body {
        color: #666;
    }

    &:hover {
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    }

    @media (max-width: 768px) {
        padding: 1rem;
    }
}
CSS