Episode 11 of 12

The @Content Keyword

Pass custom style blocks into mixins with @content — powerful pattern for media queries and wrappers.

The @Content Keyword

@content lets you pass a block of styles into a mixin. The mixin defines the wrapper, and @content is replaced by whatever you pass inside the @include block.

How @content Works

// Define a mixin with @content placeholder
@mixin wrapper {
    .wrapper {
        max-width: 1200px;
        margin: 0 auto;
        padding: 0 20px;
        @content;  // ← Custom styles go here
    }
}

// Use it — pass styles in the { } block:
@include wrapper {
    background: #f5f7fa;
    min-height: 100vh;
}

// Compiled CSS:
.wrapper {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 20px;
    background: #f5f7fa;
    min-height: 100vh;
}

Media Query Mixin (Most Common Use)

@mixin mobile {
    @media (max-width: 576px) {
        @content;
    }
}

@mixin tablet {
    @media (max-width: 768px) {
        @content;
    }
}

@mixin desktop {
    @media (min-width: 1024px) {
        @content;
    }
}

// Usage — clean and readable!
.grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;

    @include tablet {
        grid-template-columns: repeat(2, 1fr);
    }

    @include mobile {
        grid-template-columns: 1fr;
        gap: 12px;
    }
}

Flexible Breakpoint Mixin

$breakpoints: (
    xs: 480px,
    sm: 576px,
    md: 768px,
    lg: 1024px,
    xl: 1200px,
);

@mixin respond-to($breakpoint) {
    $value: map-get($breakpoints, $breakpoint);

    @if $value {
        @media (max-width: $value) {
            @content;
        }
    } @else {
        @warn "Unknown breakpoint: #{$breakpoint}";
    }
}

// Usage:
.sidebar {
    width: 300px;

    @include respond-to(md) {
        width: 200px;
    }

    @include respond-to(sm) {
        width: 100%;
    }
}

Dark Mode Mixin

@mixin dark-mode {
    @media (prefers-color-scheme: dark) {
        @content;
    }
}

.card {
    background: white;
    color: #333;
    border: 1px solid #eee;

    @include dark-mode {
        background: #1a1a2e;
        color: #eee;
        border-color: #2a2a3e;
    }
}

Hover-Capable Mixin

@mixin hover {
    @media (hover: hover) {
        &:hover {
            @content;
        }
    }
}

.card {
    transition: transform 0.2s;

    @include hover {
        transform: translateY(-4px);
        box-shadow: 0 8px 24px rgba(0,0,0,0.12);
    }
}

Keyframe Wrapper

@mixin keyframes($name) {
    @keyframes #{$name} {
        @content;
    }
}

@include keyframes(fadeIn) {
    from { opacity: 0; transform: translateY(10px); }
    to { opacity: 1; transform: translateY(0); }
}

.element {
    animation: fadeIn 0.3s ease;
}

Key Takeaways

  • @content is a placeholder inside a mixin that gets replaced by the passed block
  • Perfect for media queries — write @include mobile { ... } instead of full media queries
  • @content mixins are wrappers — they provide context, you provide the styles
  • Combine with maps and arguments for flexible breakpoint systems
  • Also great for dark mode, hover detection, keyframes, and container queries