Extending selectors from within media queries with Sass

前端 未结 6 1564
别跟我提以往
别跟我提以往 2020-11-29 00:12

I have an item class and a compact \"modifier\" class:

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

This is fine. How

相关标签:
6条回答
  • 2020-11-29 00:34

    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;
      }
    }
    
    0 讨论(0)
  • 2020-11-29 00:37

    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.

    Cross-Media Query @extend Directives in Sass

    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.

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

    0 讨论(0)
  • 2020-11-29 00:38

    I believe SASS/SCSS does not support the @extend directive inside of a media query. 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.

    0 讨论(0)
  • 2020-11-29 00:42

    The simple answer is: you can't because Sass can't (or won't) compose the selector for it. 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

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

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

    • https://github.com/sass/sass/issues/1050
    • https://github.com/sass/sass/issues/456
    0 讨论(0)
  • 2020-11-29 00:43

    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.

    0 讨论(0)
  • 2020-11-29 00:49

    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! :)

    0 讨论(0)
提交回复
热议问题