6

I have this markup where the ids are not known in advance:

#product-20625055 { background-color: #FC0; }
#product-66980342 { background-color: #0CF; }
#product-54722210 { background-color: #F0C; }
<div class="product" id="product-20625055">Product 1</div>
<div class="product" id="product-66980342">Product 2</div>
<div class="product" id="product-54722210">Product 3</div>

I need to change the background color of all divs. This is the most specific selector I could think of but it does not work:

div.product[id^="product-"] { background-color: transparent; }

Could this be done without hard-coding ids, using !important and changing HTML markup?

ivan_pozdeev
  • 33,874
  • 19
  • 107
  • 152
Salman A
  • 262,204
  • 82
  • 430
  • 521
  • Selectors which include and `#id` selector are as specific as you can get, because they are meant to be unique. If you really can't follow standard CSS guidelines and delete the id selectors, you have to not follow standard CSS guidelines and use `!important`. It's not always evil. – Rhumborl Jan 28 '16 at 13:07
  • You could possibly move the specific background color tag to a before css element, and override them with you .product class. – Kao Jan 28 '16 at 13:11
  • 2
    The three `id` selectors have a specificity of 100 whereas the `div.product[id^="product-"]` has a specificity of only 021 and so will not override the background color. You need to use an `id` selector to have a chance of overriding without using hard-coding/important. So maybe you can assign an `id` to the body and use `#id div.product[id^="product-"]`. – Harry Jan 28 '16 at 13:14

11 Answers11

7

Instead of resorting to !important, you might want to consider using the :not() pseudo-class to increase the specificity of your selector, like this:

div.product:not(#specificity-hack) { background-color: transparent; }

This matches the same elements as your original selector (assuming that specificity-hack is not a possible ID for a product div, which seems likely here), but since selectors inside :not() are included in the specificity calculation, it counts as more specific than the rules you're trying to override.

(The main reason not to use !important if you can avoid it is that it's addictive — the only way to override an !important rule is with another !important rule, so the more you use it, the more you'll find yourself needing it. Eventually, half your CSS rules will be marked !important, and you're basically back where you started, except that now your style sheets are bloated with lots of !important markers, and you've also effectively deprived yourself of the ability to use !important to override normal styles in the rare cases where it's actually legitimately useful, and now have to resort to specificity hacks like the one shown above. Moral of the story: !important is powerful but easy to abuse — don't use it unless you really have to!)

Community
  • 1
  • 1
Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153
  • 2
    +1 Funny how this was asked so soon after you commented on my answer. I also appreciate the irony of a selector called `:not(#specificity-hack)`. – BoltClock Jan 28 '16 at 15:57
3

I think this is one of those cases where !important might be the best option.

#product-20625055 {
  background-color: #FC0;
}
#product-66980342 {
  background-color: #0CF;
}
#product-54722210 {
  background-color: #F0C;
}
div[id^="product-"].product {
  background-color: transparent !important;
}
<div class="product" id="product-20625055">Product 1</div>
<div class="product" id="product-66980342">Product 2</div>
<div class="product" id="product-54722210">Product 3</div>
Paulie_D
  • 107,962
  • 13
  • 142
  • 161
3

All the three id selectors that are used in your snippet have a specificity of 100 whereas the selector which you are using to try and override (div.product[id^="product-"]) has a specificity of only 021 (because it has one class selector, one attribute selector and one element type selector).

You cannot override the id selector unless you use another id selector as part of the full selector (adding an id selector anywhere will suffice) (or) use !important (or) use inline styles. Because unless an id selector is added the first digit will always be 0 and so will be less specific than the id selectors.

Since you cannot hardcode the id of each element (as it is random), the only option would be to add an id to a parent element and then use it as part of the selector like I had mentioned in my comment. The id could be added to a common parent (or) if there is no parent then to the body.

#product-20625055 {
  background-color: #FC0;
}
#product-66980342 {
  background-color: #0CF;
}
#product-54722210 {
  background-color: #F0C;
}
#id div.product[id^="product-"] {
  background-color: transparent;
}
<div id='id'>
  <div class="product" id="product-20625055">Product 1</div>
  <div class="product" id="product-66980342">Product 2</div>
  <div class="product" id="product-54722210">Product 3</div>
