CSS规则:为类名中数字大于某个值的元素添加样式

8
我的样式表看起来像这样:
.thing-1 { background-image: url('top.png'); }
.thing-2 { background-image: url('top.png'); }
.thing-3 { background-image: url('top.png'); }
/* etc... */

紧接着这个是:
.thing-20 { background-image: url('bottom.png'); }
.thing-21 { background-image: url('bottom.png'); }
.thing-22 { background-image: url('bottom.png'); }
/* etc... */

我正在寻找一种使用LESS或类似工具简化我的样式表的方法。这是我想要做的:

.thing-[i < 15] { background-image: url('top.png'); }
.thing-[i >= 15] { background-image: url('bottom.png'); }

有没有一种方法可以使用LESS实现这样的效果?如果不是LESS,也许是SASS?

JQuery对此有一些相当不错的解决方案,可以看看这个链接: http://api.jquery.com/category/selectors/我认为,如果您有选择为类命名更具体的名称的选项,这可能是一种方法: http://api.jquery.com/attribute-starts-with-selector/ - grobmotoriker
3
虽然这样做可以让您的CSS编写更简洁,但实际上并不会减小编译后的CSS大小。需要以这种方式生成类名可能是设计缺陷的迹象。 - cimmanon
我完全同意@cimmanon的观点...在此,我尝试直接回答你的问题...但最好的解决方案可能是为每个背景图像只有一个类选择器,并在标记中相应地使用它。 - Martin Turjak
@所有人,很抱歉让大家等了这么久。这可能看起来像一个设计缺陷,但如果你想象一下五线谱上的音符(例如.note-1、.note-2、.note-3),就会更清楚为什么我有这些类了。每个音符都有自己的垂直(有时是水平)位置以及其他样式,所以我希望能够一次性获取所有顶部音符并将它们倒置,使得花梗朝下。感谢大家提供的好主意! - Big McLargeHuge
4个回答

13

由于您要求处理LESS和Sass,这里提供了一些解决方案。您可以在两者中都使用循环来达到目的——但是Sass在此领域稍微强大一些,因为它具有内置的控制指令,如@for@if@while@each。当然,实现这个的方法有多种,但这是我首先想到的:

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

并且 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)); }
}

在这里,您可以获得精确的输出。

但是,要实现更加枯燥的输出,请使用:

LESS:请参见@seven-phases-max's answer。然而,问题在于即使你只有少于15个项目,也必须始终打印出.thing-15。除非您添加另一个保护程序,仅在需要时才添加.thing-15,像这样:

.thing(@i) when (@i = 15) {
    .thing-15 {background-image: url('bottom.png')}
}

你可以尝试在less2css.org上使用Less解决方案。

或者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; }
  }
}

我认为最后一个方案是最优雅的解决方案。

演示


有没有办法检测属性是否小于某个值?例如 img[width<"500"]? - v3nt

5

在某些情况下,预处理器并不是特别必要的

更新:将解决方案完全通用化,允许在thing-#类的任一侧添加额外的类。

对于您正在处理的数字,这是相当实用的。基本上,这种技术类似于我为这个问题所回答的内容,但在您的情况下,代码如下(这里是一个使用背景颜色的微调示例):

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

当它在多个数字进行“一般”选择时,它使用属性选择器,然后过滤掉不适用于特定类的通用选择。

您可以进一步减少CSS

如果您将1-9类更改为具有前导零(thing-01thing-02等),则通用css可以进一步简化为以下内容

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

实际限制

如果需要在非常大的数字处设置断点,过滤的内容会更多,这将变得非常繁琐。但是,可以通过我的原始答案中提到的一些更大的级别来实现断点,在那时,也许可以使用LESS或SCSS来进行断点处理,同时还可以保持输出CSS的低廉。


3
支持这个好主意。我仍然认为这看起来比预处理的输出要乱一些,但我只会使用两个类选择器,而不是有很多具有相同属性的类。无论如何,@ScottS,恭喜您获得LESS银徽章 ;-) - Martin Turjak
@MartinTurjak:感谢祝贺(你比我还早知道!)和投票支持。是的,我的解决方案在外观上看起来有些“凌乱”,但实际上它的CSS代码行数更少,而且我的解决方案适用于所有高于15的值,而你的示例(例如)仅适用于thing-49及以下的值,如果需要适应thing-100,则需要添加另外51行CSS输出,或者是thing-10000...而我的解决方案不管数值高于15多少都保持不变。 - ScottS
我完全同意你的观点(不需要再说服我了 =) - 我的意思是,我甚至不会走OP所走的路线,只保留.bg-top { background-image: url('top.png'); }.bg-bottom { background-image: url('bottom.png'); }或类似的代码 - 这样你就只需要两行CSS =) - Martin Turjak
@MartinTurjak:啊,我明白你的意思了。是的,我不确定为什么这对OP来说不是一个选项。然而,请看一下我的简化代码版本,稍微调整了类结构。此外,我使基本答案完全通用,以允许在“thing-#”类的任一侧使用类。 - ScottS
看起来整洁多了;-)但我已经给了你我的+1呵...啊,你得到了银徽章,所以你不能抱怨=P - Martin Turjak

4

是的,你可以在LESS中实现这个功能。然而,代码有点可怕(基本上需要学习一些高级的LESS概念),所以如果你的用例很简单,我猜你更喜欢手动编写这些内容(正如@Ashkan建议的那样)。


LESS代码:

.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);

昨晚我刚看了你的答案,我们差不多同时回答了同一个问题,但是我忘记点赞了=) 正如我在我的答案中所述,如果您添加一个额外的保护条件,仅当@i = 15时才添加.thing-15,那么您的解决方案将更加通用。 - Martin Turjak
谢谢Martin。是的,它可能会更智能一些,但我不想让它变得更加可怕。我猜还好吧,假设这只是一个例子,你仍然需要手动编辑太多东西(比如如果你需要其他数字,改变所有那些“15”,“30”)... - seven-phases-max

2

你可以选择任意一种方式

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

你可以为元素使用多个类名:

.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*/}

并像这样使用:

<div class="top thing-1"></div>
<div class="bottom thing-1"></div>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接