You could always negate .class2 and .class3 using the :not() pseudo-class:
[class^="class2"]:not(.class2),
[class^="class3"]:not(.class3) {
color: #f00;
}
[class^="class2"]:not(.class2),
[class^="class3"]:not(.class3) {
color: #f00;
}
<div class="class1">don't select</div>
<div class="class2">don't select</div>
<div class="class3">don't select</div>
<div class="class4">don't select</div>
<div class="class21">select</div>
<div class="class22">select</div>
<div class="class23">select</div>
<div class="class24">select</div>
<div class="class31">select</div>
<div class="class32">select</div>
<div class="class33">select</div>
<div class="class34">select</div>
Keep in mind that the attribute selector [class^="class2"] will select class attributes starting with the substring class2. If you want to cover cases where there are multiple classes and class2 isn't the first class, then it gets a little complex because you also need to account for whitespace:
[class^="class2"]:not(.class2),
[class*=" class2"]:not(.class2),
[class^="class3"]:not(.class3),
[class*=" class3"]:not(.class3) {
color: #f00;
}
[class^="class2"]:not(.class2),
[class*=" class2"]:not(.class2),
[class^="class3"]:not(.class3),
[class*=" class3"]:not(.class3) {
color: #f00;
}
<div class="another class1">don't select</div>
<div class="another class2">don't select</div>
<div class="another class3">don't select</div>
<div class="another class4">don't select</div>
<div class="another class21">select</div>
<div class="another class22">select</div>
<div class="another class23">select</div>
<div class="another class24">select</div>
<div class="another class31">select</div>
<div class="another class32">select</div>
<div class="another class33">select</div>
<div class="another class34">select</div>
You could alternatively just select all .class2*/.class3* combinations, and then override the CSS for .class2/.class3 back to their initial state.
For instance:
[class^="class2"],
[class^="class3"] {
color: #f00;
}
.class2,
.class3 {
/* Reset all styles back to their initial state */
color: initial;
}
[class^="class2"],
[class^="class3"] {
color: #f00;
}
.class2,
.class3 {
/* Reset all styles back to their initial state */
color: initial;
}
<div class="class1">don't select</div>
<div class="class2">don't select</div>
<div class="class3">don't select</div>
<div class="class4">don't select</div>
<div class="class21">select</div>
<div class="class22">select</div>
<div class="class23">select</div>
<div class="class24">select</div>
<div class="class31">select</div>
<div class="class32">select</div>
<div class="class33">select</div>
<div class="class34">select</div>
Due to how inflexible these approaches are, elements with a class such as class2-block will also be selected since the end of the class isn't being checked.
With that being said, it may be safer just to use a CSS preprocessor to generate the combinations.
For instance, here is a simple loop in LESS:
.class39 {
color: #f00;
}
@iterations: 38;
.loop (@i) when (@i > 19) {
.class@{i}:extend(.class39) {}
.loop(@i - 1);
}
.loop (@iterations);
Which would compile to:
.class39, .class38, .class37, .class36, .class35, .class34, .class33,
.class32, .class31, .class30, .class29, .class28, .class27, .class26,
.class25, .class24, .class23, .class22, .class21, .class20 {
color: #f00;
}
.class39, .class38, .class37, .class36, .class35, .class34, .class33,
.class32, .class31, .class30, .class29, .class28, .class27, .class26,
.class25, .class24, .class23, .class22, .class21, .class20 {
color: #f00;
}
<div class="class1">don't select</div>
<div class="class2">don't select</div>
<div class="class3">don't select</div>
<div class="class4">don't select</div>
<div class="class21">select</div>
<div class="class22">select</div>
<div class="class23">select</div>
<div class="class24">select</div>
<div class="class31">select</div>
<div class="class32">select</div>
<div class="class33">select</div>
<div class="class34">select</div>
Likewise, you could also use the following SCSS:
$count: 20;
%class-list {
color: #f00;
}
@mixin class-loop {
@for $i from 39 through $count {
.class#{$i} { @extend %class-list; }
}
}
@include class-loop;
Which would compile to the same as the LESS results.