The title basically says it all.
Suppose I have an element which I want to change color on :hover, but while clicked, I want it to switch back to its original color. So, I've tried this:
a:link, a:visited, a:active {
background: red;
}
a:hover {
background: green;
}
As it turns out, this doesn't work. After a lot of head-scratching, I realized that the :hover state was overriding the :active state. This was easily solved by this:
a:link, a:visited {
background: green;
}
a:hover {
background: red;
}
a:active {
background: green;
}
(I could combine the 1st rule with the 3rd one).
Here's the fiddle: http://jsfiddle.net/V5FUy/
My question: is this the expected behavior? As far as I understand this, the :active state should always override the :hover state, since the :active state will almost always be accompanied with the :hover state.
yes this is expected behavior,
lets take a look at another example. just adding two classes,
<ul>
<li class="item first">item</li>
<li class="item">item</li>
<li class="item">item</li>
<li class="item">item</li>
<li class="item last">item</li>
</ul>
here the class first also comes together with the class item.
but if we declare our css in the wrong order that would not give the wanted behavior
.first { background: blue; }
.item { background: red; }
as you can see, the last matching selector will be used.
it is the same as your example, no mather what is more logic,
the 2 pseudo-classes are concidered equal, thus the same rules apply
the last matching defenition wins.
edit
pseudoclasses are equals, it is the one defined last that wins! here is a jsFiddle that proves my point :link defined after :hover, :link wins (test) so, your statement of :hover overriding :link is wrong, its just the same like with :active, its all about the order.
The active state must be declared after the hover state, in your CSS you're clumping together the active state before the active state so it's not being triggered.
If you state the proper order of operation it works, like below, it works fine.
a.noworks:link, a.noworks:visited {
background: red;
}
a.noworks:hover {
background: green;
}
a.noworks:active {
background: red;
}
So, to answer your question, yes this is the expected behavior.
Here is the order of operation:
a:link
a:visited
a:hover
a:active
Because in the first code you defined :hover after you defined :active, so :hover "overwrote" :active. In the second, it's the other way around, :active overwrites :hover.
EDIT:
Sorry, I misunderstand the question.
Basically when you are in active state (with a mouse pointer) you are actually in hover state too. So based on CSS rules it would read the last one in stylesheet.
When you hover over a link and hold down the mouse key It's like this if we take pseud classes as normal classes :
<a class="active hover"></a>
So if your css was
.active{color:green}
.hover{color:red}
it would apply red
but if your css was
.hover{color:red}
.active{color:green}
It would apply green
From W3C
a:link { color: red } /* unvisited links */
a:visited { color: blue } /* visited links */
a:hover { color: yellow } /* user hovers */
a:active { color: lime } /* active links */
Note that the A:hover must be placed after the A:link and A:visited
rules, since otherwise the cascading rules will hide the 'color'
property of the A:hover rule. Similarly, because A:active is placed
after A:hover, the active color (lime) will apply when the user both
activates and hovers over the A element.
This is how it works, and I'll try to explain why. As we know CSS will continue searching the document when applying styles and apply the style that is most specific to the element.
Example:
li.betterList { better list styling here }
Is more specific and will overwrite
li { list styling here }
And these Puesdo selectors are all considered the same specificity and thus the last line will overwrite the previous one. This is confirmed by the note on W3Schools
Note: :active MUST come after :hover (if present) in the CSS definition in order to be effective!
you can also throw this CSS on your jsfidle and watch it overwrite since they are the same specificity
.works {background: red}
.works {background: green}
This is the expected behavior in so far as most people always place the :hover pseudo-class at the end of the group of rules.
Order of declaration matters with pseudo-classes (see more here: http://reference.sitepoint.com/css/pseudoclasses), so the final rules get precedence, as with other rules in CSS.
For most people, I think the desired behavior:
a:link {
⋮ declarations
}
a:visited {
⋮ declarations
}
a:hover {
⋮ declarations
}
Since the :active is not so useful it is left out... or combined with a:link and a:visited... and then it is overridden by a:hover
W3C spells it out here:
Note that the A:hover must be placed after the A:link and A:visited
rules, since otherwise the cascading rules will hide the 'color'
property of the A:hover rule. Similarly, because A:active is placed
after A:hover, the active color (lime) will apply when the user both
activates and hovers over the A element.
http://www.w3.org/TR/CSS2/selector.html#dynamic-pseudo-classes
Even W3schools gets this one right:
Note: a:hover MUST come after a:link and a:visited in the CSS
definition in order to be effective!!
Note: a:active MUST come after a:hover in the CSS definition in order
to be effective!!
http://www.w3schools.com/css/css_pseudo_classes.asp
I think you should at least consider the flow of User Interaction on links (or buttons).
Usually,
:link has always been the default (untouched),
Then when a User points to the button, then that is where :hover comes into play.
Once a User points to the link or button, then he/she will click, that is where :active comes in.
That is the standard sequence of how we interact with links (or buttons). With the exception of :visited, where the result is only obvious when the User has previously pressed the link.
It would be really helpful if you keep in mind the mnemonic: ' L o V e H A t e ' when dealing on links (except for :visited, which doesn't work for buttons).
However, if you really want to do an override, say, you want to change the color of a link that was already visited on active state, you can do something like:
a:visited:active {
color: red;
}
But the bottom line is, avoid changing the standard sequence if it's not necessary.
You can have the :active pseudo-class override the :hover pseudo-class regardless of the order of declaration by using the :not() selector.
a:link, a:visited, a:active {
background: red;
}
a:hover:not(:active) {
background: green;
}
This way, the :hover selector is triggered only when the :active selector is not.
Related
Sample code: http://jsfiddle.net/RuQNP/
<!DOCTYPE html>
<html>
<head>
<title>Foo</title>
<style type="text/css">
a:link, a:visited {
color: blue;
}
a:hover, a:active {
color: red;
}
.foo a:link, .foo a:visited {
color: green;
}
/* A possible fix */
/*
.foo a:hover, .foo a:active {
color: red;
}
*/
</style>
</head>
<body>
<div class="foo">
Example
</div>
</body>
</html>
What I was expecting:
The link would appear red on hover.
What I get:
The link appears green on hover.
Questions:
Why does the color defined in .foo a:link, .foo a:visited
selector override the one in a:hover, a:active? What's going on?
I understand that I can fix it and get what I expect by uncommenting
the commented code. However, I want to know how can we correct the
.foo a:link, .foo a:visited selector such that it does not
override the color defined in a:hover, a:active?
If I understand http://www.w3.org/TR/CSS21/cascade.html#specificity properly (Thanks, BoltClock), this is the specificity table for the various selectors in the code.
a:link - 0 0 1 1
a:visited - 0 0 1 1
a:hover - 0 0 1 1
a:active - 0 0 1 1
.foo a:link - 0 0 2 1
.foo a:visited - 0 0 2 1
So, the style defined for .foo a:link overrides the style for a:hover when both link as well as hover pseudo-classes apply to an A element of class foo.
Similarly, the style defined for .foo a:visited overrides the style for a:hover when both visited as well as hover pseudo-classes apply to an A element of class foo.
When you first started with CSS, you might have learned about the LoVe-HAte mnemonic for the order in which to specify link selectors (a:link, a:visited, a:hover, a:active). Have you ever wondered why this mnemonic was chosen?
Well, there's a note in the spec on how the link and dynamic pseudo-classes are treated when multiple rules using all of them apply to the same element, which explains why you need to set link selectors in that order:
Note that the A:hover must be placed after the A:link and A:visited rules, since otherwise the cascading rules will hide the 'color' property of the A:hover rule. Similarly, because A:active is placed after A:hover, the active color (lime) will apply when the user both activates and hovers over the A element.
Anyway, the point I'm trying to make above is that all four pseudo-classes, being pseudo-classes, have equal specificity. Everything else about specificity applies. In this case, out of a bunch of equally specific selectors, the last rule is applied. When or how each pseudo-class is triggered is never relevant.
Now, the simple introduction of the .foo selector causes your second set of link/visited rules to override your first set of link/visited styles and the hover/active styles, forcing links in elements with that class to always appear green until you add hover/active styles with the .foo selector.
Sorry if my answer seems stitched-up or slipshod by the way, I'm typing this on my iPhone right now and it's pretty hard to think out here...
This is how I understand it. All these pseudo classes have same specificity, so the pseudo class written at last wins. Now what do pseudo-classes :link, :visited, :focus, :hover, :active do? Let us see one by one.
a: link{color: red} tells the user agent to color the anchor element red in any state. Run the following script:
a:link {
color: red;
}
Go to stackoverflow
The anchor element is colored red in the following states if and only if the link is unvisited,
Unvisited
hovered
Focused(Tabbed)
Active(Clicked)
So, a: link{color: red} tells the user agent to give red color to anchor element in all of the above states. Now let's compare it with a:hover pseudo-class. Run the following script
a:hover {
color: red;
}
Go to stackoverflow
The anchor element is colored red in the following states,
hovered
Active(clicked)
We see that both :link and :hover pseudo classes are capable to define the hover state -- So if you assign these two pseudo-classes to a particular element then the one mentioned at last in the css file wins. This is the reason we say :link will override :hover when the former is mentioned below the later. The same concept holds for other pseudo-classes. I'd like to give list of what every pseudo class do.
a:link {...} sets the following states of an unvisited link
- Focused(Tabbed)
- hovered
- Active(Clicked)
link state will override every other state.
a:visited {...} sets the following states of a visited link:
- Focused(Tabbed)
- hovered
- Active(Clicked)
a:visited {...} will override every other state except :link if and only if the link has been visited.
Note that visited means it must be considered visited as per user agent's cache. E.g. a website visited 10 days ago might not be in user agent's cache then it'd be technically considered unvisited.
a:focus {...} sets the following states for both visited and unvisited links:
- Focused(Tabbed)
- hovered
- Active(Clicked)
a:focus {...} overrides :hover and :active states.
a:hover {...} sets the following states to both visited and unvisited links:
- hovered
- Active(Clicked)
a:hover {...} overrides :active state
a:active {...} sets the following states for both visited and unvisited links:
Active(Clicked)
To fix it, put the .foo ... selector first and add !important to the color value for the other link/visited selector, like this:
a:link, a:visited {
color: blue;
}
a:hover, a:active {
color: red !important;
}
.foo a:link, .foo a:visited {
color: green;
}
The reason that the .foo a:link, .foo a:visited selector overrides the other selector no matter where you put it is that because .foo a:link is more specific than a:link. (ditto for :visited.) So the .foo ... selector will always override the a:link,a:visited selector because it has a parent class name, so it's more specific.
(Also read #BoltClock's answer about LoVe - HAte - that's part of the problem.)
I've just wasted an afternoon figuring out that the a:visited selector in CSS has all attributes disabled apart from a handful that are directly related to colour (see here: http://www.impressivewebs.com/styling-visited-links/ ).
Anyway, I'm wondering if it's possible to unset an attribute set for a:link? I have an a:link selector that fills in the background with a CSS gradient, but it would be nice if this could go grey for a:visited.
According to the new implementation, you can set background-color for a:visited, but unfortunately this gets overridden by the background attribute for a:link because a:visited can't use background now.
All I'd like to do is unset background for a:visited so that background-color is used. Does anyone know if this is possible?
use a instead of a:link for background color
see fiddle here
a{
background: green;
}
a:visited{
background: orange;
}
Give your hyperlink a display style of inline-block
a{
display: inline-block;
background-color: red;
//this becomes the default bgcolor; override it in subsequent pseudo state styles
}
This allows you to specify background colors for your hyperlinks.
You have to normally specify the styles for hyperlinks in the following order
a:link - a normal, unvisited link
a:visited - a link the user has visited
a:hover - a link when the user mouses over it
a:active - a link the moment it is clicked
In this order the visited link style overrides the normal link style. So, your css for visited will be applied after you click the link.
Make sure that you declare a:visited after the a. Otherwise the a will overrule it.
a {
background: #ff0000;
}
a:visited {
background: url( none );
}
It seems the following variants produce identical results:
/* 1 */
a, a:visited, a:active { color: black; }
a:hover { color: red; }
/* 2 */
a, a:link, a:visited, a:active { color: black; }
a:hover { color: red; }
/* 3 */
a:link, a:visited, a:active { color: black; }
a:hover { color: red; }
Most guidance on the web uses 2 or 3. Why not go for the simplest variant which is 1? I cannot find a good reason to ever apply :link if all you need is one style for normal links and one for hover.
Is it best-practice to not use :link? Why or why not?
I don't care whether the link is visited or not. Both receive the same style. I only care about hover or not hover. This question is not about what the variants do - all do the same thing. It is about what the best variant is. Is one of the variants faulty? Which one is best-practice?
Because not every a is a link.
<a name="table_of_contents">Table of Contents</a>
isn't a link, it's an anchor that can be linked to with <a href="#table_of_contents">.
a will match it, a:link won't.
It is used to differentiate between simple anchors and anchors with href attributes. See demo jsfiddle here.
<style>
a { color: red; }
a:link { color: blue; }
</style>
<a name="anchor">No href</a><br />
With href
EDIT:
For this reason, it is important to cover all cases in your CSS. Option 2 is the only option that completely covers all cases. If you do not have anchor elements without href attributes, you are safe with option 1.
a:link is specifically for links that have not been visited. a applies to all <a> elements.as you said
I don't care whether the link is visited or not
then you may avoid the use of a:link ...use of only a...a:hover...a:active will satisfy your need
and also a:link wont work if there is no href in your anchor but a will do
I suppose you can use
<a>
to create a button so that could produce alternate results...
I always use a:link
It solely depends on your intention, so for your example, I would simply style all anchor elements one color and only change the style when the element is hovered.
a {color: #000;}
a:hover {color: #f00;}
In your case, you are only changing the color of the link when it's hovered. You need to add the hover pseudo element after the base rule otherwise it would be overridden due to the cascading of the style sheet.
If you were to use all of the psuedo elements in this case and you wanted the only difference to be the hover it would look like this:
a:link, a:visited, a:focus, a:active {color: #000;}
a:hover {color: #f00;}
The pseudo-class names are self explanatory:
:link - any unvisited link
:visited - any visited link
:active - when the link is active, e.g. when it's clicked or activated with a keyboard event
:focus - when the link gains focus, e.g. when a user tabs through the elements and it is the selected element
:hover - when it's hovered or moused over
The benefit of using a pseudo-class is that it will have a higher specificity than just targeting the anchor element. However, in your case it may not be needed.
I have this problem in css where i have two different states in css for example
#koolbutton .active {
color: #fff
}
#koolbutton{
color: #ccc //not active
}
When i try this html
<button id ="koolbutton" class="active">
It gives me the the normal grey koolbutton not the active one which is white! thanks
You need to omit the space between #koolbutton and .active.
#koolbutton { /*not active*/ }
#koolbutton.active { /*active*/ }
The issue is with your first selector:
#koolbutton .active
Since there is a space between the id and class selector, this applies to every element with a class of active and an ancestor with an id of koolbutton. What you want is to select every element with a class of active and an id of koolbutton:
#koolbutton.active
Although the order of your selectors doesn't matter due to CSS Specificity rules, in terms of creating more maintainable CSS I would recommend you put the default styles first, followed by any variations to that style:
#koolbutton { /* default styles */ }
#koolbutton.active { /* .active styles */ }
#koolbutton.foo { /* Another class styles */ }
If you are really wanting to style active/focus states, you should probably look at the :focus and :active pseudo selectors.
You may try this one also;
#koolbutton:active {
color: #fff; //when user click the button
}
#koolbutton{
color: #ccc; //normal display of button
}
Here is the working Live Demo.
I have to disable the color change of an anchor tag when visited. I did this:
a:visited{ color: gray }
(The link is gray in color before visited.) But this is a way where I explicitly state the color after the link is visited, which is again a color change.
How can I disable the color change of an anchor tag when visited without doing any explicit color changes?
If you just want the anchor color to stay the same as the anchor's parent element you can leverage inherit:
a, a:visited, a:hover, a:active {
color: inherit;
}
Notice there is no need to repeat the rule for each selector; just use a comma separated list of selectors (order matters for anchor pseudo elements). Also, you can apply the pseudo selectors to a class if you want to selectively disable the special anchor colors:
.special-link, .special-link:visited, .special-link:hover, .special-link:active {
color: inherit;
}
Your question only asks about the visited state, but I assumed you meant all of the states. You can remove the other selectors if you want to allow color changes on all but visited.
You can't. You can only style the visited state.
For other people who find this, make sure that you have them in the right order:
a {color:#FF0000;} /* Unvisited link */
a:visited {color:#00FF00;} /* Visited link */
a:hover {color:#FF00FF;} /* Mouse over link */
a:active {color:#0000FF;} /* Selected link */
For :hover to override :visited, and to make sure :visited is the same as the initial color, :hover must come after :visited.
So if you want to disable the color change, a:visited must come before a:hover. Like this:
a { color: gray; }
a:visited { color: orange; }
a:hover { color: red; }
To disable :visited change you would style it with non-pseudo class:
a, a:visited { color: gray; }
a:hover { color: red; }
It’s possible to use the LinkText system color value from the CSS 4 Color Module to obtain the browser default value if one wishes to defer to that.
a:visited { color: LinkText; }
link
However note:
These values may also be used in other contexts, but are not widely supported by browsers.
It at least appears to work in Firefox 98 and Chromium 99.
If you use some pre-processor like SASS, you can use #extend feature:
a:visited {
#extend a;
}
As a result you will see automatically-added a:visited selector for every style with a selector, so be carefully with it, because your style-table may be increase in size very much.
As a compromise you can add #extend only in those block wich you really need.
For those who are dynamically applying classes (i.e. active):
Simply add a "div" tag inside the "a" tag with an href attribute:
<a href='your-link'>
<div>
<span>your link name</span>
</div>
</a>
Either delete the selector or set it to the same color as your text appears normally.
You can solve this issue by calling a:link and a:visited selectors together. And follow it with a:hover selector.
a:link, a:visited
{color: gray;}
a:hover
{color: skyblue;}
I think if I set a color for a:visited it is not good: you must know the default color of tag a and every time synchronize it with a:visited.
I don't want know about the default color (it can be set in common.css of your application, or you can using outside styles).
I think it's nice solution:
HTML:
<body>
<a class="absolute">Test of URL</a>
<a class="unvisited absolute" target="_blank" href="google.ru">Test of URL</a>
</body>
CSS:
.absolute{
position: absolute;
}
a.unvisited, a.unvisited:visited, a.unvisited:active{
text-decoration: none;
color: transparent;
}
a {
color: orange !important;
}
!important has the effect that the property in question cannot be overridden unless another !important is used. It is generally considered bad practice to use !important unless absolutely necessary; however, I can't think of any other way of ‘disabling’ :visited using CSS only.
Use:
a:visited {
text-decoration: none;
}
But it will only affect links that haven't been clicked on yet.