将 Sass 变量与 CSS3 媒体查询结合使用

发布于 2025-01-02 09:18:03 字数 619 浏览 1 评论 0原文

我尝试将 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;}

它会生成 960px 布局,同样与屏幕宽度无关。另请注意,如果我删除 $base_width: 1160px; 的第一行,它将返回未定义变量的错误。我有什么想法吗?

I'm trying to combine the use of a Sass variable with @media queries as follows:

$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.

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:

@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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

塔塔猫 2025-01-09 09:18:03

这根本不可能。由于触发 @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

This is simply not possible. Since the trigger @media screen and (max-width: 1170px) happens on the client-side.

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.

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:

@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

=base_width_changes($base_width)
    #wrapper
        width: $base_width
不知所踪 2025-01-09 09:18:03

与 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);
    }

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.

    @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);
    }
高跟鞋的旋律 2025-01-09 09:18:03

这对于 SASS 是不可能的,但对于 CSS 变量是可能的(或 CSS 自定义属性)。唯一的缺点是浏览器支持 - 但实际上有一个 PostCSS 插件 - postcss-css-variables - “扁平化”CSS 变量的使用(这也为您提供了对旧版浏览器的支持)。

以下示例非常适合 SASS(并且使用 postcss-css-variables,您也​​可以获得对旧版浏览器的支持)。

SCSS

$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 (它通常会自动执行),这种增加通常可以忽略不计。

CSS

.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;
  }
}

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).

The following example works great with SASS (and with postcss-css-variables you get support for older browsers too).

SCSS

$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

.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;
  }
}
多情出卖 2025-01-09 09:18:03

编辑:请不要使用此解决方案。 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 语句。

Edit: Please do not use this solution. The answer by ronen is much better.

As a DRY solution, you can use the @import statement inside a media query, e.g. like this.

@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.

燃情 2025-01-09 09:18:03

有了 @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
        ));
    }

现在可以有更多的 DRY 媒体查询定位.myDiv 具有一堆不同的值。


地图文档: https://sass-lang.com/documentation/functions/map

示例地图使用:https://www.sitepoint.com/using-sass-maps/

With @ronen's great answer and a map, there's some real power available:

    @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.


Map docs: https://sass-lang.com/documentation/functions/map

Example map usage: https://www.sitepoint.com/using-sass-maps/

物价感观 2025-01-09 09:18:03

我也有同样的问题。

$menu-width 变量在 mobile 视图 @media only 屏幕上应为 240px,在 (max-width : 768px) 上应为 340px。 桌面视图。

所以我简单地创建了两个变量:

$menu-width: 340px;
$menu-mobile-width: 240px;

这是我如何使用它的:

.menu {
    width: $menu-width;
    @media only screen and (max-width : 768px) {
      width: $menu-mobile-width;
    }
}

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.

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;
    }
}
つ可否回来 2025-01-09 09:18:03

两条建议

1
编写适用于小屏幕的“默认”CSS 语句,并仅对大屏幕使用媒体查询。通常不需要 max-width 媒体查询。

示例(假设元素具有“container”类)

@mixin min-width($width) {
  @media screen and (max-width: $width) {
    @content;
  }
}

.container {
  width: 960px;

  @include min-width(1170px) {
    width: 1160px;
  }
}

2 使用 CSS 变量来解决问题,如果 你可以

@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 的 max-width,并且父元素可能有只要 box-sizing 属性设置为 border-box,水平内边距为 5px。解决问题的方法有很多。如果父容器不是 Flex 或网格容器,您可以使用 .container { margin: auto }

Two recommendations

1
Write your "default" CSS statements to be for small screens and only use media queries for larger screens. There's usually no need for a max-width media query.

Example (assuming the element has class "container")

@mixin min-width($width) {
  @media screen and (max-width: $width) {
    @content;
  }
}

.container {
  width: 960px;

  @include min-width(1170px) {
    width: 1160px;
  }
}

2 Use CSS variables to solve the problem, if 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);
}

Note:

Since it will have the width of 1160px when the window has a width of 1170px, it may be better to use a width of 100% and max-width of 1160px, and the parent element might have a horizontal padding of 5px, as long as the box-sizing property is set to border-box. There are a lot of ways to solve the problem. If the parent is not a flex or grid container you might use .container { margin: auto }.

荒岛晴空 2025-01-09 09:18:03

这也可以通过 % 占位符实现。

%占位符可以包含在媒体查询中。因此,您可以设置多个变量以在不同的屏幕尺寸下使用,然后占位符会自动进行相应的预处理。我也在这里使用一些 mixins 来缩短我的媒体查询声明。

在您的 _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; }
    } 

瞧!

我广泛使用这种技术来处理可变字体大小和许多其他事情。

This is also possible with %placeholders.

%placeholders can be wrapped in media queries. So you could set up multiple variables to use at different screen sizes, and then the placeholders would automagically pre-process accordingly. I'm using some mixins to shorten my media query declarations here also.

In your _vars.scss file:

    $width-1: 960px;
    $width-2: 1160px;

In your _placeholders.scss file:

    %variable-site-width                    { 
        @media screen and (max-width: 1170px)       { width: $width-1; }
        @media screen and (min-width: 1171px)       { width: $width-2; }
    }

In your page.scss file:

    .wrapper.     { @extend %variable-site-width; background: red; etc... }

And this will compile to something similar to:

    @media screen and (max-width: 1170px) { 
        .wrapper { width: 960px; }
    }
    @media screen and (min-width: 1171px) { 
        .wrapper { width: 1160px; }
    } 

Voila!

I use this technique extensively for things like variable font sizes and a raft of other things.

农村范ル 2025-01-09 09:18:03

将所有样式(即 SCSS 规则)放入 @mixin 中,然后使用它:

// the mixin's declaration
@mixin someScssRules($base_width) {
    .title {
        width: $base_width;
    }
    ...
}

// the mixin's usage
@media (max-width: 1170px) {
  @include someScssRules(960px);
}

@media (min-width: 1171px) {
  @include someScssRules(1160px);
}

以上所有内容都可以放在同一个 SCSS 文件中。

主题:不要使用 1170px 和 1171px,对最小值和最大值使用相同的值,例如 1170px。

Put all your styles (i.e. SCSS rules) in a @mixin then use it:

// the mixin's declaration
@mixin someScssRules($base_width) {
    .title {
        width: $base_width;
    }
    ...
}

// the mixin's usage
@media (max-width: 1170px) {
  @include someScssRules(960px);
}

@media (min-width: 1171px) {
  @include someScssRules(1160px);
}

All the above could be placed in the same SCSS file.

Of topic: don't use 1170px and 1171px, use the same value for min and max, e.g. 1170px.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文