カテゴリー
[Sass] scssで扱う配列でのイテレーションを理解する ~ cssだけでチャートを描画するための前知識
※ 当ページには【広告/PR】を含む場合があります。
2020/05/15
今回はSassでのデータを配列と取り扱う上で、前もって理解しておきたい文法のお話です。
Sassの配列はかなり扱いが厳密ではなく、かなり緩く簡単に使うことができます。
その決まりの緩さ故に、たまにルール無用の配列を使ってしまうと訳が分からないイテレーションになってしまうことがあります。
Sass特有の配列の使い方を理解して、scssで使えるイテレーションのパターンに関してここで復習しておこうというのが今回の記事の目的です。
最終的には、d3jsのようなjs系のライブラリでのスクリプトを介したチャートの描画や、svg要素をxmlでベタ書きで打ち出したグラフなどに頼らない、純粋なcssだけを用いたスタイリンでチャートを描く方法を考えてみたいと思います。
scssの配列の文法色々
Lists contain a sequence of other values.(リストは連続した値を含むもの)
公式にもあるように、一元配列に関しては、丸括弧
()
リスト(配列)
$array: (hoge1, hoge2, hoge3); // コンマ切り
// OR
$array: (hoge1 hoge2 hoge3); // スペース切り
ちなみに、中身なしの0個の要素をもつ場合にもリストが使えます。
一元配列に限れば、釘括弧
[]
$array: [hoge1, hoge2, hoge3]; // コンマ切り
// OR
$array: [hoge1 hoge2 hoge3]; // スペース切り
と出来ます。
むしろこっちの表現の方が、従来の多言語の
配列
sassの配列
実は
()
[]
例えば、配列を先に丸括弧
(hoge1, hoge2, ...)
[piyo1, piyo2,...]
丸括弧の方が釘括弧より強いという微妙な優先順位があるようです。
紛らわしいのがここからで、リストは一元配列と取り扱える場合には、括弧を省略できる仕様になっているため、以下は配列として機能してしまいます。
$array: hoge1, hoge2, hoge3;
// OR
$array: hoge1 hoge2 hoge3;
これはシンタックスシュガー(糖衣構文)であり、見栄えもスッキリするので、他のサイトでもこちらを
sassの配列
Sassの配列の操作色々
配列の取得は組み込み関数の
nth
イテレーションのインデックスは、1からカウント開始するようです。
// nth($array, $index):
nth($array, 1); // hoge1
nth($array, 2); // hoge2
配列の値の長さの取得は
length
// length($array)
length($array); // 3
Sassの配列の位置を取得は
index
// index($array, $element)
index($array, hoge1); // 1
index($array, hoge3); // 3
sassの配列をどう使うべきか?
結論を言うと、私見ではありますが、多次元配列を扱いたい際には、配列を
[]
,
javascriptとも文法的な意味で整合性がとれるので、忘れにくいとも言えます。
// 多次元配列
$itemss: [[black, lime, fuchsia, olive], [blue, aqua], [yellow, red]];
$i: 0; $j: 0;
@each $items in $itemss {
@each $item in $items {
.group#{$i}-element#{$j}-bg {
background: #{$item};
}
$j: $j+1;
}
$i: $i+1;
$j: 0;
}
コンパイル後の出力は、
.group0-element0-bg {
background: black;
}
.group0-element1-bg {
background: lime;
}
.group0-element2-bg {
background: fuchsia;
}
.group0-element3-bg {
background: olive;
}
.group1-element0-bg {
background: blue;
}
.group1-element1-bg {
background: aqua;
}
.group2-element0-bg {
background: yellow;
}
.group2-element1-bg {
background: red;
}
となります。
せっかくなので、同じ結果を得られるような配列の構成パターンを作って実験してみます。
釘かっこ"()"を配列のバウンダリー識別文字に使うパターン
繰り返しになりますが、リストの境界を示す際に
()
$itemss: ((black, lime, fuchsia, olive), (blue, aqua), (yellow, red));
$i: 0; $j: 0;
@each $items in $itemss {
@each $item in $items {
.group#{$i}-element#{$j}-bg {
background: #{$item};
}
$j: $j+1;
}
$i: $i+1;
$j: 0;
}
丸括弧カッコ"()"を使わない配列を使うケース
下のようにスペースとコンマを使うことで、頑張れば2次元の配列を取り扱うこともできます。
$itemss: black lime fuchsia olive, blue aqua, yellow red;
$i: 0; $j: 0;
@each $items in $itemss {
@each $item in $items {
.group#{$i}-element#{$j}-bg {
background: #{$item};
}
$j: $j+1;
}
$i: $i+1;
$j: 0;
}
行列までならシンタックスシュガーでいける感じです。
スペースとコンマを逆に取り扱うケース
ひとつ実験として、先ほどの上のコードの配列でコンマとスペースを入れ替えてたパターンを試してみましょう。
$itemss: black, lime, fuchsia, olive blue, aqua yellow, red;
$i: 0;
$j: 0;
@each $items in $itemss {
@each $item in $items {
.group#{$i}-element#{$j}-bg {
background: #{$item};
}
$j: $j+1;
}
$i: $i+1;
$j: 0;
}
このコードをコンパイルすると以下のような結果になります。
.group0-element0-bg {
background: black;
}
.group1-element0-bg {
background: lime;
}
.group2-element0-bg {
background: fuchsia;
}
.group3-element0-bg {
background: olive;
}
.group3-element1-bg {
background: blue;
}
.group4-element0-bg {
background: aqua;
}
.group4-element1-bg {
background: yellow;
}
.group5-element0-bg {
background: red;
}
となり、期待していた出力とは全く異なった結果になってしまいます。
セパレータ間でも、コンマとスペースでの力関係があり、シンタックスシュガーを使う限りは、コンマが優位になり配列境界を示す文字に役割が変わります。
対して、スペースはあくまでもセパレータ識別記号として認識されるようです。
配列の修正
ではどうしてもスペース文字で配列境界に扱い、配列の中身をコンマ切りにしたいときがあるかも知れません。
どうすれば良いかというと、上記のコードから配列の要素にあたるブロックに
()
[]
$itemss: (black, lime, fuchsia, olive) (blue, aqua) (yellow, red);
$i: 0; $j: 0;
@each $items in $itemss {
@each $item in $items {
.group#{$i}-element#{$j}-bg {
background: #{$item};
}
$j: $j+1;
}
$i: $i+1;
$j: 0;
}
コンマを使わない配列
いっそのこと、コンマ切りを止めたい場合には、
$itemss: (black lime fuchsia olive) (blue aqua) (yellow red);
$i: 0;
$j: 0;
@each $items in $itemss {
@each $item in $items {
.group#{$i}-element#{$j}-bg {
background: #{$item};
}
$j: $j+1;
}
$i: $i+1;
$j: 0;
}
ともできます。
これも期待したコンパイル結果を得ます。
混ぜるな危険ケース
ここまで上のコードサンプルで試したように、sassで配列を扱う場合には、以下の主に3つのパターンが推奨されます。
1. 括弧で配列のバウンダリーを示し、コンマを要素セパレータとして使う
2. 括弧で配列のバウンダリーをを示し、スペースを要素セパレータとして使う
3. コンマで配列のバウンダリーをを示し、スペースを要素セパレータとして使う
詰まりは、
括弧とコンマとスペース
例えば割と無謀とも思える以下の配列も、期待したコンパイル結果を出力します。
$itemss: [black lime fuchsia olive], blue aqua, (yellow, red);
$i: 0;
$j: 0;
@each $items in $itemss {
@each $item in $items {
.group#{$i}-element#{$j}-bg {
background: #{$item};
}
$j: $j+1;
}
$i: $i+1;
$j: 0;
}
まだ要素数も次元数も少ないうちは辛うじて読めるものの、データが複雑になったり、複数の配列を使ったりするほどなにがなんだかわからないようなコードになる温床になります。
例えば更に混ぜてしまった、以下のコードは、果たして上と同じ結果になるでしょうか?
...答え合わせはお手元のコンパイラで是非試してみてください。
$itemss: ((black, lime, fuchsia, olive) blue, aqua [yellow, red]);
$i: 0;
$j: 0;
@each $items in $itemss {
@each $item in $items {
.group#{$i}-element#{$j}-bg {
background: #{$item};
}
$j: $j+1;
}
$i: $i+1;
$j: 0;
}
sassの配列を取り扱うルールのだけは早いうちから気をつけておきたいものです。
Sass配列を使ったイテレーション
ここからは
@each
@forで配列をイテレーションするパターン
上記では全て
@each
$itemss: [[black, lime, fuchsia, olive], [blue, aqua], [yellow, red]];
@for $i from 1 through length($itemss) {
@for $j from 1 through length(nth($itemss, $i)) {
.group#{$i - 1}-element#{$j - 1}-bg {
background: #{nth(nth($itemss, $i), $j)};
}
}
}
コードの行数はスッキリしています。
イテレーションが1から始まるので、要素数のカウントには注意が必要です。
@whileで配列をイテレーションするパターン
最後に
while
continue
break
@while
$itemss: [[black, lime, fuchsia, olive], [blue, aqua], [yellow, red]];
$i: 1;
@while $i <= length($itemss) {
$j: 1;
@while $j <= length(nth($itemss, $i)) {
.group#{$i - 1}-element#{$j - 1}-bg {
background: #{nth(nth($itemss, $i), $j)};
}
$j: $j+1;
}
$i: $i+1;
}
この
@while
ここでもイテレーションが1から始まるので、要素数のカウントや配列要素のアクセスには注意が必要です。
おまけ 〜 今回のスタイルの利用例
せっかくなので、今回のテクニックを使ってを簡単な要素に配列的に取り出したスタイルをhtml要素に適用させてみます。
scssファイルの中身はこちらです。
.circle {
display: inline-block;
width: 20px;
height: 20px;
border-radius: 50%;
}
$itemss: [[black, lime, fuchsia, olive], [blue, aqua], [yellow, red]];
$i: 0; $j: 0;
@each $items in $itemss {
@each $item in $items {
.group#{$i} {
&.element#{$j}-bg {
background: #{$item};
}
}
$j: $j+1;
}
$i: $i+1;
$j: 0;
}
html要素は以下のようなものに適用させます。
<div>
<div class="circle group0 element0-bg"></div>
<div class="circle group0 element1-bg"></div>
<div class="circle group0 element2-bg"></div>
<div class="circle group0 element3-bg"></div>
</div>
<div>
<div class="circle group1 element0-bg"></div>
<div class="circle group1 element1-bg"></div>
</div>
<div>
<div class="circle group2 element0-bg"></div>
<div class="circle group2 element1-bg"></div>
</div>
...何の捻りもなくてすみませんが、見た目は以下のようになります。
まとめ
以上で見てきたように、
(): 丸カッコ
[]: 釘カッコ
,: カンマ
: スペース
Sassはcssと比べて可読性の高いコーディングができるので、他者が読んでも変わりやすい書き方を心掛けるとよいとおもいます。
記事を書いた人
ナンデモ系エンジニア
主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。
カテゴリー