CSS
less

LESSでループ処理を実装する方法

More than 5 years have passed since last update.

LESSでも連番でクラスを定義したいことってありますね。
共通部分を関数にして、手動で連番を列挙する方法があります。

less
.foo(@num) {
    (~".foo-@{num}") {
        // style...
    }
}

.foo(1);
.foo(2);
.foo(3);
// ...
.foo(99);
.foo(100);

ただ、これが数十行ともなると書くのも大変ですし、LESS自体の見通しも悪くなりますね。プログラミングをやったことがある人であれば、for などのループで回せないかと考えると思います。

しかし、LESSはループ構文をサポートしていません。なので、再帰関数とLESSのガード(when)を使ってループっぽいことをします。このトリックはTwitter Bootstrapで使われています。

less
.iterate(@i) when not (@i < 10) { } // ループを抜けるために必要
.iterate(@i) when (@i < 10) {
    (~".test@{i}") {
        width: @i;
    }

    .iterate(@i + 1); // 次のループへ
}

.iterate(0); // ループを実行

これをコンパイルすると、次の通りループした結果のCSSが生成されます。

.test0 {
  width: 0;
}
.test1 {
  width: 1;
}
.test2 {
  width: 2;
}
.test3 {
  width: 3;
}
.test4 {
  width: 4;
}
.test5 {
  width: 5;
}
.test6 {
  width: 6;
}
.test7 {
  width: 7;
}
.test8 {
  width: 8;
}
.test9 {
  width: 9;
}

ちなみに、上のLESSをPHPで表現するとしたら下記のようなコードになります。PHPにはガードがありませんが、if分岐でガードします。再帰はLESSと同じですね。

<?php
function iterate($i) {
    if ( $i < 10 ) { // ガード
        echo ".test{$i} { width: {$i} }\n";

        iterate($i + 1); // 再帰
    } else {
        return;
    }
}

iterate(1);

LESSでループを実装するとトリッキーなコードになるので、ループを多く書く必要がある場面では、SaSSなどの別のツールと組み合わせたほうがいいかもしれませんね。