I'm trying to combine the use of a Sass variable with @media queries as follows:
我正在尝试将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
is then defined at various points in the stylesheet width percentage-based measurements to produce fluid layouts.
然后在基于样式表宽度百分比的测量中的各个点处定义$ base_width以生成流体布局。
When I do this, the variable seems to be recognized properly but the conditions for the media query are not. For example, the above code produces an 1160px layout regardless of screen width. If I flip-flop the @media statements like so:
当我这样做时,变量似乎被正确识别,但媒体查询的条件不是。例如,无论屏幕宽度如何,上面的代码都会产生1160px的布局。如果我像这样触发@media语句:
@media screen and (min-width: 1171px) {$base_width: 1160px;}@media screen and (max-width: 1170px) {$base_width: 960px;}
It produces a 960px layout, again regardless of screen width. Also note that if I remove the first line of $base_width: 1160px;
it returns an error for an undefined variable. Any ideas what I'm missing?
无论屏幕宽度如何,它都会产生960px的布局。另请注意,如果我删除$ base_width的第一行:1160px;它返回一个未定义变量的错误。我缺少什么想法?
6 个解决方案
#1
This is simply not possible. Since the trigger @media screen and (max-width: 1170px)
happens on the client-side.
这根本不可能。由于触发器@media屏幕和(max-width:1170px)发生在客户端。
Achieving your expected result would only be possible if SASS grabbed all rules and properties in your stylesheet containing your $base_width
variable and copied/changed them accordingly.
只有当SASS抓住包含$ base_width变量的样式表中的所有规则和属性并相应地复制/更改它们时,才能实现预期结果。
Since it won't work automatically you could do it by hand like this:
由于它不能自动工作,你可以这样手工完成:
@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 ...
This is not really DRY but the best you can do.
这不是真的干,但你能做的最好。
If the changes are the same every time you could also prepare a mixin containing all the changing values, so you wouldn't need to repeat it. Additionally you can try to combine the mixin with specific changes. Like:
如果每次您还准备包含所有更改值的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
And the Mixin would look like this
Mixin看起来像这样
=base_width_changes($base_width) #wrapper width: $base_width
#2
Similar to Philipp Zedler's answer, you can do it with a mixin. That lets you have everything in a single file if you want.
与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);}
#3
Edit: Please do not use this solution. The answer by ronen is much better.
编辑:请不要使用此解决方案。 ronen的答案要好得多。
As a DRY solution, you can use the @import
statement inside a media query, e.g. like this.
作为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";}
You define all responsive elements in the file included using the variables defined in the media query. So, all you need to repeat is the import statement.
您可以使用媒体查询中定义的变量定义文件中包含的所有响应元素。所以,你需要重复的是import语句。
#4
I had the same problem.
我有同样的问题。
The $menu-width
variable should be 240px on the mobile view @media only screen and (max-width : 768px)
and 340px on the desktop view.
$ menu-width变量在移动视图@media only屏幕上应为240px,在桌面视图上为(max-width:768px)和340px。
So i have simply created two variables:
所以我只创建了两个变量:
$menu-width: 340px;$menu-mobile-width: 240px;
And here is how i have used it:
以下是我如何使用它:
.menu { width: $menu-width; @media only screen and (max-width : 768px) { width: $menu-mobile-width; }}
#5
This isn't possible with SASS, but it is possible with CSS variables (or CSS custom properties). The only drawback is browser support – but there's actually a PostCSS plugin - postcss-css-variables - that "flattens" the use of CSS variables (which gives you support for older browsers, too).
这对于SASS是不可能的,但是CSS变量(或CSS自定义属性)可以实现。唯一的缺点是浏览器支持 - 但实际上有一个PostCSS插件 - postcss-css-variables--“扁平化”CSS变量的使用(这也为旧版浏览器提供了支持)。
The following example works great with SASS (and with postcss-css-variables you get support for older browsers too).
以下示例适用于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);}
This would result in the following CSS. The repetitive media queries will increase the file size, but I have found that the increase is usually negligible once the web server applies gzip
(which it will usually do automatically).
这将导致以下CSS。重复的媒体查询将增加文件大小,但我发现,一旦Web服务器应用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; }}
#6
With @ronen's great answer and a map, there's some real power available:
借助@ ronen的精彩答案和地图,可以获得一些真正的力量:
@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 ));}
It's now possible to have lots more DRY media queries targeting .myDiv
with a bunch of different values.
现在可以有更多针对.myDiv的DRY媒体查询,其中包含许多不同的值。
Map docs: https://sass-lang.com/documentation/functions/map
地图文档:https://sass-lang.com/documentation/functions/map
Example map usage: https://www.sitepoint.com/using-sass-maps/
示例地图用法:https://www.sitepoint.com/using-sass-maps/
#1
This is simply not possible. Since the trigger @media screen and (max-width: 1170px)
happens on the client-side.
这根本不可能。由于触发器@media屏幕和(max-width:1170px)发生在客户端。
Achieving your expected result would only be possible if SASS grabbed all rules and properties in your stylesheet containing your $base_width
variable and copied/changed them accordingly.
只有当SASS抓住包含$ base_width变量的样式表中的所有规则和属性并相应地复制/更改它们时,才能实现预期结果。
Since it won't work automatically you could do it by hand like this:
由于它不能自动工作,你可以这样手工完成:
@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 ...
This is not really DRY but the best you can do.
这不是真的干,但你能做的最好。
If the changes are the same every time you could also prepare a mixin containing all the changing values, so you wouldn't need to repeat it. Additionally you can try to combine the mixin with specific changes. Like:
如果每次您还准备包含所有更改值的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
And the Mixin would look like this
Mixin看起来像这样
=base_width_changes($base_width) #wrapper width: $base_width
#2
Similar to Philipp Zedler's answer, you can do it with a mixin. That lets you have everything in a single file if you want.
与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);}
#3
Edit: Please do not use this solution. The answer by ronen is much better.
编辑:请不要使用此解决方案。 ronen的答案要好得多。
As a DRY solution, you can use the @import
statement inside a media query, e.g. like this.
作为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";}
You define all responsive elements in the file included using the variables defined in the media query. So, all you need to repeat is the import statement.
您可以使用媒体查询中定义的变量定义文件中包含的所有响应元素。所以,你需要重复的是import语句。
#4
I had the same problem.
我有同样的问题。
The $menu-width
variable should be 240px on the mobile view @media only screen and (max-width : 768px)
and 340px on the desktop view.
$ menu-width变量在移动视图@media only屏幕上应为240px,在桌面视图上为(max-width:768px)和340px。
So i have simply created two variables:
所以我只创建了两个变量:
$menu-width: 340px;$menu-mobile-width: 240px;
And here is how i have used it:
以下是我如何使用它:
.menu { width: $menu-width; @media only screen and (max-width : 768px) { width: $menu-mobile-width; }}
#5
This isn't possible with SASS, but it is possible with CSS variables (or CSS custom properties). The only drawback is browser support – but there's actually a PostCSS plugin - postcss-css-variables - that "flattens" the use of CSS variables (which gives you support for older browsers, too).
这对于SASS是不可能的,但是CSS变量(或CSS自定义属性)可以实现。唯一的缺点是浏览器支持 - 但实际上有一个PostCSS插件 - postcss-css-variables--“扁平化”CSS变量的使用(这也为旧版浏览器提供了支持)。
The following example works great with SASS (and with postcss-css-variables you get support for older browsers too).
以下示例适用于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);}
This would result in the following CSS. The repetitive media queries will increase the file size, but I have found that the increase is usually negligible once the web server applies gzip
(which it will usually do automatically).
这将导致以下CSS。重复的媒体查询将增加文件大小,但我发现,一旦Web服务器应用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; }}
#6
With @ronen's great answer and a map, there's some real power available:
借助@ ronen的精彩答案和地图,可以获得一些真正的力量:
@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 ));}
It's now possible to have lots more DRY media queries targeting .myDiv
with a bunch of different values.
现在可以有更多针对.myDiv的DRY媒体查询,其中包含许多不同的值。
Map docs: https://sass-lang.com/documentation/functions/map
地图文档:https://sass-lang.com/documentation/functions/map
Example map usage: https://www.sitepoint.com/using-sass-maps/
示例地图用法:https://www.sitepoint.com/using-sass-maps/