简体   繁体   中英

Nested css selectors by adding to class name in SASS

I am building a flexbox grid system and am looking to keep my scss file manageable.

What is wrong with the selectors for elements with classes col-2, col-4, col-6 that are causing them not to work?

.grid-container{
max-width:1280;
margin: 0 24px;
display: flex;

    [class^="col"]{
        flex:1;
        margin: 0 8px;

        &:first-child{
            margin-left:0;
        }
        &:last-child{
           margin-right:0;
        }

        [class*="-2"]{
            width:16.5%;
        }

        [class*="-4"]{
            width:33%;
        }

        [class*="-6"]{
            width:50%;
        }
    }
}

All columns are getting the styling for margin and the first-child and last-child behavior but not the width from the other selectors. Is this perhaps a flexbox issue? flex-basis?

It's not a "flexbox" issue. It's a "CSS" issue.

[class^="col"] {
   [class*="-2"] {
       width:16.5%;
   }
}

will result in this CSS:

[class^="col"] [class*="-2"]{width:16.5%;}

But you probably want...

[class^="col"][class*="-2"]{width:16.5%;}

... which would be produced by...

[class^="col"] {
   &[class*="-2"] {
       width:16.5%;
   }
}

The space (in CSS) and the ampersand & (in SCSS) are the differences.

[class^="col"] {
  [class*="-2"] {
    width: 16.5%;
  }
  [class*="-4"] {
    width: 33%;
  }
  [class*="-6"] {
    width: 50%;
  }
}

Will produce the following selectors:

[class^="col"] [class*="-2"] {}
[class^="col"] [class*="-4"] {}
[class^="col"] [class*="-6"] {}

Notice the space between each attribute selector. The selectors above will first search for and element that has a class attribute that starts with the .col class. They then find an element nested within the .col element with a class attribute that contains -2 , -4 or -6 somewhere in the attribute.

By adding an ampersand & you can capture the current selector path. The following SCSS is the same as what you have now:

[class^="col"] {
  & [class*="-2"] {
    width: 16.5%;
  }
}

Compiles to (space between attribute selectors):

[class^="col"] [class*="-2"] {}

Placing the ampersand immediately before the nested selector (like you have with first-child and last-child ) gives a different result, the one you (likely) want:

[class^="col"] {
  &[class*="-2"] {
    width: 16.5%;
  }
}

Compiles to (no space between attribute selectors):

[class^="col"][class*="-2"] {}

IMHO what you have currently is over engineered. I'd suggest something more straightforward and flexible. Use regular class selectors.

.col {    
  &-2 { width: 16.5%; }
  &-4 { width: 33%; }
  &-6 { width: 50%; }    
}

[class*="col-"] {
  flex: 1;
  margin: 0 8px;

  &:first-child { margin-left: 0; }
  &:last-child { margin-right: 0; }
}

See below Stack Snippet to see what the above is compiled to. Note that I used *= (asterisk equals) instead of ^= (caret equals) for class placement flexibility. Up to you if you want to enforce column classes to be the first class in the class attribute value.

https://codepen.io/anon/pen/yXveRq

 .row { display: flex; } .col-2 { width: 16.5%; } .col-4 { width: 33%; } .col-6 { width: 50%; } [class*="col-"] { flex: 1; margin: 0 8px; } [class*="col-"]:first-child { margin-left: 0; } [class*="col-"]:last-child { margin-right: 0; } 
 <div class="row"> <div class="col-4">Col 1</div> <div class="col-4">Col 2</div> <div class="col-4">Col 3</div> </div> 

CoJanks. The quick and dirt fix is to set additional definitions to the 'flex' on the .col class in the .grid-container.

Here is a quick and dirty answer to solve your problem for ya!

flex:1 1 auto;

FYI. There were some discrepancies in class nesting as well that I covered in the link provided.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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