user246114
user246114

Reputation: 51631

Override one css class with another?

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

Upvotes: 3

Views: 17610

Answers (7)

Marius Schulz
Marius Schulz

Reputation: 16440

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 enforce 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".

Upvotes: 2

Dan F
Dan F

Reputation: 12052

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

Upvotes: 1

Douglas
Douglas

Reputation: 37761

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.

Upvotes: 5

drmonkeyninja
drmonkeyninja

Reputation: 8540

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.

Upvotes: -1

Jeriko
Jeriko

Reputation: 6637

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.

Upvotes: 2

rahul
rahul

Reputation: 187070

Use

li.foo { 
  background-color: green; 
}

Upvotes: 1

Dominic Rodger
Dominic Rodger

Reputation: 99791

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.

Upvotes: 9

Related Questions