tags:

views:

70

answers:

7

Hi,

I have a list, with an li style defined. I want to replace the style of an individual element, but it doesn't seem to have any visual effect. Example:

.myList li {
  background-color: yellow;
}

.foo {
  background-color: green;
}

<ul class='myList'>
  <li>Hello</li>
</ul>

When I add an item to the list, it has the .myList li style applied properly. I try now to remove all styles and apply the foo style to a single item (using jquery):

$(item).removeClass();
$(item).addClass("foo");

the item does not change color to green though, but this reports the class is set to 'foo':

alert($(item).attr('class'));

so I guess I'm not understanding css rules here, looks like the li class definition is just overriding whatever else I do, however I want the reverse to be true, I want to override the li style definition with foo. How do we do this?

Thanks

+6  A: 

You're running into problems with specificity, or what other languages call "precedence". You may find Chris Coyier's Specifics on Specificity tutorial helpful.

In brief, more specific means higher precedence:

ul.mylist li.foo {
  background-color: green;
}

Where possible, avoid !important (as someone recommends below) - it's a hack that means (vaguely) that "this rule applies above any other rule". See Chris' comments in the article as to how to use it sensibly.

Dominic Rodger
+1  A: 

Use

li.foo { 
  background-color: green; 
}
rahul
.myList li.foo { background-color: green !important; } will make sure it works as expected (I think).
monkeyninja
A: 

You can force a particular style to override by adding !important to the rule.

.foo { background-color: green!important; }

Although, surprise surprise, I don't think IE6 honours it properly.

Jeriko
`!important` is a sledge hammer, and it only has two states (Oh no! I need to override something !important!). It is **usually** best avoided.
David Dorward
I agree. And I figured there would be other better answers, but sometimes it's all you need :)
Jeriko
I agree with David. Furthermore, IE6 does support it, just so long as you don't do [wacky stuff](http://modxcms.com/about/team/rthrash/css-hacking-important.html) like declare a css property twice but mark the first as !important. Crazy.
Dan F
A: 

Not sure if I am following this correctly, but it sounds like you are correctly adding the class to the list item, but the item still has the ".myList li" style applied as there is no class on the list element to remove. Therefore the original style takes precedence.

monkeyninja
If I'm understanding you correctly (and I'm not sure I am), then you are missing the class being added with JS.
David Dorward
Is the removeClass not being called prior to the class being added?
monkeyninja
+3  A: 

The ".myList li" selector is more specific than the ".foo" selector, so when both rules apply, the item will be yellow. When you do "$(item).removeClass();" you remove any class names from the li, but if the ul still has it's "myList" class name, then the li will still get the styles from the ".myList li" selector.

One way to change the CSS would be to:

.myList li     { background-color: yellow; }
.myList li.foo { background-color: green; }

Then it is clear that the second rule is more specific than the first.

Douglas
Ok I think this works well for what I want to do - but now if I want to set the selector for my list element, the string to use is now the full thing, like: $(item).addClass(".myList li.foo");, right?
Oh just tried, seems to work, and I can reference the selector name just by its last component ("foo"), thanks.
A: 

The li itself doesn't have a class, so calling .removeClass() has nothing to do.

You could do something like

$(item).closest('.myList').removeClass()

and that'd remove the myList class from the entire list, but that's probably not what you want.

I haven't tested this, but something like

li.foo {background-color: green;}

might do the trick to make the browser respect your foo wishes.

I'd suggest reading Andy Clarke's awesome CSS: Specificity Wars to fully grok css specificity

Dan F
A: 

CSS works with precedences which are given to different selectors based on a point system. The selector with the most points "wins" and determines the element's style.

  1. Simple selector (e.g. p, li, ul, body, ...): 1 point
  2. Class (e.g. .foo, ...): 10 points
  3. Pseudo class (e.g. :hover, :focus, :active, ...): 10 points
  4. ID (e.g. #wrapper, #content, #header, ...): 100 points
  5. style="..." (e.g. style="color: red"): 1000 points

You can use the attribute "!important" to enforche the highest precedence. Note that IE 6 does ignore this attribute completely.

If even the summed points of two styles equal each other, the one later defined "wins".

Marius Schulz
Cool thanks for the breakdown.