CSS Styling not 'cascading'? - css

I am updating someones site. Their markup selecting <a> tags is like this:
#wrapper a{color: red;}
Which is fine. But if I create a <div> within wrapper and give it the <a> tags my own styling eg:
.mydiv a{color: white;}
It simply doesnt work - the color:white in my <div> gets overwritten by the color:red in wrapper, even though the .mydiv css is located below the #wrapper css on my external style sheet. Whats more every other styling - background-color, border, etc - works fine!

This is called specificity.
The selector with the id attribute is more specific than the selector with the class attribute (the former points to a single element but the latter points to multiple elements), so the selector with the id takes precedence over yours regardless of the order.
Your selector needs to be more specific in order to override the other selector:
#wrapper .mydiv a{color: white;}

The reason your CSS rule is being overwritten is because the priority of style rules depends largely on the specificity at which they're defined.
.myClass a is less specific than #myID a, as class selection implies a broader range of elements to be affected by the rule than does ID. To ensure that your rule takes precedence over the old one, simply use #wrapper .mydiv a as your selector, thereby enhancing the specificity of your rule to surpass that of the old one.

Related

Why is .a .b{color: #ffffff;} affecting my b class object, but not .b{color: #ffffff;}?

I'm new to css and I'm experimenting with css injections, where I change attributes of a homepage on my browser.
I have an element b which has an ancestor a ( not directly, there a few steps between).
I read multiple times that by using a space between classes e.g. .a .b{} you select all objects of class b that are an descendant of an object of class a.
So injecting.a .b{color: #ffffff;} is changing the color of my object to white as expected. But only using .b{color: #ffffff;} is not, which I don't understand, as it should affect all objects of class b, no matter of their ancestors?
That is most likely because of selector specificity. Your .b is being applied, but there's another style overwriting it. You can inspect element and see what is the style being applied. If you want to make sure it's being applied, you can use .b {color: #fff !important;}
Edit: !important should be used as last resource, its not considered a good practice

Overriding combined css classes

There are numerous questions about the order of loading CSS files and overriding classes, but after reading them I still have something I can't figure out.
There are two CSS files:
<link rel="stylesheet" href="standard.css" type="text/css">
<link rel="stylesheet" href="override.css" type="text/css">
loaded in this order (I checked that).
The HTML looks like this:
<div class="div_D1 ov_D1">
<div class="div_D2 ov_D2">
<div class="div_D3 ov_D3">
blablah
</div>
</div>
</div>
Standard.css contains:
.div_D1{
background: white;
}
.div_D2{
height: 10px;
}
.div_D1 .div_D3{
padding-left: 20px;
}
Override.css contains:
.ov_D1{
background: red;
}
.ov_D2{
height: 50px;
}
.ov_D3{
padding-left: 0px;
}
.ov_D1 and .ov_D2 are applied correctly: the background of .div_D1 is red, the height of .div_D2 is 50px.
.ov_D3 on the other hand does not behave as I expected. If I look at the order the rules are applied, the browser first applies .ov_D3, and then .div_D1 .div_D3, leaving me with an unwanted padding of 20px.
If however I change the class selector in Override.css to
.div_D1 .ov_D3 it does remove the padding.
Also changing the css to
.ov_D3{
padding-left: 0px; !important
}
does the trick. So there are solutions, I only can't understand why with a single selector the order of loading is respected, and with multiple selectors it is not.
This is called specificity of a Selectors. From the book Beginning CSS: Cascading Style Sheets for Web Design, Third Edition by Ian Pouncey and Richard York:
In addition to style sheet precedence, an order of precedence exists for the selectors contained in each style sheet.
This precedence is determined by how specific the selector is.
For example, an ID selector is the most specific,
and the universal selector is the most general. Between these, the
specificity of a selector is calculated using the following formula:
Count 1 if the styles are applied from the (X)HTML style attribute, and 0 otherwise; this becomes variable a.
Count the number of ID attributes in the selector; the sum is variable b.
Count the number of attributes, pseudo-classes, and class names in a selector; the sum is variable c.
Count the number of element names in the selector; this is variable d.
Ignore pseudo-elements.
Now take the four values and put them together in groups of four.
For Example:
Selector : div.someclass.someother
Selector Type : Element Name + Class Name + Class Name
specificity:
0,0,2,1, (a = 0, b = 0,
c = 2, d = 1)
In CSS, there are rules for specificity (quoted from MDN):
The following list of selectors is by increasing specificity:
Universal selectors
Type selectors
Class selectors
Attributes selectors
Pseudo-classes
ID selectors
Inline style
Since you have added specificity to your Selector you weren't able to override by normal CSS class selector.
So your Code
.div_D1 .div_D3is more specific than.div_D3and less specific than.div_D3.ov_D3.
JS Fiddle
As per MDN CSS selectors have rules called 'Specificity' which determine their order of precedence. The more specific a rule is, the greater it's priority regardless of position within a/some stylesheet(s).
A rule such as .class-1 .class-3 has a specificity (it's more specific) higher than .class-3 and takes precedence, as such the less-specific rule cannot override it without the use of !important which negates all other specificity rules. Using the higher specificity rule only takes place with conflicting styles, however.
So, you have set the rule:
.div_D1 .div_D3 { }
The above rule is more specific than:
.ov_D3 { }
Even though they target the same element the rule with the higher specificity takes precedence. You can fix this in your JS Fiddle by prepending the appropriate class structure as defined above.
So, .ov_D3 becomes either:
.div_D1 .ov_D3
or
.ov_D1 .ov_D3
Example here: JS Fiddle

Css selection dependent on different selector's condition

Is it possible to define css class behaves dependent to an other css class?
For example; when
a:hover
Then I want to set
p {background:#fff;}
Is this possible with pure css?
Edit: Assume that no nested relation exist.
If you mean you want all p to have that style when a:hover regardless of where they are in the DOM, then no, you can't do that. You'll need to use a script to apply the style (or some class containing that style) to the p elements when a receives a hover.
if you have a structure like this:
<a><p>...</p></a>
then this:
a:hover p {background: #fff;}
will work. However, block elements should not be placed inside inline elements (in this case, no <p> inside <a>
if your markup is valid, and looks like this:
<p><a>...</a></p>
then you could have
p:hover {background: #fff;}
but a descendant can't affect the parent css (unless you use javascript) while the opposite is true (parent css affects descendants)
I do not see why you would be limited to these restrictions with a littl creativity. if you use fixed positioning the descendant can overlap its parent. and still respond like a descendant.
If the <p> tag immediately follows the <a> tag then you could use the adjacent sibling selector e.g.
a:hover+p{
background:#fff;
}
This is supported in IE8+

Overriding a class in CSS

There are already many questions related to this. But I'm still not clear. Also not sure if the title of the question is correct. Here's my problem:
What the below CSS code means?
#nav li { /*some cssA*/ }
#nav li.over { /*some cssB*/ }
#nav li a { /*some cssC*/ }
#nav li a:hover { /*some cssD*/ }
#nav li ul a span { /*some cssE*/ }
As per my understanding, please correct me if I am wrong:
Line 1: every li element within any element with id="nav" will have styling cssA
Line 2: When I put my cursor over every li element within any element with id="nav" will have styling cssB
Line 3: every a element within every li element within any element with id="nav" will have styling cssC
Line 4: When I hover every a element within every li element within any element with id="nav" will have styling cssD
Line 5: Every span element within every a element within every ul element within every li element within any element with id="nav" will have styling cssE. Also anyother ul or a element will not have this style untill unless the parent element has id="nav"
You are correct on all except .over, The "." represents a class. and "#" represents ID. But yeah, you've got the concept down.
Also, if you want to "Override" as the title says, you'll add
!important
to the end of any rules you want to take precedence over the others.
you can override the css by giving !important or you can give inline style.
priority of inline css is high then external css
All of the existing answers are correct, but there is a bit more to it than has been given already.
As has already been said, "li.over" is a combined selector - it will selector li elements that also have a class of "over". If you wanted to use different CSS properties or property values whilst the mouse is over (hovering over) the element then you use the pseudo class selector "li:hover". These are called pseudo class as you aren't selecting something that is part of the document, but based on the state of an element. There are also pseudo elements which again aren't in the document directly, but logical extensions of the document structure - for example first-child, first-of-type, fifth-of-type, odd items etc.
"#nav li ul a span" is a descendant selector, as you say it will select elements that are children (at any level) of each parent, so "#nav li" selects "li" elements contained within an item with ID "nav" - even several levels down.
If you want to select items that are direct children of the parent then you can use the ">" symbol. I.e. "#nav > li" will select li elements that are directly below any item with an ID of "nav", but not any li elements that are children of that element, or indeed elements below that.
Incidentally "#nav" is exactly equivalent to "*#nav" as it selects any element with the ID, you could also write "ul#nav" if you only wanted to select ul elements with the ID. This could in turn be combined with a class "ul#nav.bar" or even multiple classes "ul#nav.bar.touch".
Removing the space between the selectors like this combines them, so in the last case instead of looking for an item with class "touch" inside an item with class "bar" inside an item with ID "nav" inside a "ul" element, you are selecting a "ul" element with an ID of "nav" and both the classes "bar" and touch". An element like this-
<ul class="bar touch" id="nav">...</ul>
It is also possible to use attribute selectors, so if you wanted to select links which will open in a new window you could use "a[target=_blank]" - which selects based both on the presence of the attribute and the value - or if you wanted to select links with any href value you could use "a[href]". This simply selects all elements with this attribute.
On top of that you can even select items which are adjacent (next to) another element, if you wanted to select all paragraphs directly following an image then you would use "img + p" in your selector, or "p + img" if you wanted to select images directly following a paragraph. As always the last item in the selector is the one the styles are applied to.
It is generally considered good practice not to be overly specific with CSS selectors, as it makes your code much less re-usable. Unless you need to write "div.widget" just write ".widget" as the otherwise you'd not be able to create a "widget" using other elements, and it makes it much harder to override these properties later on in those cases you might need to.
To wrap up selectors, there's a good introduction to CSS selectors on MDN and Code School (paid course provider) also have a excellent online foundation course on CSS available for a very reasonable price which will go through selectors in some detail.
With regard to overriding classes, there are two further concepts you should understand - cascade order and specificity.
Given a HTML snippet of-
<div class="widget">
<p>
Some text you want to style
</p>
</div>
And the following CSS-
#widget p { color: yellow; }
p { color: blue; }
The color of the text would be yellow and not blue because the specificity of the first selector is greater (more specific) than the second. To understand this I suggest you have a play with a Specificity calculator and have a read of the Smashing Magazine tutorial on the subject.
In short though, inline styles trump all, and the more specific a selector the more likely it is to be applied in place of other selectors that would otherwise apply different property values. The value in the selector with the highest specificity score "wins", but other property values from selectors with lower specificity that do not clash will also still be applied to the element.
For example, altering our earlier CSS-
#widget p { color: yellow; }
p {
color: blue;
font-weight: bold;
}
The text will still be yellow, but will also be bold as there is no font-weight property given in the selector with higher specificity.
The last concept you should understand is what happens when two or more rules have identical specificity.
#widget p { color: yellow; }
#widget p {
color: blue;
font-weight: bold;
}
In this case our text is now blue as the second rule appears later in the stylesheet and thus overrides the first. If you have multiple stylesheets then the rules from the last stylesheet to appear in the document head will override rules with identical specificity.
In almost all cases you should use a more specific or the order of the selectors within the stylesheet in order to apply the right styles to the right element, and absolutely should not be routinely using the !important flag to achieve this unless absolutely necessary. See http://james.padolsey.com/usability/dont-use-important/ for a fuller explanation than I give here, but it rapidly becomes unmaintainable (what do you do when everything is "important") and it is also not accessible for users who may wish to override your styles in their user agent stylesheet (local to their browser) in order to help them read or use the page (increasing font size, contrast with background colour etc.)

Combining two selectors in CSS3

Is there anyway to combine two selectors? such as:
#div:hover:not(.class)
Edit:
I understand this work as I wrote. However, how can I achieve a "hover" effect for a "LI" element , but exclude the hover effect when the mouse is over a certain "DIV' inside the LI?
E.G.
<li>Hello <div id="#no-hover">Bye</div> </li>
I would like to get a hover effect for the li:
li:hover{ text-color:#CCC; }
but somehow exclude the hover effect when the mouse is over the #no-hover div.
Any ideas?
Based on your question edit, to maximize browser compatibility (I mean, why not if you can?) you can get away with not using CSS3 selectors at all. Try this, assuming black is the default text color:
li, li:hover div#no-hover {
color: #000;
}
li:hover {
color: #ccc;
}
Although you may want to use a class instead of an ID if you want to affect multiple elements with a no-hover classification. In which case you would do this instead for your first rule:
li, li:hover div.no-hover {
Either way, since selecting a descendant with its ancestor is more specific than selecting just the ancestor, assuming the same combinators on the ancestor it'll override the second rule even though that one comes later.
Update:
If you only want to have the hover effect not applying to Bye, then you can just create an extra hover rule for that and set the color explicitly (as other answers showed).
If the hover effect should not apply to the whole li element, then I think there is no way to do it. You needed some kind of parent selector, which does not exist in CSS.
Yes and it is fairly easy to try: http://jsfiddle.net/5vaUW/
(probably only works if your browser supports CSS3)
You might want to read more about CSS3 selectors, where you can find this:
A selector is a chain of one or more sequences of simple selectors separated by combinators. One pseudo-element may be appended to the last sequence of simple selectors in a selector.
A sequence of simple selectors is a chain of simple selectors that are not separated by a combinator. It always begins with a type selector or a universal selector. No other type selector or universal selector is allowed in the sequence.
A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.
In css2, would be:
li:hover{
color:#CCC;
}
li:hover div{
color: #000;
}
For CSS3, I agree with Felix Kling.

Resources