</div>
Harry
  • 87,580
  • 25
  • 202
  • 214
  • A good work around, I didn't think of that when I wrote my comment, but this involves changing markup (whether that really is impossible for the OP, or "just because", I don't know) – Rhumborl Jan 28 '16 at 14:31
  • @Rhumborl No, it doesn't really need a change of markup (I mean it doesn't need a change to the HTML file itself) because `id` can be added through other means also. Plus, OP says without hard coding id and without using `!important`, so the only way is to add an `id` selector as part of the complex selector. – Harry Jan 28 '16 at 14:33
  • This is a good second option (first if I had some control over the parent elements). – Salman A Jan 28 '16 at 16:42
  • @SalmanA: Yup, I get you. Ilmari's answer suits your case wonderfully well :) – Harry Jan 28 '16 at 16:46
0

Maybe you could choose the div's by class (because they all have the same) and add !important

.product {
   background: transparent!important;
}
Marcel Wasilewski
  • 2,519
  • 1
  • 17
  • 34
0

use the css !important feature this is useful in situations as you are currently in. But be causious while using it dont use it excesively in your css files. It is used in css to overide rules. Whenever you put it after any css rule that !important will make sure to use that rule over any other rule defined anywhere in any css files you are using.

#product-20625055 { background-color: #FC0 !important ; }
#product-66980342 { background-color: #0CF !important ; }
#product-54722210 { background-color: #F0C !important ; }
0

Straight from https://developer.mozilla.org/en/docs/Web/CSS/Specificity#The_!important_exception

When an !important rule is used on a style declaration, this declaration overrides any other declarations.

You can use !important to override any css

<div class="product" id="product-20625055">Product 1</div>
<div class="product" id="product-66980342">Product 2</div>
<div class="product" id="product-54722210">Product 3</div>

#product-20625055 { background-color: #FC0; }
#product-66980342 { background-color: #0CF; }
#product-54722210 { background-color: #F0C; }

.product {background-color: transparent !important;}
ARIF MAHMUD RANA
  • 5,026
  • 3
  • 31
  • 58
0

The attribute selector for [id....] needs to be altered to do a prefix value match ([id^="product"]), also since ID will take preference you will need !important after applying the transparent bgcolor. See below for html sample.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        <!--
        #product-20625055 { background-color: #FC0; }
        #product-66980342 { background-color: #0CF; }
        #product-54722210 { background-color: #F0C; }

        div.product[id^="product"] {
            background-color: transparent!important;
        }
        -->
    </style>
</head>
<body>

<div class="product" id="product-20625055">Product 1</div>
<div class="product" id="product-66980342">Product 2</div>
<div class="product" id="product-54722210">Product 3</div>



</body>
</html>
SHOGUN.IO
  • 1
  • 2
0

Just add to your body or other element which wraps your products some ID and

#product-20625055 {
  background-color: blue;
}
#wrapper .product[id^="product-"] {
  background-color: red;
}
<div id="wrapper">
  <div class="product" id="product-20625055">Product 1</div>
</div>
Narek-T
  • 1,898
  • 10
  • 20
0

Selector div.product[id*="product-"] will works! if you have to rewrite already existing property, you have to use !important:

#product-20625055 { background-color: #FC0; }
#product-66980342 { background-color: #0CF; }
#product-54722210 { background-color: #F0C; }

div.product[id*="product-"] {
  background-color: green!important;
}

jsfiddle-link

Igor Ivancha
  • 3,413
  • 4
  • 30
  • 39
-1

you can use this

:nth-child(number) {css declarations;} Example:

div.product:nth-child(1){ 
background-color:white; 
}

div.product:nth-child(2){ 
background-color:blue; 
}

div.product:nth-child(3){ 
background-color:yellow; 
}
Salman Aziz
  • 426
  • 8
  • 15
-3

You can override the ID selector Using this code [id|="product"] or the div.product:not(#product) selector:

#product-20625055 { background-color: #FC0; }
#product-66980342 { background-color: #0CF; }
#product-54722210 { background-color: #F0C; }

/* You Can Use This Selector */
[id|="product"] {
  background-color: transparent !important;
}

/* Or This Selector */
div.product:not(#product) { background-color: transparent; }
<div class="product" id="product-20625055">Product 1</div>
<div class="product" id="product-66980342">Product 2</div>
<div id="product-54722210" class="product">Product 3</div>

Another practice is to have classes rather than ids in your css, so they can be easily overrided.

    .product-20625055 { background-color: #FC0; }
    .product-66980342 { background-color: #0CF; }
    .product-54722210 { background-color: #F0C; }
    
    
    .product { background-color:transparent; }
    
<div class="product product-20625055" id="product-20625055">Product 1</div>
    <div class="product product-66980342" id="product-66980342">Product 2</div>
    <div id="product-54722210" class="product product-54722210">Product 3</div>