I personally elaborate 3 possible solutions, starting from the easiest one, and then optimize it until 3rd. Easiest has a better readability, hardest uses a double nested LOOP.
Here, I report "common" code between 3 solutions (I decided to mantain separated possible sizes definitions, to be more intuitive):
@sm-screen:~"(min-width: 320px)";
@md-screen:~"(min-width: 720px)";
@lg-screen:~"(min-width: 1200px)";
@xs-gutter:20px;
@sm-gutter:30px;
@md-gutter:40px;
@lg-gutter:50px;
@property:padding;
//@property:margin;
Note that @property
could be "margin
" or "padding
" indifferently, simply switching comment.
To this variable definition you can append the following 3 proposals:
SOLUTION 1
This is the easiest solution. The drawback is that it generates a different mediaquery for each rule, resulting in redundant code:
.side(top, right, bottom, left);
.side(@possible-values...)
{
.generate-property-loop(1, @possible-values);
}
.generate-property-loop(@var; @possible-values) when (@var <= length(@possible-values))
{
//Let's extract values in @var position from list @possible-values
@direction: extract(@possible-values, @var);
.@{property}.@{direction}
{
@{property}-@{direction}: @xs-gutter;
@media @sm-screen
{
@{property}-@{direction}: @sm-gutter;
}
@media @md-screen
{
@{property}-@{direction}: @md-gutter;
}
@media @lg-screen
{
@{property}-@{direction}: @lg-gutter;
}
}
.generate-property-loop((@var + 1), @possible-values);
}
SOLUTION 2
A possible solution is to move mediaquery outside LOOP but it continues to require explicit mediaquery definition:
.side(top, right, bottom, left);
.side(@possible-values...)
{
.generate-property-loop(1, @possible-values, @xs-gutter);
@media @sm-screen
{
.generate-property-loop(1, @possible-values, @sm-gutter);
}
@media @md-screen
{
.generate-property-loop(1, @possible-values, @md-gutter);
}
@media @lg-screen
{
.generate-property-loop(1, @possible-values, @lg-gutter);
}
}
.generate-property-loop(@var, @possible-values, @gutter) when (@var <= length(@possible-values))
{
//Let's extract values in @var position from list @possible-values
@direction: extract(@possible-values, @var);
.@{property}
{
&.@{direction}
{
@{property}-@{direction}: @gutter;
}
}
.generate-property-loop((@var + 1), @possible-values, @gutter);
}
SOLUTION 3
With a double nested loop, you can achieve the total flexibility, simply passing "directions" and "scren-size" as parameters, but at cost of a minor readability:
.side(top, right, bottom, left);
.side(@possible-values...)
{
.generate-property-loop(1, @possible-values, @xs-gutter);
.mediaquery-loop(sm,md,lg);
}
.mediaquery-loop(@possible-screens...)
{
.generate-mediaquery-loop(1, @possible-screens);
}
.generate-property-loop(@var, @possible-values, @gutter) when (@var <= length(@possible-values))
{
@direction: extract(@possible-values, @var);
.@{property}
{
&.@{direction}
{
@{property}-@{direction}: @gutter;
}
}
.generate-property-loop((@var + 1), @possible-values, @gutter);
}
.generate-mediaquery-loop(@var, @possible-sizes) when (@var <= length(@possible-screens))
{
@sizes: extract(@possible-sizes, @var);
@screen-size: ~"@{sizes}-screen";
@gutter-size: ~"@{sizes}-gutter";
@media @@screen-size
{
.generate-property-loop(1, @possible-values, @@gutter-size);
}
.generate-mediaquery-loop((@var + 1), @possible-screens);
}