Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. Sass Dictionary
  3. @media Nesting

@media Nesting

In Sass, media queries (@media) can be nested inside selectors. In plain CSS, @media blocks must be written in a separate location in the file, but with Sass nesting, the breakpoints for a selector can be kept in the same block. After compilation, they are automatically expanded into standard @media blocks.

In plain CSS, the selector and media query end up separated like this.

/* Plain CSS: selector and media query are written in different locations */
.card {
    font-size: 1rem;
    padding: 24px;
}

@media (max-width: 768px) {
    .card {
        font-size: 0.9rem;
        padding: 16px;
    }
}

Syntax

// ========================================
// Basic syntax for nesting @media inside a selector
// ========================================

// Write @media inside a selector block
.selector {
    property: value;

    // Nest the media query here
    @media (condition) {
        property: value;   // Applies to .selector
    }
}

// Compiled CSS (reference)
// .selector { property: value; }
// @media (condition) { .selector { property: value; } }


// ========================================
// Explicit parent selector reference with &
// ========================================

// Using & makes the parent selector reference more explicit
.selector {
    property: value;

    @media (condition) {
        & {
            property: value;
        }
    }
}

Main @media nesting patterns

PatternExampleDescription
max-width (non-mobile-first)@media (max-width: 768px) { ... }Applies styles to screens at or below the specified width.
min-width (mobile-first)@media (min-width: 768px) { ... }Applies styles to screens at or above the specified width.
Range@media (min-width: 768px) and (max-width: 1023px) { ... }Applies styles only within a specific width range, such as tablets.
Print@media print { ... }Print-only styles can be written alongside the selector.
Color scheme@media (prefers-color-scheme: dark) { ... }Dark mode styles can be grouped per component.
Combined with @mixin@include sp { ... }Wrap media queries in a mixin for shorter notation.

Sample Code

Using a card component and navigation as examples, this demonstrates responsive styles with nested @media. Breakpoint definitions for each component are consolidated in one place, making changes easy to spot.

// ========================================
// Card component responsive layout
// ========================================

.card {
    display: grid;
    grid-template-columns: 200px 1fr;   // Desktop: thumbnail + text 2-column
    gap: 24px;
    padding: 24px;
    background-color: #ffffff;
    border: 1px solid #dee2e6;
    border-radius: 8px;

    // Switch to 1 column at tablet width
    @media (max-width: 1023px) {
        grid-template-columns: 1fr;
        gap: 16px;
        padding: 20px;
    }

    // Further reduce padding at smartphone width
    @media (max-width: 767px) {
        padding: 16px;
        gap: 12px;
    }

    // Card title
    &__title {
        font-size: 1.25rem;
        font-weight: bold;
        color: #2c3e50;
        margin: 0 0 8px;

        // Reduce font size at smartphone width
        @media (max-width: 767px) {
            font-size: 1.1rem;
        }
    }

    // Card body text
    &__body {
        font-size: 1rem;
        line-height: 1.7;
        color: #495057;

        @media (max-width: 767px) {
            font-size: 0.9rem;
        }
    }
}


// ========================================
// Navigation responsive layout
// ========================================

.nav {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 32px;
    background-color: #2c3e50;
    height: 60px;

    // Switch to vertical drawer menu at smartphone width
    @media (max-width: 767px) {
        display: none;   // Toggle with JavaScript

        &.is-open {
            display: flex;
            flex-direction: column;
            align-items: stretch;
            height: auto;
            padding: 8px 0;
        }
    }

    // Navigation link
    &__link {
        display: block;
        padding: 8px 16px;
        color: #ecf0f1;
        text-decoration: none;
        border-radius: 4px;
        transition: background-color 0.2s;

        &:hover {
            background-color: #34495e;
        }

        // Increase padding for easier tapping at smartphone width
        @media (max-width: 767px) {
            padding: 12px 24px;
            border-radius: 0;
            border-bottom: 1px solid #34495e;
        }
    }
}


// ========================================
// Hero section: managing multiple breakpoints
// ========================================

.hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 480px;
    padding: 64px 32px;
    text-align: center;
    background-color: #f0f4f8;

    // Tablet width
    @media (max-width: 1023px) {
        min-height: 360px;
        padding: 48px 24px;
    }

    // Smartphone width
    @media (max-width: 767px) {
        min-height: 280px;
        padding: 40px 16px;
    }

    // Heading
    &__heading {
        font-size: 2.5rem;
        font-weight: bold;
        color: #2c3e50;
        margin: 0 0 16px;
        line-height: 1.3;

        @media (max-width: 1023px) {
            font-size: 2rem;
        }

        @media (max-width: 767px) {
            font-size: 1.5rem;
            margin-bottom: 12px;
        }
    }

    // Subtext
    &__sub {
        font-size: 1.1rem;
        color: #636e72;
        max-width: 600px;

        @media (max-width: 767px) {
            font-size: 0.95rem;
        }
    }
}


// ========================================
// Dark mode support (prefers-color-scheme)
// ========================================

.article {
    background-color: #ffffff;
    color: #2c3e50;
    padding: 32px;
    border-radius: 8px;

    // Applies when the user's OS is set to dark mode
    @media (prefers-color-scheme: dark) {
        background-color: #1e272e;
        color: #dfe6e9;
    }

    &__title {
        font-size: 1.5rem;
        border-bottom: 2px solid #dee2e6;
        padding-bottom: 8px;
        margin-bottom: 16px;

        @media (prefers-color-scheme: dark) {
            border-bottom-color: #4a5568;
        }
    }
}


// ========================================
// Print styles nested inside selectors
// ========================================

.page-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 32px;
    background-color: #2c3e50;
    color: #ffffff;

    // Use white background when printing to avoid relying on background printing settings
    @media print {
        background-color: #ffffff;
        color: #000000;
        border-bottom: 1px solid #000000;
    }
}

// Hide navigation when printing
.nav {
    @media print {
        display: none;
    }
}

Common Mistakes

Nesting @media too deeply, resulting in many duplicate media queries in the compiled output

Sass @media nesting does not automatically merge identical media query conditions across multiple selectors. Writing the same breakpoint nested inside each component expands them into separate @media blocks in the compiled CSS.

ng_example.scss
// The same breakpoint is nested inside each of three components
.header {
    font-size: 1.5rem;
    @media (max-width: 767px) {
        font-size: 1.2rem;
    }
}

.hero {
    padding: 64px;
    @media (max-width: 767px) {
        padding: 32px;
    }
}

.footer {
    height: 120px;
    @media (max-width: 767px) {
        height: auto;
    }
}
/* Compiled output: @media (max-width: 767px) appears three times */
.header { font-size: 1.5rem; }
@media (max-width: 767px) {
    .header { font-size: 1.2rem; }
}

.hero { padding: 64px; }
@media (max-width: 767px) {
    .hero { padding: 32px; }
}

.footer { height: 120px; }
@media (max-width: 767px) {
    .footer { height: auto; }
}

This repetition is easier to manage by naming breakpoints with a mixin and keeping component nesting to a minimum. The impact on CSS file size is largely absorbed by gzip compression, but when duplication is heavy, grouping @media blocks at the end of the file is also an option.

Misunderstanding that nesting @media conditions produces OR logic instead of AND

When one @media block is nested inside another, Sass combines the two conditions with and. Writing @media (max-width: 1024px) inside @media (min-width: 768px) does not produce OR logic — it compiles to "min-width: 768px AND max-width: 1024px".

ng_example.scss
// Written under the assumption that the inner @media becomes an OR condition
.sidebar {
    display: block;

    @media (min-width: 768px) {
        width: 240px;

        // Intending to narrow down to tablet width only
        @media (max-width: 1024px) {
            width: 200px;
        }
    }
}
/* Compiled output: AND combination (may or may not be intended, but easy to misread) */
.sidebar { display: block; }
@media (min-width: 768px) {
    .sidebar { width: 240px; }
}
@media (min-width: 768px) and (max-width: 1024px) {
    .sidebar { width: 200px; }
}

If a range is the goal, write it as a single @media (min-width: 768px) and (max-width: 1024px) from the start — this makes the intent clearer. Nesting @media only narrows conditions further (AND); it never adds alternatives (OR).

Notes

Sass @media nesting allows breakpoint styles related to a selector to be written inside that selector's block. In plain CSS, @media blocks must be placed elsewhere in the file, making it necessary to search for where a component's responsive definitions are. With Sass nesting, all states of a component can be collected in one place, making changes, deletions, and moves straightforward. After compilation, the output is standard @media blocks, so there is no difference in the size or behavior of the resulting CSS. Using a mixin to define breakpoint conditions by name allows even shorter notation such as @include sp { ... }. Combining with nesting and parent selector reference (&) makes component-based style management more effective.

If you find any errors or copyright issues, please .