olo
olo

Reputation: 5271

CSS selector for multiple different class name combinations

I want to hide a few classes and the classes look like .class-1, .class-2, .class-3..... .class-60 and so on.

I want to hide all class20s, class30s classes and typing each class line is not efficient way to do

.class21,
.class22,
.class23 {
  display: none;
}

I'd like to know is it possible to select classes like below, but if I use something like below, class2 and class3 is selected.

[class^="class2*"],
[class^="class3*"] {
 display: none;
}

or scss way?

Upvotes: 4

Views: 1870

Answers (3)

Josh Crozier
Josh Crozier

Reputation: 240868

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.

Upvotes: 2

Den Isahac
Den Isahac

Reputation: 1525

You can use the nth-child CSS property to target a range of elements. First of all, I'd like you to change your class values from class1..class60 to just a class as is:

<ul>
  <li class="class"></li> <!-- 1st item -->
  ...
  <li class="class"></li> <!-- 60th item -->
</ul>

Then you can use the following CSS declaration to hide the li items from 20th to 39th.

li:nth-child(n+20):nth-child(-n+39) {
  display: none;
}

Upvotes: 0

caramba
caramba

Reputation: 22480

Use *= more explanation about the 30 css selectors you must memorize (starts to get interesting in this case from point 10)

/* get all divs with classes containing *class* */
div[class*=class] {
  border: solid 2px orange;
}

/* get all divs with classes containing *class2* */
div[class*=class2]{
  border: solid 2px green;
}
<div class="class21">xxx</div>
<div class="class22">xxx</div>
<div class="class23">xxx</div>
<div class="class24">xxx</div>

<div class="class31">xxx</div>
<div class="class32">xxx</div>
<div class="class33">xxx</div>
<div class="class34">xxx</div>

Upvotes: 2

Related Questions