在 CSS3 媒体查询中使用 Sass 变量
Posted
技术标签:
【中文标题】在 CSS3 媒体查询中使用 Sass 变量【英文标题】:Using Sass Variables with CSS3 Media Queries 【发布时间】:2012-02-25 16:33:22 【问题描述】:我正在尝试将 Sass 变量的使用与 @media 查询结合起来,如下所示:
$base_width:1160px;
@media screen and (max-width: 1170px) $base_width: 960px;
@media screen and (min-width: 1171px) $base_width: 1160px;
$base_width
然后在样式表宽度百分比测量中的各个点定义,以产生流畅的布局。
当我这样做时,变量似乎被正确识别,但媒体查询的条件却不是。例如,上面的代码生成一个 1160px 的布局,无论屏幕宽度如何。如果我像这样翻转@media 语句:
@media screen and (min-width: 1171px) $base_width: 1160px;
@media screen and (max-width: 1170px) $base_width: 960px;
无论屏幕宽度如何,它都会生成 960 像素的布局。另请注意,如果我删除 $base_width: 1160px;
的第一行,它会为未定义的变量返回错误。有什么我想念的想法吗?
【问题讨论】:
重复的***.com/questions/40739695/… 【参考方案1】:这根本不可能。由于触发 @media screen and (max-width: 1170px)
发生在客户端。
只有在 SASS 抓取包含您的 $base_width
变量的样式表中的所有规则和属性并相应地复制/更改它们时,才能实现您的预期结果。
由于它不会自动工作,您可以像这样手动操作:
@media screen and (max-width: 1170px)
$base_width: 960px // you need to indent it to (re)set it just within this media-query
// now you copy all the css rules/properties that contain or are relative to $base_width e.g.
#wrapper
width: $base_width
...
@media screen and (min-width: 1171px)
$base_width: 1160px
#wrapper
width: $base_width
...
这不是真正的 DRY,而是你能做的最好的。
如果每次更改都相同,您还可以准备一个包含所有更改值的 mixin,这样您就不需要重复它。此外,您可以尝试将 mixin 与特定更改结合起来。喜欢:
@media screen and (min-width: 1171px)
+base_width_changes(1160px)
#width-1171-specific-element // additional specific changes, that aren't in the mixin
display: block
Mixin 看起来像这样
=base_width_changes($base_width)
#wrapper
width: $base_width
【讨论】:
在@media 查询中,SASS 仍然无法使用 $variables 吗? @HappyTorso 一直都是这种情况,直到出现在视口调整大小时运行的客户端 Sass 编译器(例如在 javascript 中)。 Sass 变量在构建时被编译成静态值;它们在运行时不再存在。当查询中的媒体属性发生变化时,媒体查询会在运行时进行评估。 @ericsoco 我不明白为什么这是一个原因。 SASS 可以轻松(?)跟踪变量的所有用法并在使用它们的地方插入媒体查询;$foo: 1rem; @media (min-width: 10rem) $foo: 2rem .class font-size: $foo .class2 padding: $foo
将导致 .class font-size: 1rem .class2 padding: 1rem @media (min-width: 10rem) (.class font-size: 2rem .class2 padding: 2rem
是的,sass 是一个预处理器,没有理由说“这根本不可能”......它可以做到,只是没有实现。【参考方案2】:
与 Philipp Zedler 的回答类似,您可以使用 mixin 来完成。如果需要,您可以将所有内容都放在一个文件中。
@mixin styling($base-width)
// your SCSS here, e.g.
#Contents
width: $base-width;
@media screen and (max-width: 1170px)
@include styling($base-width: 960px);
@media screen and (min-width: 1171px)
@include styling($base-width: 1160px);
【讨论】:
迟早你会遇到这个问题,虽然:sitepoint.com/cross-media-query-extend-sass 这个比我的回答好! +1 喜欢这个解决方案。将其与地图 (sass-lang.com/documentation/functions/map) 结合使用,您就拥有了一些力量——我将在这里制作一个单独的解决方案来解释。编辑:完成。 ***.com/a/56894640/385273【参考方案3】:这对于 SASS 是不可能的,但对于 CSS 变量(或 CSS custom properties)是可能的。唯一的缺点是浏览器支持——但实际上有一个 PostCSS 插件——postcss-css-variables——它“扁平化”了 CSS 变量的使用(它也为你提供了对旧浏览器的支持)。
下面的示例非常适用于 SASS(并且使用 postcss-css-variables,您也可以获得对旧浏览器的支持)。
$mq-laptop: 1440px;
$mq-desktop: 1680px;
:root
--font-size-regular: 14px;
--gutter: 1rem;
// The fact that we have to use a `max-width` media query here, so as to not
// overlap with the next media query, is a quirk of postcss-css-variables
@media (min-width: $mq-laptop) and (max-width: $mq-desktop - 1px)
:root
--font-size-regular: 16px;
--gutter: 1.5rem;
@media (min-width: $mq-desktop)
:root
--font-size-regular: 18px;
--gutter: 1.75rem;
.my-element
font-size: var(--font-size-regular);
padding: 0 calc(var(--gutter) / 2);
这将产生以下 CSS。重复的媒体查询会增加文件大小,但我发现一旦网络服务器应用gzip
(它通常会自动执行),增加通常可以忽略不计。
.my-element
font-size: 14px;
padding: 0 calc(1rem / 2);
@media (min-width: 1680px)
.my-element
padding: 0 calc(1.75rem / 2);
@media (min-width: 1440px) and (max-width: 1679px)
.my-element
padding: 0 calc(1.5rem / 2);
@media (min-width: 1680px)
.my-element
font-size: 18px;
@media (min-width: 1440px) and (max-width: 1679px)
.my-element
font-size: 16px;
【讨论】:
【参考方案4】:编辑:请不要使用此解决方案。 ronen 的回答要好得多。
作为 DRY 解决方案,您可以在媒体查询中使用 @import
语句,例如像这样。
@media screen and (max-width: 1170px)
$base_width: 960px;
@import "responsive_elements";
@media screen and (min-width: 1171px)
$base_width: 1160px;
@import "responsive_elements";
您使用媒体查询中定义的变量定义文件中包含的所有响应式元素。因此,您需要重复的只是 import 语句。
【讨论】:
【参考方案5】:有了@ronen 的great answer 和一张地图,就有了一些真正的力量:
@mixin styling($map)
.myDiv
background: map-get($map, 'foo');
font-size: map-get($map, 'bar');
@media (min-height: 500px)
@include styling((
foo: green,
bar: 50px
));
@media (min-height: 1000px)
@include styling((
foo: red,
bar: 100px
));
现在可以有更多针对 .myDiv
的 DRY 媒体查询,其中包含一堆不同的值。
地图文档:https://sass-lang.com/documentation/functions/map
地图使用示例:https://www.sitepoint.com/using-sass-maps/
【讨论】:
我花了一秒钟才看到它,但这与@ronen 的答案相同,只是使用地图输入来一次支持多个变量。我不会以任何方式贬低它的价值,但在我建立这种联系之前很难理解【参考方案6】:我遇到了同样的问题。
$menu-width
变量在 移动 视图 @media only screen and (max-width : 768px)
上应为 240 像素,在桌面 视图上应为 340 像素。
所以我只是创建了两个变量:
$menu-width: 340px;
$menu-mobile-width: 240px;
这是我使用它的方式:
.menu
width: $menu-width;
@media only screen and (max-width : 768px)
width: $menu-mobile-width;
【讨论】:
【参考方案7】:两条建议
1
为小屏幕编写“默认”CSS 语句,仅对大屏幕使用媒体查询。通常不需要max-width
媒体查询。
示例(假设元素具有“容器”类)
@mixin min-width($width)
@media screen and (max-width: $width)
@content;
.container
width: 960px;
@include min-width(1170px)
width: 1160px;
2使用CSS变量解决问题,如果you can。
@mixin min-width($width)
@media screen and (max-width: $width)
@content;
:root
--container-width: 960px;
@include min-width(1170px)
--container-width: 1160px;
.container
width: var(--container-width);
注意:
由于窗口宽度为 1170px 时宽度为 1160px,因此最好使用 100% 的宽度和 1160px 的最大宽度,并且父元素可能具有 5px 的水平填充,只要 box-sizing 属性设置为border-box。有很多方法可以解决问题。如果父级不是 flex 或 grid 容器,您可以使用 .container margin: auto
。
【讨论】:
标准 CSS 变量是最干净的路径。【参考方案8】:这也可以通过 %placeholders 实现。
%placeholders 可以包含在媒体查询中。因此,您可以设置多个变量以在不同的屏幕尺寸下使用,然后占位符会自动相应地进行预处理。我也在使用一些 mixin 来缩短我的媒体查询声明。
在您的 _vars.scss 文件中:
$width-1: 960px;
$width-2: 1160px;
在您的 _placeholders.scss 文件中:
%variable-site-width
@media screen and (max-width: 1170px) width: $width-1;
@media screen and (min-width: 1171px) width: $width-2;
在您的 page.scss 文件中:
.wrapper. @extend %variable-site-width; background: red; etc...
这将编译为类似于:
@media screen and (max-width: 1170px)
.wrapper width: 960px;
@media screen and (min-width: 1171px)
.wrapper width: 1160px;
瞧!
我将这种技术广泛用于可变字体大小和大量其他事情。
【讨论】:
以上是关于在 CSS3 媒体查询中使用 Sass 变量的主要内容,如果未能解决你的问题,请参考以下文章