My stylesheet looks like this:
.thing-1 { background-image: url('top.png'); }
.thing-2 { background-image: url('top.png'); }
.thing-3 { background-image: url('top.png'); }
/* etc... */
Followed by this:
.thing-20 { background-image: url('bottom.png'); }
.thing-21 { background-image: url('bottom.png'); }
.thing-22 { background-image: url('bottom.png'); }
/* etc... */
I am looking for a way to simplify my stylesheet with LESS or something similar. Here's what I'd like to do:
.thing-[i < 15] { background-image: url('top.png'); }
.thing-[i >= 15] { background-image: url('bottom.png'); }
Is there a way I can do something like this with LESS? If not LESS, maybe SASS?
The greater than sign (>) selector in CSS is used to select the element with a specific parent. It is called as element > element selector. It is also known as the child combinator selector which means that it selects only those elements which are direct children of a parent.
As a special case for increasing specificity, you can duplicate weights from the CLASS or ID columns. Duplicating id, class, pseudo-class or attribute selectors within a compound selector will increase specificity when overriding very specific selectors over which you have no control.
As you are asking for LESS and Sass, here are some solutions. You can achieve it in both with looping through values - but Sass is a bit stronger in this field as it has built-in control directives like @for
, @if
, @while
and @each
. There are of course multiple ways of implementing this but this were the first that came to mind:
LESS:
.bg (@i) when (@i < 15) { background-image: url('top.png'); }
.bg (@i) when (@i >= 15) { background-image: url('bottom.png'); }
.things (@max, @i: 1) when (@i < @max) {
.thing-@{i} { .bg (@i); }
.things (@max, (@i + 1));
}
.things(50);
and SCSS:
@function bg($i) {
@if $i < 15 { @return 'top.png' }
@else { @return 'bottom.png' }
}
@for $i from 1 through 50 {
.thing-#{$i} { background-image: url(bg($i)); }
}
where you achieve your exact output.
But a more dry output would be achieved with:
LESS: see @seven-phases-max's answer. However, there is the problem of always having to print out .thing-15
also if you only have less than 15 items. Unless you add another guard that adds .thing-15
only when needed like so:
.thing(@i) when (@i = 15) {
.thing-15 {background-image: url('bottom.png')}
}
you can try out the Less solutions at less2css.org
or SCSS:
%bg-top { background-image: url('top.png'); }
%bg-bottom { background-image: url('bottom.png'); }
@for $i from 1 through 50 {
.thing-#{$i} {
@if $i < 15 { @extend %bg-top; }
@else { @extend %bg-bottom; }
}
}
The last one in my opinion is the most elegant solution.
Update: Made the solution fully general to allow for extra classes on either side of thing-#
class.
This is fairly practical with the numbers you are dealing with. Basically the technique is similar to what I answered for this question, but in your case the code is as follows (here is a tweaked example just using background color):
[class*="thing-"] {
background-image: url('top.png');
}
[class*="thing-1"]:not(.thing-1):not(.thing-10):not(.thing-11):not(.thing-12):not(.thing-13):not(.thing-14),
[class*="thing-2"]:not(.thing-2),
[class*="thing-3"]:not(.thing-3),
[class*="thing-4"]:not(.thing-4),
[class*="thing-5"]:not(.thing-5),
[class*="thing-6"]:not(.thing-6),
[class*="thing-7"]:not(.thing-7),
[class*="thing-8"]:not(.thing-8),
[class*="thing-9"]:not(.thing-9) {
background-image: url('bottom.png');
}
It uses the attribute selector when it is doing a "general" selection across multiple numbers, and then filters out for specific classes that the general should not apply to.
If you change your 1-9
classes to have preceeding zeros (thing-01
, thing-02
etc.), then the general css can be reduced further to this:
[class*="thing-"] {
background-image: url('top.png');
}
[class*="thing-"]:not([class*="thing-0"]):not(.thing-10):not(.thing-11):not(.thing-12):not(.thing-13):not(.thing-14) {
background-image: url('bottom.png');
}
This would all get very cumbersome if a break point at a very large number was needed, as more filtering would need to occur. But still some larger levels can be achieved for breaking as my original answer for the other question demonstrated, and at that point, perhaps using LESS or SCSS to somehow do the break pointing might be possible, while still keeping output CSS low.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With