0

I set dynamically classes on elements with class names "displayIfYes_%%" where %% comes from a database and can have a lot of values.

I am trying to set a simpler CSS selector for the classes I don't want to display, but I can't find how to do it.

I have a working solution to display elements only when value is "yes" using this CSS:

.displayIfYes_yes {visibility: inherit !important;}
.displayIfYes_na, 
.displayIfYes_no,
.displayIfYes_scaled,
.displayIfYes_raw
/* ... and so on for any additionnal value */
{display: none !important;}

I want a selector to select any element which has class which begins with "displayIfYes" but does not end with "yes".

TylerH
  • 20,799
  • 66
  • 75
  • 101
Eric Malalel
  • 185
  • 1
  • 17

3 Answers3

1

you can use selector [attribute|="value"] in this case your attribute can be class.

So:

[class|="displayIfYes"]{
/* */
}

will select class attribute which starts with that. The only complication is class attribute can have more than 1 class so this solution might not always work.

In that case I recommend using different classes for different scenarios from the database. You can create a class for each scenario such as;

.na, 
.no,
.scaled,
.raw {
    /* other styles */
}
.displayIfYes {
    display: none !important;
}
pegasuspect
  • 991
  • 4
  • 15
1

The traditional way to solve this problem is to use a “base” class, then override with more specific classes. In your case, this would be:

.display-if-yes {
  display: none;
  /* Other styles which apply to all types */
}

.display-if-yes-yes {
  display: unset;
  visibility: inherit;
}
<div class="display-if-yes display-if-yes-yes">Yes</div>
<div class="display-if-yes display-if-yes-no">No</div>
<div class="display-if-yes display-if-yes-other">Other</div>

If you are unable to change your class structure for some reason, this should work for your specific requirements:

.displayIfYes_yes {
  /* visibility: inherit; */
  color: red;
}

*[class^='displayIfYes_']:not(.displayIfYes_yes),
*[class*=' displayIfYes_']:not(.displayIfYes_yes) {
  /* display: none; */
  color: green;
}
<div class="displayIfYes_yes">displayIfYes_yes</div>
<div class="displayIfYes_no">displayIfYes_no</div>
<div class="displayIfYes_other">displayIfYes_other</div>

I’ve commented out your specific styles just for the sake of the demo.

MTCoster
  • 5,868
  • 3
  • 28
  • 49
1

Here's a solution without using the :not() selector, instead only relying on attribute and class selectors and the underlying specificity.

Also, you can't override display: none; with visibility: inherit. Use display: initial instead.

[class^="displayIfYes_"] {display: none;}
.displayIfYes_yes {display: initial;}
<div class="displayIfYes_yes">div.displayIfYes_yes</div>
<div class="displayIfYes_na">div.displayIfYes_na</div>
<div class="displayIfYes_no">div.displayIfYes_no</div>
<div class="displayIfYes_scaled">div.displayIfYes_scaled</div>
<div class="displayIfYes_raw">div.displayIfYes_raw</div>
Constantin Groß
  • 10,719
  • 4
  • 24
  • 50
  • Thanks it works perfectly. I just have to change [class^="displayIfYes_"] by [class*="displayIfYes_"] since targeted elements can have multiple classes and I am not responsible for setting order of classes. – Eric Malalel Jul 18 '19 at 10:19