Specificity clash: Utility class being overwritten by attribute selector - css

In my app, submit buttons and links look identical.
The way I have structured my css is like this:
.button, input[type=submit]{
//default colour
background:grey;
}
.button-primary{
background:green;
}
.button-danger{
background:red;
}
If I wanted a red background on a submit button, I was hoping I would be able to simply add the .button-danger class to it. But unfortunately this does nothing and the submit remains grey, because input[type=submit] is more specific than .button-danger.
What is an elegant way to get around this?

Change your CSS to:
.button, input[type=submit]:not([class^=button-]){
background:grey;
}
What this does is add the :not selector to only style input buttons with the default style, if they dont have subsequent button classes added to them, classes which start with button-
More on :not
The negation CSS pseudo-class, :not(X), is a functional notation
taking a simple selector X as an argument. It matches an element that
is not represented by the argument. X must not contain another
negation selector, or any pseudo-elements.
The specificity of the :not pseudo-class is the specificity of its
argument. The :not pseudo-class does not add to the selector
specificity, unlike other pseudo-classes.

Add something to the selector to make it more specific. For example:
.button-danger, input[type=submit].button-danger {
background:red;
}

Use of "!important keyword" is always possible. something like this:
.button-danger{
background:red !important;
}

Related

Style button when :active different from :hover

I want to make a button that displays a background color when hovering and a button color without a background color when the button is down. Here is my current code:
.windowButton:hover {
background-color:#1a82b8;
}
.windowButton:active #windowClose polygon {
fill:#1a82b8;
}
The problem with the above code is that it turns the icon a color when :active but doesn't remove the background color set by :hover. How do I remove the background color?
You have to set a new background color on :hover state
.windowButton:hover {
background-color:#1a82b8;
}
.windowButton:active {
fill:#1a82b8;
background-color:#000000;/*You can put the color you want*/
}
Pseudo states inherit values. For consistency purposes, it is best to only declare the styles which you are changing in your pseudo state rules.
Note: :hover MUST come after :link and :visited (if they are present) in the CSS definition, in order to be effective!
How about this?
I would guess, its cause on the first property you are using background-color and the second fill.
button:hover {
background-color: red;
}
button:active {
background-color: blue;
}
jsFiddle working example (1)
In order for the active state to be applied while the user is also hovering over the button, it's necessary for the :hover selector to come before the :active selector in the code.
From https://developer.mozilla.org/en-US/docs/Web/CSS/:active:
Styles defined by the :active pseudo-class will be overridden by any
subsequent link-related pseudo-class (:link, :hover, or :visited) that
has at least equal specificity. To style links appropriately, put the
:active rule after all other link-related rules, as defined by the
LVHA-order: :link — :visited — :hover — :active.
While the accepted answer did mention that it's necessary to have :active come after :link and :visited, it doesn't say that it must also come after :hover (since in the example given in the question this was already the case). However this wasn't immediately clear to me, so I wanted to post this answer for anyone else who was stuck like I was because the :hover selector was coming after :active.
Also, I think the LVHA-order is a handy rule to keep in mind and relevant to this question.
`button:hover{background-color: transparent;color: yellow;}
button:active {background: white;color: black;}`

understanding css important keyword in this example

