メタ言語の続きです。前回はSass(SCSS)の@import
を使ってBEMのブロックごとにファイルを分けました。今回は変数($
)や@mixin
を使って、モジュールファイルを超えた共通スタイルを設定してみます。それではいきましょう!
【目次】
※参考:前回記事
【Sass(SCSS)】@importでBEMのBlockごとにファイル分割する - クモのようにコツコツと
※メタ言語(HTMLテンプレートエンジン、AltCSS、AltJS)まとめ qiita.com
前回のおさらい
前回、BEMのブロックごとに「_ブロック名.scss」という名のモジュールファイルに分割。全体共通部分の「_base.scss
」も作成。
ファイル名の頭にアンスコ_
を付けると「パーシャル」ファイルとしてコンパイル時に無視される。cssフォルダには本体の「style.css」しかコンパイルれない。
そしてパーシャルを@import
で本体の「style.scss」にインポートするとコンパイル時に読み込まれて合体する。
これによって、ブロックの名前がファインダーで一目瞭然になり、ブロック名が重複する心配もなくなる。
詳細は前回の記事を参照。
※参考:【Sass(SCSS)】@importでBEMのBlockごとにファイル分割する - クモのようにコツコツと
変数($)に共通スタイルの値を設定
変数の書き方
ただ、この状態で作って行った時に、同じような設定のスタイルがモジュールファイルを超えて分散し、修正が大変になりそうな予感がする。
Sass(SCSS)にはそれを解決する方法がある。まずは変数を使ってみたい。
Sass(SCSS)の変数は以前、「CSS変数」の記事でも触れた。*1
※参考:CSS変数でドット絵マリオをルイージにしたった! - クモのようにコツコツと
このような書き方。
/*SCSS変数定義*/
$変数名: 値;
- 変数名の頭にドル
$
を付ける。
※参考:Sass: Variables
_variable.scssを作成
「setting」というフォルダを作ってその中に「_variable.scss」を作成。
ひとまず色関係の変数を設定してみる。
_variable.scss
$base-color: #C30D23; $text-color: #333; $text-color_w: #fff; $bg-color_g: #eee;
それを本体のstyle.scssにインポート。前回の@import
を使う。
@import 'setting/_variable'; /***** base *****/ @import 'base/_base'; /***** block *****/ @import 'block/_main'; @import 'block/_inner';
記述順にコンパイルされるので_variable
は一番上にしてみる。コメントを付けるとコンパイルされてしまうため、コメント無しにしている。
ブロックの色設定を変数に置き換える
各ブロックの色スタイルを変数に置き換えてみる。
_base.secc
body { margin: 0; padding: 0; font-family: sans-serif; color: $text-color; a { color: $base-color; } }
_main.scss
/* main */ .main { width: 960px; margin: 0 auto; &__title { color: $text-color; font-size: 2em; } &__lede { font-size: 1em; } }
_inner.scss
/* inner */ .inner { margin: 0 0 40px; &__title { padding: 10px; background: $bg-color_g; border-left: 2px solid $base-color; font-size: 1.5em; line-height: 1.2; } &__text { &-em { font-weight: bold; background: $bg-color_g; padding: 5px; color: $base-color; } &-bikou { font-size: 0.8em; &:before { content: "※"; } } &-btn { background: $base-color; color: $text-color_w; padding: 10px; } } }
コンパイル結果
これでどうコンパイルされるか確認する。
gulp起動!
npx gulp
ブラウザ立ち上がる。見た目は変わらない!
コンパイルされたCSSも前回と同じ!
style.css
@charset "UTF-8"; /***** base *****/ body { margin: 0; padding: 0; font-family: sans-serif; color: #333; } body a { color: #C30D23; } /***** block *****/ /* main */ .main { width: 960px; margin: 0 auto; } .main__title { color: #333; font-size: 2em; } .main__lede { font-size: 1em; } /* inner */ .inner { margin: 0 0 40px; } .inner__title { padding: 10px; background: #eee; border-left: 2px solid #C30D23; font-size: 1.5em; line-height: 1.2; } .inner__text-em { font-weight: bold; background: #eee; padding: 5px; color: #C30D23; } .inner__text-bikou { font-size: 0.8em; } .inner__text-bikou:before { content: "※"; } .inner__text-btn { background: #C30D23; color: #fff; padding: 10px; }
Sass(SCSS)の変数はファイルを超えても適用されることがわかった!
@mixinで再利用するスタイルを定義
@mixinの書き方
次に@mixin
を使って再利用するスタイルの定義をしてみる。
先程の変数はCSSの「値」の部分を置き換えたが、@mixin
はプロパティと値のセットで設定できる。
@mixin
こんな書き方
@mixin mixin名 { プロパティ1: 値; プロパティ2: 値; プロパティ3: 値; }
@include
で読み込む。@mixin
とセットの存在。
セレクタ { @include mixin名; プロパティ4: 値; プロパティ5: 値; }
コンパイル結果
セレクタ { プロパティ1: 値; プロパティ2: 値; プロパティ3: 値; プロパティ4: 値; プロパティ5: 値; }
mixinのスタイルも一緒にコンパイルされる
引数を使った@mixin
関数のように引数を使うこともできる。
@mixin mixin名($引数1, $引数2) { プロパティ1: $引数1; プロパティ2: $引数2; プロパティ3: 値; }
@include
で読み込む時に引数の値を設定すると
セレクタ { @include mixin名(#fff, 10px); プロパティ4: 値; プロパティ5: 値; }
コンパイル結果
セレクタ { プロパティ1: #fff; プロパティ2: 10px; プロパティ3: 値; プロパティ4: 値; プロパティ5: 値; }
引数が反映されている。
引数に初期値を設定する
コロンで繋いで値を入れると引数の初期値になる
@mixin mixin名($引数1:#fff, $引数2:10px) { プロパティ1: $引数1; プロパティ2: $引数2; プロパティ3: 値; }
@include
でインクルードする時に引数空欄だと初期値が入る
/*引数空欄*/ セレクタ1 { @include mixin名(); プロパティ4: 値; プロパティ5: 値; }
コンパイル結果
/*引数空欄*/ セレクタ1 { プロパティ1: #fff; プロパティ2: 10px; プロパティ3: 値; プロパティ4: 値; プロパティ5: 値; }
引数の上書き(全て)
インクルード時に引数を入力すると値が上書きされる
/*引数上書き(全て)*/ セレクタ2 { @include mixin名(#ccc, 30px); プロパティ4: 値; プロパティ5: 値; }
コンパイル結果
/*引数上書き(全て)*/ セレクタ2 { プロパティ1: #ccc; プロパティ2: 30px; プロパティ3: 値; プロパティ4: 値; プロパティ5: 値; }
引数の上書き(一部)
引数を一部上書きしたい場合は引数名も書く
/*引数上書き(一部)*/ セレクタ3 { @include mixin名($引数2:30px); プロパティ4: 値; プロパティ5: 値; }
コンパイル結果
/*引数上書き(一部)*/ セレクタ3 { プロパティ1: #fff; プロパティ2: 30px; プロパティ3: 値; プロパティ4: 値; プロパティ5: 値; }
mixinを実装してみる
_mixin.scssを作成
実際にやってみる。まず「setting」フォルダに「_mixin.scss」を作成。
「style.scss」で「_mixin.scss」をインポート
@import 'setting/_variable'; @import 'setting/_mixin'; /***** base *****/ @import 'base/_base'; /***** block *****/ @import 'block/_main'; @import 'block/_inner';
_mixin.scssでflexboxのmixinを設定
@mixin
はflexboxとかpositonとかbackgroundとか、複数個のプロパティで指定するスタイルなんかに使うと便利そう。
例えばこの下の方の「ここ押せワンワン」ボタンをflexboxで真ん中寄せにしてみる。
「_mixin.scss」にflexboxの設定を書く。
@mixin flexbox($wrap: nowrap, $justify: flex-start, $align: stretch) { display: flex; flex-wrap: $wrap; justify-content: $justify; align-items: $align; }
mixin
名はflexbox()
flexbox()
の引数は左から$wrap
,$justify
,$align
- 引数
$wrap
の初期値はnowrap
- 引数
$justify
の初期値はflex-start
- 引数
$align
の初期値はstretch
- スタイルの値に3つの引数を設定
index.ejsにflexboxを設定するdivタグを追加
「index.ejs」のボタン部分はfor文の中の. inner__text
に読み込まれている変数inner
<% for (var i = 0; i < inner.length; i++) { %> <section id="nest" class="inner"> <h2 class="inner__title"><%- inner[i].title %></h2> <p class="inner__text"><%- inner[i].text %></p> </section> <% } %>
EJSの設定についてはこちらを参照
※参考:【メタ言語】BEMによるclass名をSass(SCSS)とEJSで書いてみる(モジュール事始め) - クモのようにコツコツと
変数inner
にdiv
タグを追記する。class名は.inner__text-flex
とする。
let inner = [ // 中略 { title:'TypeScriptで書いたクリックイベント', text: '<div class="inner__text-flex"><button class="inner__text-btn">ここ押せワンワン</button></div>' } ]
_inner.scssにflexboxをインクルード
-btn
の手前に-flex
を追記。
_inner.scss
.inner { /* 中略 */ &-flex { @include flexbox($justify: center); } &-btn { background: $base-color; color: $text-color_w; padding: 10px; } } }
-flex
でflexbox
をインクルード。変数$justify
をcenter
に設定
コンパイル結果
ブラウザがリロードされてボタンがセンター寄せになった!
コンパイル結果
index.html
<section id="nest" class="inner"> <h2 class="inner__title">TypeScriptで書いたクリックイベント</h2> <p class="inner__text"><div class="inner__text-flex"><button class="inner__text-btn">ここ押せワンワン</button></div></p> </section>
.inner__text
の中に.inner__text-flex
が追加されている
style.css
.inner__text-flex { display: flex; flex-wrap: nowrap; justify-content: center; align-items: stretch; } .inner__text-btn { background: #C30D23; color: #fff; padding: 10px; }
- .inner__text-flexが追加され、
justify-conten
にはcenter
、それ以外は初期値が入っている
おまけ:@mixinと似ている@extend(スタイルの継承)
@mixin
と似た機能で@extend
というのもある。extendは「継承」という意味。
@mixin
のような設定部分はなく、セレクタのスタイルをそのまま継承する。
セレクタ1 { プロパティ1:値; } セレクタ2 { @extend .セレクタ1; プロパティ2:値; }
@mixin
での@include
と同じ位置づけ。
コンパイルすると継承元にグループ化されるのが@mixin
と異なる。
セレクタ1, セレクタ2 { プロパティ1:値; } セレクタ2 { プロパティ2:値; }
あと、@mixin
のような引数はない。
@mixin
と@extend
の使い分け方など、こちらの記事がわかりやすかった。
※参考:Sassの「@mixinと@extendの違い」と使い分け
最後に
モジュールをファイルで分けると共通スタイルの見通しが悪くなる、と感じてたんですが、変数$
や@mixin
を使えばそれも解消しますね!
ファイルをまたがる設定は「_setting」など別フォルダにしてその中で管理していけばいいと思いました。
ファイル名、フォルダ名などは色々な流儀があり、開発規模によっても変わってくると思います。自分も試行錯誤して行きたく思います。
次回はEJSファイルの方もモジュール分割してみたく思います。それではまた!
※メタ言語(HTMLテンプレートエンジン、AltCSS、AltJS)まとめ qiita.com
*1:昔はネイティブCSSには変数はなかったが、AltCSSの変数が好評だったため正式に採用された、という流れがある