Keywords: Sass | media queries | responsive design
Abstract: This article examines the technical limitations of combining Sass variables with @media queries. Since media queries execute client-side while Sass variables are processed at compile time, directly redefining variables via media queries fails to achieve the desired effect. The analysis delves into the root cause and presents two practical solutions based on the best answer: manually duplicating CSS rules within each media query or using Sass mixins to encapsulate styling logic for better code reusability. It also briefly contrasts alternative approaches with CSS custom properties and compatibility considerations.
Problem Background and Core Challenge
In responsive web design, developers often aim to dynamically adjust layout parameters, such as a base width ($base_width), based on screen size. An intuitive approach is to combine variables with CSS3 media queries in Sass, attempting code like:
$base_width: 1160px;
@media screen and (max-width: 1170px) {
$base_width: 960px;
}
@media screen and (min-width: 1171px) {
$base_width: 1160px;
}
However, this does not work as expected: the variable appears recognized, but media query conditions are ignored, resulting in a fixed layout. For instance, the above code always produces a 1160px layout regardless of screen width. Swapping the media query order fixes it at 960px. Removing the initial variable definition also causes an undefined variable error.
Technical Principle Analysis
The root issue lies in the differing execution timings of Sass and CSS media queries. Sass is a preprocessor that handles variables and mixins at compile time on the server side, generating static CSS files. In contrast, @media queries are a CSS3 feature applied dynamically in the client (browser) based on actual device conditions during rendering. Thus, at compile time, Sass cannot anticipate the client environment and cannot redefine variables based on media query conditions. Attempting to modify variable values within a media query only creates a local copy within that block, without affecting global usage.
Solution 1: Manual Duplication of CSS Rules
The most straightforward solution is to manually duplicate CSS rules that depend on $base_width into each media query block, setting the variable value separately. For example:
@media screen and (max-width: 1170px) {
$base_width: 960px;
#wrapper {
width: $base_width;
}
// other related rules
}
@media screen and (min-width: 1171px) {
$base_width: 1160px;
#wrapper {
width: $base_width;
}
// other related rules
}
This ensures the variable is correctly applied within each media query context but violates the DRY (Don't Repeat Yourself) principle, increasing maintenance overhead.
Solution 2: Using Sass Mixins
To improve code reusability, define a mixin to encapsulate styling logic, then call it within media queries with parameters. For example:
@mixin base_width_styles($base_width) {
#wrapper {
width: $base_width;
}
// other shared styles
}
@media screen and (max-width: 1170px) {
@include base_width_styles(960px);
}
@media screen and (min-width: 1171px) {
@include base_width_styles(1160px);
}
Mixins allow centralized style management, reduce code duplication, and can be extended with additional rules for specific media queries.
Alternative Approach: CSS Custom Properties
CSS custom properties (CSS variables) offer native dynamic variable support that can be modified directly in media queries without preprocessing. For example:
:root {
--base-width: 1160px;
}
@media screen and (max-width: 1170px) {
:root {
--base-width: 960px;
}
}
#wrapper {
width: var(--base-width);
}
This method aligns better with modern CSS standards but requires consideration of browser compatibility. For older browsers, tools like the PostCSS plugin postcss-css-variables can provide fallback support.
Conclusion and Best Practices
When integrating variables with media queries in Sass, it is crucial to account for the separation between compile-time and runtime. Using mixins is recommended to balance code reusability and maintainability, or evaluate CSS custom properties to leverage native capabilities. In practical projects, choose the appropriate solution based on team stack and compatibility requirements.