in my html I have
<div id="mainNewsBody" class="news">
<a class="readMore" href="/News/Details/1">read more ...</a>
</div>
I tried to style read more ... snipper with this css
#mainNewsBody .news .readMore a{
color: #7F0609;
}
to actually apply this style I have to use !important keyword in color property.
I know that this !important keyword force to use that property but I do not understand why that is the case here, because I explicitly told to match on particular id with particular class element and inside that element to mach link.
Can someone englight me.
Thanks
Try this one:
.news .readMore {
color: #7F0609;
}
There's no need to call for id and class name for the same element.
It's a.readMore instead of .readMore a (the first case would search for an element with class .readMore and append the CSS to any children a-elements)
and #mainNewsBody .news should be #mainNewsBody.news (you should 'concatenate' the id and class since they refer to the same element)
making a total of #mainNewsBody.news a.readMore
Fiddle
EDIT
I see many notes on simplifying your css to just classes. This really depends on what you're trying to accomplish. If you're working with a huge CSS file, I'd recommend specifying as strict as possible. This to prevent any CSS being applied on places where you don't want it to.
a { } for example will mess with all your links, a.news { } will only mess with a class='news'
It'd the specificity which is troubling you, the more elements class id you have in your selector, more specific your selector is.
So for example
.class a {
}
is more specific than just
a {
}
Just see to it that you do not have a more specific selector, if you've than you need to make the current one more specific or use !important declaration as you stated.
In the above snippet this is incorrect
#mainNewsBody .news .readMore a
It will search for an element having class news inside an element having an id mainNewsBody which is not true in your case so either use this
#mainNewsBody a.readMore {
/* This will be more specific than the below one
as you are using id here and not class */
color: #7F0609;
}
Or use
.news a.readMore {
color: #7F0609;
}
Ozan is right, remove the "mainNewsBody" ID from the CSS if it's not absolutely necessary.
.news .readMore a{
color: #7F0609;}
If you want to be really specific and need to include the ID in the CSS selector remove the space from in-front of ".news"
#mainNewsBody.news .readMore a{
color: #7F0609;}
CSS Tricks - Multiple Class ID Selectors
CSS rules marked !important take precedence over later rules. !important ensures that this rule has precedence.
Probably your code is generating inline css for the a element, or you have another less specific definition for a element with !important keyword somewhere else.
Inline styles have priority higher than styles defined outside the element. To overcome the inline style or a style with !important keyword by a less specific definition, you need to define it by the keyword !important and a more specific definition.

Should the cursor property be set in a rule with or without the :hover pseudo-class?

Say you, or I, have coded an HTML element...
<a id='hydrogen' href='#'>H</a>
...and some :hover CSS...
#hydrogen:hover {
background:red;
}
...and now we want to put a fancy hand cursor when hovering. There's two options for this:
apply to stateless element:
#hydrogen {
cursor:pointer;
}
or, apply to :hover state.
#hydrogen:hover {
color:red;
cursor:pointer;
}
My question: is there any reason(s) why one way is decisively better than the other?
...or is it tomato, tomato?
Compatibility: IE6 and below only recognize the :hover pseudo class on a elements.
They are both the same, provided you always want the pointer there, reguardless of hovering.
The :hover pseudo class will inherit cursor: pointer from its non hovered state.
I would prefer to put it on the normal selector, rather than :hover.
Both ways are equally good. However i would put it on the id itself as :hover does not work on ie6 or below if element is not an anchor. If you do not care about older versions of IE. Then both ways are correct.

CSS select first element with a certain class

What is the syntax for selecting the first element with a certain class? Please specify whether that method of selection is part of CSS3 or CSS2.1.
If you need the first element with a certain class among its siblings, you can use
.myclass {
/* styles of the first one */
}
.myclass ~ .myclass {
/* styles of the others (must cancel the styles of the first rule) */
}
Don't try to use .myclass:not(.myclass ~ .myclass) to do this in only one rule, it won't work since :not() only accepts simple selectors in the parentheses.
If you want the first .myclass in the whole document, there is no way to do it with CSS alone.
The :nth-of-type() or :nth-child() approaches posted are wrong, even if they coincidentally happen to match the elements you want in your page.
Browser support of sibling selector (~): IE7+ and all others.
This problem sucks as bad as the solutions. IMO you should just give the first element a class of .first{} programmatically.
Try this
.testparent .test:first-child {
color: red;
}
<div class="testparent">
<div class="test">test</div>
<div class="test">test</div>
<div class="test">test</div>
</div>
the first div 'test' has red color only.
.class-name:first-of-type {
⋮ declarations
}

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