简体   繁体   English

使用Sass扩展媒体查询中的选择器

[英]Extending selectors from within media queries with Sass

I have an item class and a compact "modifier" class: 我有一个item类和一个紧凑的“修饰符”类:

.item { ... }
.item.compact { /* styles to make .item smaller */ }

This is fine. 这可以。 However, I'd like to add a @media query that forces the .item class to be compact when the screen is small enough. 但是,我想添加一个@media查询,当屏幕足够小时强制.item类紧凑。

On first thought, this is what I tried to do: 首先想到的是,这就是我试图做的事情:

.item { ... }
.item.compact { ... }
@media (max-width: 600px) {
  .item { @extend .item.compact; }
}

But this generates the following error: 但是这会产生以下错误:

You may not @extend an outer selector from within @media. 你可能不会在@media中扩展外部选择器。 You may only @extend selectors within the same directive. 您只能在同一指令中@extend选择器。

How would I accomplish this using SASS without having to resort to copy/pasting styles? 如何使用SASS完成此操作而无需使用复制/粘贴样式?

The simple answer is: you can't because Sass can't (or won't) compose the selector for it. 简单的答案是:你不能因为Sass不能(或不会)为它组成选择器。 You can't be inside of a media query and extend something that's outside of a media query. 您不能进入媒体查询并扩展媒体查询之外的内容。 It certainly would be nice if it would simply take a copy of it instead of trying to compose the selectors. 如果只是简单地复制它而不是试图组合选择器,那肯定会很好。 But it doesn't so you can't. 但事实并非如此。

Use a mixin 使用mixin

If you have a case where you're going to be reusing a block of code inside and outside of media queries and still want it to be able to extend it, then write both a mixin and an extend class: 如果你有一个案例,你将要重新使用媒体查询内外的代码块,并希望它能够扩展它,那么写一个mixin和一个extend类:

@mixin foo {
    // do stuff
}

%foo {
    @include foo;
}

// usage
.foo {
    @extend %foo;
}

@media (min-width: 30em) {
    .bar {
        @include foo;
    }
}

Extend the selector within a media query from the outside 从外部扩展媒体查询中的选择器

This won't really help your use case, but it is another option: 这对您的用例不会有所帮助,但它是另一种选择:

%foo {
  @media (min-width: 20em) {
    color: red;
  }
}

@media (min-width: 30em) {
  %bar {
    background: yellow;
  }
}

// usage
.foo {
  @extend %foo;
}

.bar {
  @extend %bar;
}

Wait until Sass lifts this restriction (or patch it yourself) 等到Sass取消这个限制(或自己修补)

There are a number of ongoing discussions regarding this issue (please don't contribute to these threads unless you have something meaningful to add: the maintainers are already aware that users desire this functionality, it's just a question of how to implement it and what the syntax should be). 关于这个问题有很多正在进行的讨论(请不要对这些线程做出贡献,除非你有一些有意义的东西要添加:维护者已经意识到用户需要这个功能,这只是一个如何实现它的问题以及语法应该是)。

For the record, here is how I ended up solving the problem with only duplicating generated styles once: 为了记录,这里是我最终解决问题的方法,只复制一次生成的样式:

// This is where the actual compact styles live
@mixin compact-mixin { /* ... */ }

// Include the compact mixin for items that are always compact
.item.compact { @include compact-mixin; }

// Here's the tricky part, due to how SASS handles extending
.item { ... }
// The following needs to be declared AFTER .item, else it'll
// be overridden by .item's NORMAL styles.
@media (max-width: 600px) {
  %compact { @include compact-mixin; }

  // Afterwards we can extend and
  // customize different item compact styles
  .item {
    @extend %compact;
    /* Other styles that override %compact */
  }
  // As shown below, we can extend the compact styles as many
  // times as we want without needing to re-extend
  // the compact mixin, thus avoiding generating duplicate css
  .item-alt {
    @extend %compact;
  }
}

I believe SASS/SCSS does not support the @extend directive inside of a media query. 我相信SASS / SCSS不支持媒体查询中的@extend指令。 http://designshack.net/articles/css/sass-and-media-queries-what-you-can-and-cant-do/ http://designshack.net/articles/css/sass-and-media-queries-what-you-can-and-cant-do/

You might need to use a mixin instead, though the code bloat needs to be weighed against your objective. 您可能需要使用mixin,尽管代码膨胀需要与您的目标进行权衡。

This is the cleanest, partial solution I've found. 这是我发现的最干净,最局部的解决方案。 It takes advantage of @extend where possible and falls back to mixins when inside media queries. 它尽可能利用@extend,并在内部媒体查询时回退到mixins。

Cross-Media Query @extend Directives in Sass Sass中的跨媒体查询@extend指令

See the article for full details but the gist is that you call a mixin 'placeholder' that then decides whether to output @extend or an @include. 有关详细信息,请参阅文章,但要点是您调用mixin'占位符',然后决定是输出@extend还是@include。

@include placeholder('clear') {
   clear: both;
   overflow: hidden;
}

.a {
    @include _(clear);
}
.b {
    @include _(clear);
}
.c {
    @include breakpoint(medium) {
      @include _(clear);
   }
}

Ultimately it may not be better than just using mixins, which is currently the accepted answer. 最终它可能不仅仅是使用mixins,这是目前公认的答案。

I use breakpoints, but it's the same idea: 我使用断点,但它是相同的想法:

@mixin bp-small {
    @media only screen and (max-width: 30em) {
        @content;
    }

How to use it: 如何使用它:

.sidebar {
    width: 60%;
    float: left;
    @include bp-small {
        width: 100%;
        float: none;
    }
}

There is a text about mixins where you can find out more about this option. 有关于mixins 的文本 ,您可以在其中找到有关此选项的更多信息。

Could you restructure? 你可以重组吗?

.compact { //compact-styles }
.item {}
.item.compact { @extend .compact } 

@media (max-width: 600px) {
    .item { @extend .compact; }
}

If I understand the documentation correctly, that should work. 如果我正确理解文档,那应该有用。 I think the reason the way you're trying won't work is that it doesn't see .item.compact when it's parsing the @extend, but that's an uninformed guess, so take that with a truck load of salt! 我认为你尝试的方式不起作用的原因是它在解析@extend时没有看到.item.compact,但这是一个不知情的猜测,所以用一卡车加盐吧! :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM