如何自动化减少SASS生成的重复媒体查询代码行数?
解决Sass响应式Mixin重复生成@media规则的问题
问题场景
我在工作流中使用Sass Mixin简化响应式断点代码编写,配合Gulp编译压缩CSS。但嵌套编写代码时,每个Mixin调用都会生成独立的@media规则,导致CSS中重复出现相同断点的媒体查询,增大资源体积。
示例Sass代码
#footer { .block-contacts { .social_title { display: block; @include desktop() { display: inline-block } &:before { width: 100vw; @include desktop() { width: 50vw; } } } } }
编译后重复的CSS代码
#footer .block-contacts .social_title { display: block; } @media(min-width: 64rem){ #footer .block-contacts .social_title { display:inline-block } } #footer .block-contacts:before { width:100vw; } @media(min-width: 64rem){ #footer .block-contacts:before { width:50vw; } }
自动化解决方案
不需要手动在文件末尾集中重构规则,可通过以下几种方式自动减少重复的@media生成:
1. 改写Sass Mixin实现断点样式集中存储
通过Sass的map暂存相同断点的样式,最后统一输出,避免重复生成@media:
// 定义断点配置 $breakpoints: ( desktop: 64rem ); // 用于存储不同断点的样式集合 $breakpoint-styles: (); // 改写desktop Mixin,将样式暂存到map @mixin desktop { @if map-has-key($breakpoint-styles, desktop) { $existing: map-get($breakpoint-styles, desktop); $new-styles: $existing + & { @content }; $breakpoint-styles: map-set($breakpoint-styles, desktop, $new-styles); } @else { $breakpoint-styles: map-set($breakpoint-styles, desktop, & { @content }); } } // 在文件末尾调用,输出所有断点样式 @mixin output-breakpoints { @each $name, $styles in $breakpoint-styles { $width: map-get($breakpoints, $name); @media (min-width: #{$width}) { #{$styles} } } } // 使用示例:正常写嵌套和调用Mixin,最后输出 #footer { .block-contacts { .social_title { display: block; @include desktop { display: inline-block; } &:before { width: 100vw; @include desktop { width: 50vw; } } } } } // 输出所有断点样式 @include output-breakpoints;
2. 使用Sass-MQ插件自动合并媒体查询
Sass-MQ是专门处理响应式媒体查询的Sass插件,自带相同断点样式合并功能,无需手动调整代码结构:
@import 'mq'; // 配置断点 $mq-breakpoints: ( desktop: 64rem ); #footer { .block-contacts { .social_title { display: block; @include mq(desktop) { display: inline-block; } &:before { width: 100vw; @include mq(desktop) { width: 50vw; } } } } }
编译后所有desktop断点的样式会自动合并到同一个@media规则中。
3. Gulp流程中加入css-mqpacker插件
如果不想修改Sass代码,可在Gulp的CSS处理环节加入css-mqpacker,它会扫描编译后的CSS,自动合并相同媒体查询的规则:
const gulp = require('gulp'); const sass = require('gulp-sass')(require('sass')); const postcss = require('gulp-postcss'); const mqpacker = require('css-mqpacker'); gulp.task('compile-sass', function() { return gulp.src('src/scss/**/*.scss') .pipe(sass().on('error', sass.logError)) .pipe(postcss([mqpacker({ sort: true })])) // 合并相同媒体查询 .pipe(gulp.dest('dist/css')); });
该插件会把所有匹配@media(min-width: 64rem)的规则合并成一个,里面包含所有对应样式。
4. 用Sass @at-root优化媒体查询结构
虽然需要手动处理,但@at-root可以把嵌套内的媒体查询提至根级别,减少嵌套选择器重复,同时让媒体查询更集中:
#footer { .block-contacts { .social_title { $current-selector: &; // 保存当前选择器 display: block; @at-root { @include desktop() { #{$current-selector} { display: inline-block; } } } &:before { width: 100vw; @at-root { @include desktop() { #{$current-selector}:before { width: 50vw; } } } } } } }
内容的提问来源于stack exchange,提问作者Giovan Cruz
相关产品推荐
相关产品推荐

