In SCSS
, you can use @mixin
and @extend
to reuse code. For example:
%even-row { background: pink; }
@mixin even-rows-mixin($columns) {
@for $i from 1 through $columns {
&:nth-child(#{2 * $columns}n + #{$i + $columns}) {
@extend %even-row;
}
}
}
li {
@include even-rows-mixin(8);
width: 12%;
}
Will generate:
li:nth-child(16n + 9),
li:nth-child(16n + 10),
li:nth-child(16n + 11),
li:nth-child(16n + 12),
li:nth-child(16n + 13),
li:nth-child(16n + 14),
li:nth-child(16n + 15),
li:nth-child(16n + 16) {
background: pink;
}
li {
width: 12%;
}
However, I'd like to use that mixin
inside a media query, which is not possible:
@media (max-width: X) {
li {
@include even-rows-mixin(8);
width: 12%;
}
}
@media (max-width: Y) {
li {
@include even-rows-mixin(4);
width: 16%;
}
}
This will throw an error:
You may not @extend an outer selector from within @media. You may only
@extend selectors within the same directive. From "@extend %even-row"
on line N.
I could just remove @extend
and inline the properties in the mixin
:
@mixin even-rows-mixin($columns) {
@for $i from 1 through $columns {
&:nth-child(#{2 * $columns}n + #{$i + $columns}) {
background: pink;
}
}
}
But that will generate duplicated code:
@nth-child(16n + 9) { background: pink; }
@nth-child(16n + 10) { background: pink; }
...
@nth-child(16n + 16) { background: pink; }
I wonder if there's a better way to write this code without generating duplicated properties or having to write all the possible selectors manually, maybe using interpolation or some other feature I'm not aware of.
This question came to me after answering this other question: How to select even rows with list items, just as a reference if you want to take a look to the whole thing.
You can construct a selector variable with the entire selector group.
@mixin even-rows-mixin($columns, $rule) {
$selector : '';
@for $i from 1 through $columns {
$selector: $selector + $rule + '('+ #{2 * $columns}n + "+" + #{$i + $columns} + ') ,';
}
#{$selector} {
@content;
}
}
li {
width: 12%;
}
@include even-rows-mixin(8, 'li:nth-child') {
background-color: pink;
};
Note: For some reason its not working in codepen editor. But it's working with node-sass