CSS rule for classes with number greater than

2019-04-27 01:41发布

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?

标签: css sass less
4条回答
\"骚年 ilove
2楼-- · 2019-04-27 02:21

Preprocessor Not Particularly Needed Under Some Conditions

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.

You Can Reduce the CSS Further

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');
}

Practical Limits

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.

查看更多
Explosion°爆炸
3楼-- · 2019-04-27 02:40

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.

DEMO

查看更多
爷、活的狠高调
4楼-- · 2019-04-27 02:43

you can do either

.thing-1,.thing-2,.thing-3,... { background-image: url('top.png'); }
.thing-20,.thing-21,.thing-22,... { background-image: url('bottom.png'); }

of you can use more than one class for your elements:

.top { background-image: url('top.png'); }
.bottom { background-image: url('bottom.png'); }
.thing-1 { /*only thing-1 related css code*/}
.thing-2 { /*only thing-2 related css code*/}

and use it like:

<div class="top thing-1"></div>
<div class="bottom thing-1"></div>
查看更多
Emotional °昔
5楼-- · 2019-04-27 02:45

Yes, you can do this in LESS. However the code is a bit scary (basically it will require you to learn some advanced LESS concepts) so if your use-case is that simple I guess you'd prefer to just write these things manually (as suggested by @Ashkan).


LESS code:

.thing-1  {background-image: url('top.png')}
.thing-15 {background-image: url('bottom.png')}

.thing(@i) when (@i < 15) {
    .thing-@{i} {&:extend(.thing-1);}
}
.thing(@i) when (@i > 15) {
    .thing-@{i} {&:extend(.thing-15);}
}

.generate-things(@i) when (@i > 1) {
    .generate-things((@i - 1));
    .thing(@i);
}

.generate-things(30);
查看更多
登录 后发表回答