sass(scss)の&と変数を利用して親の親であるセレクタを参照する
sass の &(アンパサンド) はとっても便利。
特に BEM やるときは、いちいち block や element を書かずに & で書き足していけばいいのでやりやすい。
例えば以下のようなコードをコンパイルすると
.block{ display: block; &__element{ display: inline-block; &--modifier{ color: #f00; } } }
こうなる。
.block{display:block} .block__element{display:inline-block} .block__element--modifier{color:red}
んだけど、BEM かつシングルクラス設計にすると、例えば modifier に block や element 要素のスタイルを @extend したい。
例えばさっきのコードだったら、
.block{display:block} .block__element{display:inline-block} .block__element--modifier{display:inline-block,color:red}
となってほしかったりする。
そういうとき、以下みたいにセレクタの名前をいちいち調べて @extend するのはちょっとスマートじゃない。
.block{ display: block; &__element{ display: inline-block; &--modifier{ @extend .block__element; color: #f00; } } }
&でうまいことやれないかなと思うけど、&は親の名前なので、以下のようなコードだと意味不明になってしまう。
.block{ display: block; &__element{ display: inline-block; &--modifier{ @extend #{&}; //@extend .block__element--modifer; になってしまう color: #f00; } } }
そこで親の親の部分で、 &を変数に格納しておけば、そのあと引き継ぐことができる。
.block{ display: block; &__element{ display: inline-block; $element: #{&}; &--modifier{ @extend #{$element}; color: #f00; } } }
これをコンパイルすると以下のようになる。
.block{display:block} .block__element,.block__element--modifier{display:inline-block} .block__element--modifier{color:red}
これを応用する場面ですが、例えば @for で回してグリッドを作るとしたら、 コード量が少なく済む。
以下はdisplay: table; 前提のグリッドを任意の block の中で作る mixin のサンプルです。
($parent という命名はいかがなものかと思うが…)
@mixin grids($cols: 12){ $width: 100/$cols; @for $i from 1 through $cols { &__#{$i}{ $parent: #{&}; box-sizing: border-box; display: table-cell; padding: 0 5px; width: $width*$i+0%; &:first-child{ padding-left: 0; } &:last-child{ padding-right: 0; } &--top{ @extend #{$parent}; vertical-align: top; } &--middle{ @extend #{$parent}; vertical-align: middle; } &--bottom{ @extend #{$parent}; vertical-align: bottom; } } } }
これを .grid という block の中で使うとして、コンパイル後
.grid__1,.grid__1--bottom,.grid__1--middle,.grid__1--top{box-sizing:border-box;display:table-cell;padding:0 5px;width:8.33333%} .grid__1--bottom:first-child,.grid__1--middle:first-child,.grid__1--top:first-child,.grid__1:first-child{padding-left:0} .grid__1--bottom:last-child,.grid__1--middle:last-child,.grid__1--top:last-child,.grid__1:last-child{padding-right:0} .grid__1--top{vertic.align:top} .grid__1--middle{vertic.align:middle} .grid__1--bottom{vertic.align:bottom} .grid__2,.grid__2--bottom,.grid__2--middle,.grid__2--top{box-sizing:border-box;display:table-cell;padding:0 5px;width:16.66667%} .grid__2--bottom:first-child,.grid__2--middle:first-child,.grid__2--top:first-child,.grid__2:first-child{padding-left:0} .grid__2--bottom:last-child,.grid__2--middle:last-child,.grid__2--top:last-child,.grid__2:last-child{padding-right:0} .grid__2--top{vertic.align:top} .grid__2--middle{vertic.align:middle} .grid__2--bottom{vertic.align:bottom} .grid__3,.grid__3--bottom,.grid__3--middle,.grid__3--top{box-sizing:border-box;display:table-cell;padding:0 5px;width:25%} .grid__3--bottom:first-child,.grid__3--middle:first-child,.grid__3--top:first-child,.grid__3:first-child{padding-left:0} .grid__3--bottom:last-child,.grid__3--middle:last-child,.grid__3--top:last-child,.grid__3:last-child{padding-right:0} .grid__3--top{vertic.align:top} .grid__3--middle{vertic.align:middle} .grid__3--bottom{vertic.align:bottom} .grid__4,.grid__4--bottom,.grid__4--middle,.grid__4--top{box-sizing:border-box;display:table-cell;padding:0 5px;width:33.33333%} .grid__4--bottom:first-child,.grid__4--middle:first-child,.grid__4--top:first-child,.grid__4:first-child{padding-left:0} .grid__4--bottom:last-child,.grid__4--middle:last-child,.grid__4--top:last-child,.grid__4:last-child{padding-right:0} .grid__4--top{vertic.align:top} .grid__4--middle{vertic.align:middle} .grid__4--bottom{vertic.align:bottom} .grid__5,.grid__5--bottom,.grid__5--middle,.grid__5--top{box-sizing:border-box;display:table-cell;padding:0 5px;width:41.66667%} .grid__5--bottom:first-child,.grid__5--middle:first-child,.grid__5--top:first-child,.grid__5:first-child{padding-left:0} .grid__5--bottom:last-child,.grid__5--middle:last-child,.grid__5--top:last-child,.grid__5:last-child{padding-right:0} .grid__5--top{vertic.align:top} .grid__5--middle{vertic.align:middle} .grid__5--bottom{vertic.align:bottom} .grid__6,.grid__6--bottom,.grid__6--middle,.grid__6--top{box-sizing:border-box;display:table-cell;padding:0 5px;width:50%} .grid__6--bottom:first-child,.grid__6--middle:first-child,.grid__6--top:first-child,.grid__6:first-child{padding-left:0} .grid__6--bottom:last-child,.grid__6--middle:last-child,.grid__6--top:last-child,.grid__6:last-child{padding-right:0} .grid__6--top{vertic.align:top} .grid__6--middle{vertic.align:middle} .grid__6--bottom{vertic.align:bottom} .grid__7,.grid__7--bottom,.grid__7--middle,.grid__7--top{box-sizing:border-box;display:table-cell;padding:0 5px;width:58.33333%} .grid__7--bottom:first-child,.grid__7--middle:first-child,.grid__7--top:first-child,.grid__7:first-child{padding-left:0} .grid__7--bottom:last-child,.grid__7--middle:last-child,.grid__7--top:last-child,.grid__7:last-child{padding-right:0} .grid__7--top{vertic.align:top} .grid__7--middle{vertic.align:middle} .grid__7--bottom{vertic.align:bottom} .grid__8,.grid__8--bottom,.grid__8--middle,.grid__8--top{box-sizing:border-box;display:table-cell;padding:0 5px;width:66.66667%} .grid__8--bottom:first-child,.grid__8--middle:first-child,.grid__8--top:first-child,.grid__8:first-child{padding-left:0} .grid__8--bottom:last-child,.grid__8--middle:last-child,.grid__8--top:last-child,.grid__8:last-child{padding-right:0} .grid__8--top{vertic.align:top} .grid__8--middle{vertic.align:middle} .grid__8--bottom{vertic.align:bottom} .grid__9,.grid__9--bottom,.grid__9--middle,.grid__9--top{box-sizing:border-box;display:table-cell;padding:0 5px;width:75%} .grid__9--bottom:first-child,.grid__9--middle:first-child,.grid__9--top:first-child,.grid__9:first-child{padding-left:0} .grid__9--bottom:last-child,.grid__9--middle:last-child,.grid__9--top:last-child,.grid__9:last-child{padding-right:0} .grid__9--top{vertic.align:top} .grid__9--middle{vertic.align:middle} .grid__9--bottom{vertic.align:bottom} .grid__10,.grid__10--bottom,.grid__10--middle,.grid__10--top{box-sizing:border-box;display:table-cell;padding:0 5px;width:83.33333%} .grid__10--bottom:first-child,.grid__10--middle:first-child,.grid__10--top:first-child,.grid__10:first-child{padding-left:0} .grid__10--bottom:last-child,.grid__10--middle:last-child,.grid__10--top:last-child,.grid__10:last-child{padding-right:0} .grid__10--top{vertic.align:top} .grid__10--middle{vertic.align:middle} .grid__10--bottom{vertic.align:bottom} .grid__11,.grid__11--bottom,.grid__11--middle,.grid__11--top{box-sizing:border-box;display:table-cell;padding:0 5px;width:91.66667%} .grid__11--bottom:first-child,.grid__11--middle:first-child,.grid__11--top:first-child,.grid__11:first-child{padding-left:0} .grid__11--bottom:last-child,.grid__11--middle:last-child,.grid__11--top:last-child,.grid__11:last-child{padding-right:0} .grid__11--top{vertic.align:top} .grid__11--middle{vertic.align:middle} .grid__11--bottom{vertic.align:bottom} .grid__12,.grid__12--bottom,.grid__12--middle,.grid__12--top{box-sizing:border-box;display:table-cell;padding:0 5px;width:100%} .grid__12--bottom:first-child,.grid__12--middle:first-child,.grid__12--top:first-child,.grid__12:first-child{padding-left:0} .grid__12--bottom:last-child,.grid__12--middle:last-child,.grid__12--top:last-child,.grid__12:last-child{padding-right:0} .grid__12--top{vertic.align:top} .grid__12--middle{vertic.align:middle} .grid__12--bottom{vertic.align:bottom}
まあ flexbox を使えるなら、こんなグリッド今時作ることないと思いますけどね!!!!!!
例はともかく、親の親を参照するのに変数に格納しておけば、万が一セレクタ名をタイポしてたとか変更しなきゃいけないときもエラーがでなくてラクチンなのでいいことです。