Sass 使使用媒体查询变得非常出色。您可以在其他 CSS 代码块中嵌套它们,这将把您要更改的属性和值放在一起。这在它们之间创建了一个明显的关联,这比尝试维护那些被大量其他代码分隔或在不同文件中更改的属性和值要好得多。我们之前已经介绍过这个内容。它是在 Sass 3.2 中新增的。
.column-1-3 {
width: 33.3333%;
@media (max-width: 600px) {
width: 100%;
}
}
但是,由于我们可能会一遍又一遍地这样做,因此我们应该像处理任何其他变量一样将媒体查询抽象出来。
$bp-babybear: "(max-width: 600px)";
.column-1-3 {
width: 33.33%;
@media #{$bp-babybear} {
width: 100%;
}
}
不过,更常见的是看到 @mixin 与 Sass @content 块一起使用。我们在文章 媒体查询命名 中介绍了这一点。
@mixin bp($point) {
@if $point == papa-bear {
@media (max-width: 1600px) { @content; }
}
@else if $point == mama-bear {
@media (max-width: 1250px) { @content; }
}
@else if $point == baby-bear {
@media (max-width: 600px) { @content; }
}
}
您可以像这样使用它
.sidebar {
width: 33.33%;
@include bp(baby-bear) {
width: 100%;
}
}
并且没有理由不能同时进行这两者,如果您更喜欢这种外观,可以将媒体查询抽象成变量。
@mixin bp($point) {
$bp-babybear: "(max-width: 600px)";
$bp-mamabear: "(max-width: 1250px)";
$bp-papabear: "(max-width: 1600px)";
@if $point == papa-bear {
@media #{$bp-papabear} { @content; }
}
@else if $point == mama-bear {
@media #{$bp-mamabear} { @content; }
}
@else if $point == baby-bear {
@media #{$bp-babybear} { @content; }
}
}
它具有完全相同的用法。
顺便说一句,我喜欢“bp”作为名称,因为它是一个您需要一遍又一遍键入的东西,而且它简短而简洁。
乍一看,@mixin 方法似乎价值有限。仅使用变量更简洁,并且同样有意义。但是,使用 @mixin,我们获得了额外的功能!
也许我们想创建一个根本不包含任何媒体查询的样式表版本。在某些情况下,这绝对是合理的。也许我们想创建一个 IE 8 及以下版本的样式表。Nicolas Gallagher 几年前尝试使用 Sass 来实现这一点,但这略有不同。IE 8 及以下版本本身不支持媒体查询,因此也许我们决定要 为它们提供一个不包含媒体查询的精简样式表。像这样的旧浏览器速度本来就慢,因此与其用它们无法使用的额外代码来惩罚它们,不如通过为它们提供更少的代码来帮助它们。有点像 通用 IE 6 样式表 的想法。
我们可以结合使用 条件注释 来做到这一点。
<!--[if !IE 8]><!-->
<link rel="stylesheet" href="style.css">
<!--<![endif]-->
<!--[if gte IE 9]>
<link rel="stylesheet" href="style.css">
<![endif]-->
<!--[if lte IE 8]>
<link rel="stylesheet" href="style-NoMQs.css">
<![endif]-->
另一个合理的和现实世界的提供不含媒体查询样式表的理由是,如果您的网站某些页面使用响应式设计,而某些页面具有特定于移动设备的版本。我认为这是合理的。 那些具有特定于移动设备版本的页面实际上并不需要其中的媒体查询。
那么,如何从相同的 Sass 源创建 style.css 和 style-NoMQs.css 呢?我们使用 @mixin 的强大功能。
我们在 bp @mixin 中使用逻辑条件,该条件将继续输出媒体查询或不输出任何内容。
$MQs: true;
@mixin bp($point) {
@if ($MQs) {
$bp-babybear: "(max-width: 600px)";
$bp-mamabear: "(max-width: 1250px)";
$bp-papabear: "(max-width: 1600px)";
@if $point == papa-bear {
@media #{$bp-papabear} { @content; }
}
@else if $point == mama-bear {
@media #{$bp-mamabear} { @content; }
}
@else if $point == baby-bear {
@media #{$bp-babybear} { @content; }
}
}
}
您不会在 @mixin 之外声明该变量。您将从 @import 所有部分文件的“主”文件中声明它。因此,也许您的 style.scss 文件是
$MQs: true;
@import "variables";
@import "colors";
@import "global";
/* etc. */
并且您可以通过创建 style-NoMQs.scss 来创建“无媒体查询”版本 (style-NoMQs.css)
$MQs: false;
@import "variables";
@import "colors";
@import "global";
/* etc. */
只需将该变量更改为 false
,输出的 CSS 将完全不包含任何媒体查询。
非常感谢 Cat Farman 在她的 Cognition 文章 回退到级联 中写下了这个想法,并略微修改了将支持变量传递给 @mixin 本身。(这样更安全吗?)
最后,我了解到许多人不喜欢 Sass 在最终输出中输出重复的媒体查询的方式,只将媒体查询“冒泡”到嵌套的底部。为了尊重选择器的源顺序特异性(据我了解),这是必要的。我个人从未担心过这个问题,因为我始终使用启用了 GZip 的方式提供资源,而 GZip 可以将重复的文本作为早餐,它不会改变文件大小太多。更不用说浏览器毫无问题地快速浏览并应用这些规则。但是,如果您仍然不喜欢这样(或者我错了),则有一个 Grunt 插件 可以解决这个问题。
其他方法
- Dmitry Sheiko 的 技术 允许大于和小于设置断点。
- Breakpoint-sass
很棒的技巧。我唯一希望的是有一种方法可以在 SASS 中使用内联 MQ,并仍然可以稍后将它们合并。
嘿,Chris,这太棒了,这是一个能够继续构建“移动优先”网站但仍然能够在 IE8 中显示“桌面”版本的好解决方案。
几个月前,我想出了一个非常相似的解决方案,如果你能看看你的想法,我将不胜感激:https://github.com/peduarte/mobile-first-sass
干杯
我喜欢您保持 @media print 生机勃勃的方式!
如果您不想维护自己的 mixin,则有一个 Compass 扩展可以自动处理此问题(以及更多!),称为 Breakpoint。
我之前曾在 CSS Tricks 的评论中介绍过其他功能,但 Breakpoint 的 无查询回退 可能会让阅读本文的人感兴趣。
它有多种输出模式:单独的样式表(如 Chris Coyier 在这篇文章中所述)以及 在同一样式表中使用条件类输出方法,如果您不想为已经很慢的旧版 IE 产生单独的 CSS 下载。
例如,您编写一些 Sass
生成此 CSS
我赞同 http://www.breakpoint-sass.com..。非常有用且易于维护。
我们也使用这种方法(但使用条件注释为 MQ 和非 MQ 浏览器提供单独的样式表)。
这很棒,因为您可以随着屏幕宽度的增加逐步添加样式,并且非 MQ 浏览器会获得相同的结果。
几个月前,在我还没有 Codepen 账户之前 :'(,我一直在尝试一个想法,为旧版 IE 指定一个理想的屏幕尺寸,而不是为它们提供移动版或完整桌面版。这可以同时用于宽度和高度。快速笔
http://codepen.io/thomasdobber/pen/oLvCq
这正是卫报团队使用他们新发布的 sass-mq mixin 所做的事情。该理论在 自述文件 和 这篇文章 中进行了描述。这是一个简洁的解决方案,并且易于理解。
我一直在进行 一个小小的补充,以设置目标静态断点,以便静态/栅格化输出仅包含适用于特定屏幕尺寸的样式,并避免例如为 IE8 及其朋友提供宽屏样式。
感谢分享!
我对移动优先开发采用了类似的方法,但由于我使用的是 .less 文件,因此无法访问 @content 块(至少据我所知)。因此,我不得不提出一个依赖于存储在变量中的媒体查询的解决方案。您当然也可以在 SASS 中实现这一点。
在我的主文件中,导入了一些 .less 文件。
@import “variables.less”;
@import “mixins.less”;
@import “reset.less”;
@import “base.less”;
@import “layout.less”;
@import “modules.less”;
媒体查询变量存储在 variables.less 文件中,看起来像这样
@mq-medium-and-up: ~”only screen and (min-width: @{breakpoint-medium})”;
@mq-large-and-up: ~”only screen and (min-width: @{breakpoint-large})”;
这是一个使用其中一个变量的示例(我承认有点牵强)
body {
background: yellow;
@media @mq-medium-and-up {
background: red;
}
}
我还为 IE <= 8 保留了一个单独的主文件,看起来像这样
@import “variables.less”;
@mq-medium-and-up: ~”all”;
@mq-large-and-up: ~”all”;
@import “mixins.less”;
@import “reset.less”;
@import “base.less”;
@import “layout.less”;
@import “modules.less”;
上面发生的事情是,在导入 variables.less 文件后,我立即覆盖媒体查询变量并重新定义它们。现在,无论何时在样式表中使用这些变量,它们都将被编译成媒体规则,这些规则为旧版本的 Internet Explorer 理解(不确定 IE < 7 是否也如此)。
body {
background: yellow;
@media all {
background: red;
}
}
因此,基本上这些旧浏览器将获得桌面体验,我认为这可能是让他们只获得基本体验的一个不错的替代方案。这显然应该是一个具体情况具体分析的决策。您对这个解决方案有什么想法?
很棒的解决方案:我最近在几个相当大的项目中使用了它,它意味着处理旧版 IE 变得轻而易举。Jake Archibald 大约一年前提出了几乎完全相同的东西:http://jakearchibald.github.io/sass-ie/
你也可以将变量放入一个列表中,然后让 mixin 循环遍历它。我最初这样做是为了避免为每个断点重写 mixin,而且效果还不错。我通常不使用“三只熊”的类比,但为了与本文保持一致,我进行了修改。
此外,要创建一个单独的旧版 IE 样式表,你可以使用以下 mixin
然后,你可以在“oldie.scss”文件的顶部添加以下变量
并将你的样式表链接到你的 HTML,如下所示
并像往常一样编写你的 Sass
这将在你的普通“style.css”文件中呈现为
并自动渲染到你的“oldie.css”文件中,不使用媒体查询,仅使用 mixin 中定义的“oldie 断点”(babybear 和 mamabear),如下所示
哇,这太长了,但如果你仍然想要支持旧版 IE 浏览器,它太酷了,不容错过。就我个人而言,我尝试正式支持 IE8+,但希望它在 IE6/7 中看起来尽可能好,而不必花费太多时间进行修改。
你还可以使用 $oldie 变量做类似以下的事情
这将呈现到普通的“style.css”文件中,如下所示
以及到“oldie.css”文件,如下所示
这将自动将所有 IE 修复程序放入“oldie.css”文件中,保持“style.css”文件干净。好了,我完成了!
我正要写同样的话——更好的方法!
这是一个很酷的简化方法。但是我唯一不喜欢的是你的样式表最终充满了重复的
@media()
声明。如果 Sass 足够智能,可以将相同的媒体查询分组在一起,就像这样
相反,它会创建两次
@media(max-width:767px)...
块。至少它足够智能,可以将媒体查询从样式定义中提取出来。因此,如果你有一个包含数百个元素的大型样式表,这些元素在几个不同的断点处具有不同的值,那么最终你的样式表中将添加数千个@media()
块。我尝试过使用 append() 命令将断点值添加到 Sass 列表中,然后迭代这些列表并生成所有分组在一起的媒体查询,但嵌套选择器会很快变得混乱。仍在寻找解决这个问题的方案。
有一个解决方案:http://www.building-blocks.com/thinking/combine-matching-media-queries-with-grunt
@Jake 110% 同意。+1。
@Paul 如果我们不使用 Grunt 呢…?
我看不出有什么充分的理由要在已经复杂且饱和的开发工作流程中再添加一个难题,仅仅是为了让 Sass 以显而易见的方式编译媒体查询:在 CSS 的底部。
在这个问题上,DRY 原则失效了。
Chris 最后提到的关于 GZip 压缩和浏览器的内容当然有助于“接受”这个问题,但并没有完全消除一丝不快的感觉。
嘿 @jake 和 @Ricardo
Kimberly Blessing 做了一个很棒的演示,说明你们担心的问题根本不重要。无论你是否将所有 MQ 合并在一起或将它们散布在页面中,两种方法之间都没有明显的区别。
Kimberly Blessing:优化媒体查询
所以,请随意消除你心中的不快 :)
最终目标是使你的 Sass 更易于阅读和理解,而不是你的 CSS。在这种情况下,你可以看到应用于每个元素的每个 MQ,而不是在整个页面中搜索以找出为什么是 300px 而不是 500px……
P.S. Grunt 真的非常易于使用,如果你还没有使用过,一旦你开始使用,你将永远不会回头 :) <3
@Eric,非常感谢你提供的文章,信息量很大。
看到 IE10 击败 Chrome,以及所有 IE8、IE9 和 IE10 在 Microsoft.com 测试中击败 Chrome,我感到印象深刻。说实话,选择 Microsoft.com 作为测试网站之一似乎是一个非常奇怪的选择……IE8 和 IE9 击败 Chrome?得了吧 :p
但回到主题,我个人对整个“最终输出中重复的媒体查询”肥皂剧的不满并不是性能问题,我多少有点了解(并且本文中的数据证实了这一点)。更多的是关于最终 CSS 文件的美观性,尤其是当我想到学生和其他刚入行的网页设计师/前端开发人员时,因为他们看不到我漂亮的 SCSS 文件,只能看到最终的 CSS 文件。我认为理解那里真正发生的事情非常困难。这对我和你来说可能很明显,但对新手不一定如此。
此外,我不太喜欢不得不“遵守”Sass 对我如何使用媒体查询编译 SCSS 的看法(我知道我们有几种输出样式:嵌套、展开、紧凑和压缩,但这是另一个话题)。应该有一种方法,就像我刚才提到的样式一样,来决定编译后媒体查询将在最终 CSS 文件中如何显示。
如果我是一个有 Rails 知识的程序员,我会很早就尝试解决这个问题。但我不是。失败。
关于 Grunt,之前有人告诉我过,我相信情况确实如此,但我还没有看到关于如何运行它的简单教程,类似于针对三年级学生的教程;我尝试过几次让它运行,但相信我,我看到的教程都假设你已经了解和掌握了许多其他事物/概念,而这就是 Grunt 失败的地方。
我之前对 Sass 也曾有过类似的感觉,直到我能够自己弄明白,但这花了我一段时间。不久前,我使用新的 Browser-Sync 工具时也遇到了同样的情况,直到我能够自己弄清楚如何安装它,而安装说明并不清楚,并且假设“本指南假设您已经在项目中安装了 Grunt 并知道如何使用它。” 真的。哈哈。
而且,我没有使用 Grunt 安装它,因为它不需要 ¬¬
不错的文章,Chris,我一直在阅读你的博文——每次都做得很好。
我刚刚开始尝试 Nicolas Gallaghers 的方法。它是 ie8/移动优先。浏览器只下载一个样式表。太棒了,看看吧!
nicolasgallagher.com/mobile-first-css-sass-and-ie/
我喜欢使用 Sass,它将节省大量时间!
非常好。Sass 非常方便且有趣。
很棒的文章,Chris,一如既往。我也做了 类似的事情。我为查询使用了链接列表(可能会在某个时候将其恢复为标准的 $变量),并且还包括了为非 MQ 设备设置默认视图以及包含/排除某些内容的选项。
这篇文章和其他一些评论给了我一些想法,我可能会进一步探索这些想法,特别是在模块化媒体查询和 MQ 缓冲方面。
此技术对视网膜显示屏也很有效!
一个小提示 ;-)
我只是把这个放在这里
http://breakpoint-sass.com/
https://github.com/lolmaus/breakpoint-slicer/
条件注释的方式是解决 IE“坏话”的最常用方法。
有多少人使用过“Paul Irish 的在
<html>
标签中使用条件注释的方式”(PICCHTW)呢?举手!我对 Sass 还不够熟悉,所以我不确定如何在该设置中使用 html 标签类。我想可以使用类似 Chris Ruppel 的解决方案 的方法来处理这类事情?像这样?
最终得到这个
它不允许你选择性地应用来自媒体查询的样式,但它允许你为特定版本的 IE 提供来自特定媒体查询的所有样式,以便它获得的不仅仅是移动样式。
但就像我说的,我对 Sass 还不够熟悉,所以请有人告诉我这是否很糟糕或者 Sass 语法错误。:-)
@Zoe 是的 :)
我不想在我的示例中特别指出 IE,但我的
.no-mq
类通常实际上是一个特定的条件类,例如.lte-ie8
@Zoe 我实际上认为 Chris Ruppel 的 mixin 是一种非常有选择性地应用样式的方法 :)——顺便说一句,我认为你的评估中没有任何糟糕或错误的地方,只是观点不同而已。
我更喜欢用条件类的方式(像“皮卡丘” (PICCHTW) 一样),而不是为 IE 使用(和管理)额外的文件,Chris Ruppel 的 mixin 简直太棒了。
也许只有我一个人这样想,但我强烈倾向于有一套中央媒体查询,每个查询加载其断点特定的 SCSS 文件。额外的好处是在移动优先的设置中,构建 IE8 仅仅是所有样式的累积结果。我想每个人都有自己的偏好。
混合和变量用于媒体查询。
mediaquery.scss
超级好用 :)
我已将其放入 index 中
¨
以及 style.css 中
@media screen and (min-width: 980px)
{
body{
height:100%;
}
}
我可能来晚了一点,但在编写移动优先并支持 IE8 时,对我来说一个非常简单的解决方案是
Mixin
Sass
输出 CSS
这只是一个简单的示例,但正如您所看到的,如果您将 $ie8-support 变量设置为 TRUE,它将在桌面媒体查询中添加额外的 .ie8 类。如果您将其设置为 FALSE,则不会添加任何内容。效果很好。
Codepen 示例
http://codepen.io/thelifemgmt/pen/bKrdq?editors=010
仅仅为了支持 IE8 而创建两个单独的样式表对我来说毫无意义。
无论如何……仅供参考。