使用Sass变量和CSS3媒体查询

时间:2021-04-20 01:18:41

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/