SASS : &記法による記述をネストを再現しつつ @extend する
月花です。
今日はSASSの備忘録的なTipsです。
SASSでは、 &(アンパサンド, アンド)によって親セレクタを参照することができます。
この親というのは、事実上の親ではなく、あくまでセレクタ記法としての親なので、たとえば .product というセレクタを .product-image の親にすることもできます。
これは別にDOM上の親子でなくともよいのがSASSの強みですが、こうやってこねくり回していると、じゃあこれを @extend で継承し、フォークしたくなったらどうすればよいでしょうか。
<div class="product"> <div class="product-image"><img src="xxxxxx"></div> <div class="product-text">xxxxxxxxx</div> </div>
こういうHTMLと、
.product{ display:block; &-image{ float:left; } &-text{ float:right; } }
こういうSASSがあります。
新しく
<div class="article"> <div class="article-image"><img src="xxxxxx"></div> <div class="article-text">xxxxxxxxx</div> </div>
こういうHTMLができました。
基礎のレイアウトは同じなので、これに当てるSASSは @extend を使ってそこから拡張していきたい、というときに
.product{ display:block; &-image{ // ←ここと float:left; } &-text{ // ←ここってどうやって @extend するの? float:right; } } // だって .article{ @extend .product; &-image{ @extend &-image; // ←ここの & は .article-image だから、 //.article-image-imageになってしまう } &-text{ @extend .product-text; // ←これなら通りそうだけど、全部に書くの? } }
という問題が発生しました。
ちなみに、
.article{ $parent : '.product'; }
単純にこうでいいのではというのは誤りで、コンパイルすると
.product, .article { display: block; } .product-image { float: left; } .product-text { float: right; }
こうなります。
&-text{} というような書き方では、ネスト上では親でもコンパイル後には兄弟になってしまうのです。
自分自身である & を使ってわかりやすく冗長に書きなおすと、
.product{ &{ display:block; } &-text{ float:right; } }
これと等価なので、一見子に見えても実は兄弟を指定しているためです。
Tipsなのでさくさくいきましょう。
変数を使って親の名前を保持しておく
.product{ // ←これを覚えると display:block; &-image{ // ←ここで使える float:left; } &-text{ float:right; } } .article{ $parent : '.product'; // ← 親を覚えて @extend #{$parent}; &-image{ @extend #{$parent}-image; // ← ここで展開 width:80%; } &-text{ @extend #{$parent}-text; color:black; } }
コンパイル後、
.product, .article { display: block; } .product-image, .article-image { float: left; } .product-text, .article-text { float: right; } .article-image { width: 80%; } .article-text { color: black; }
と、正しく @extend できた。
りくつ
SASS では、 #{$variable} と書くことで、文字列として展開することができる。
だから、親を変数に収めて、あとは書き足すだけ。
ちなみに、変数にドットを含めず、ドットを前に出すこともできる。
.article{ $parent : 'product'; @extend .#{$parent}; &-image{ @extend .#{$parent}-image; } &-text{ @extend .#{$parent}-text; } }
もう一段ネストしたら?
もう一段深くなって
.product{ display:block; &-text{ float:right; &-title{ font-weight:bold; } &-description{ font-size:12px; } } }
こう来たら、単純に
.article{ $parent : '.product'; // ←親を覚える @extend #{$parent}; &-text{ $child : #{$parent}-text; // ←子を覚える @extend #{$child}; &-title{ @extend #{$child}-title; // ←子を使う } &-description{ @extend #{$child}-description; } } }
コンパイル後、
.product, .article { display: block; } .product-text, .article-text { float: right; } .product-text-title, .article-text-title { font-weight: bold; } .product-text-description, .article-text-description { font-size: 12px; } .article-text-title { color: red; } .article-text-description { color: black; }
以上です。