Why not :visited instead of a:visited for links? - css

Every example and stylesheet I've looked at uses a:visited to style links. Besides a:visited having higher specificity, shouldn't :visited be equivalent and simpler?

TL;DR: At the time of writing, you are completely correct; there is no difference between a:visited and :visited. However, using a:visited is best practice for future-proofing your code.
TL;DR EDIT: As of August 2016, the CSS4 Working Draft allows other tags to use :visited. There is now a functional difference between a:visited and :visited! Beware.
For web development languages today, specifically HTML5 and CSS3, you are right: there is functionally no difference between a:visited and :visited. Now, please take this with caution: web standards, elements, and user interface protocols are ever-evolving, meaning that in the future, it is possible that a new tag compatible with :visited may be introduced.
When :visited was introduced in CSS, the W3C CSS1 spec said:
In CSS1, anchor pseudo-classes have no effect on elements other than 'a'. Therefore, the element type can be omitted from the selector:
a:link { color: red } == :link { color: red }
HOWEVER, in the CSS2 spec, the behavior of the :visited pseudo-class was not restricted to just a tags:
The document language determines which elements are hyperlink source anchors. For example, in HTML4, the link pseudo-classes apply to a elements with an "href" attribute.
This means that it is up to the document language and browser to determine which elements are compatible with :visited. While the current industry standard states that for HTML, only a elements with an href attribute qualify, this may well change later down the line.
EDIT, August 2016: Looks like the CSS4 Working Draft has confirmed my suspicion; in the new spec, :visited can be used for other "link-like" elements, namely <area> and <link>. The spec says:
The :any-link pseudo-class represents an element that acts as the source anchor of a hyperlink. For example, in [HTML5], any <a>, <area>, or <link> elements with an href attribute are hyperlinks.
So <a>, <area>, and <link> are all treated as hyperlinks, and the spec says that :visited applies to all hyperlinks. So as of CSS4, you'll be better off including the a in a:visited.

According to Selectors Level 4 :visited applies to any hyperlink, which in HTML is the <a>, <area> and <link> elements when they have an href attribute.
A quick test for the link element shows that Firefox at least partially respects this:
Try http://jsfiddle.net/rfdzpjLo/4/ in FF or see below
link:before { content:attr(href); }
link { display:block; }
:visited { color: red; }
:link { color:green; }
<link href="http://stackoverflow.com/questions/27263128/why-not-visited-instead-of-avisited-for-links" />
<link href="example.net/lsjhuehbsi00ejjdus" />

Yes, but it won't be future compatible if a new tag is introduced that may be styled with :visited.
Closest proof I can find:
http://www.w3.org/TR/CSS21/selector.html#link-pseudo-classes
The document language determines which elements are hyperlink source anchors. For example, in HTML4, the link pseudo-classes apply to A elements with an "href" attribute. Thus, the following two CSS 2.1 declarations have similar effect:
a:link { color: red }
:link { color: red }

In theory it's the same for reasons already mentioned. On paper, a:visited vs :visited makes it explicit that the style only applies to anchors, and may potentially be faster: think of it as the browser needing to iterate through all a tags in the one hand side, and checking if :visited applies, vs doing the same for all tags in the DOM.
Imho though, the more important reason is that styles related to a tag, a pseudo-selector, a class and an identifier aren't necessarily applied in a consistent and predictable order from a browser to the next.
Suppose, for instance, this visited link:
<a id="foo" class="bar" href="...">visited link</a>
Then consider the following CSS:
#foo {
color: red;
}
.bar {
color: green;
}
:visited {
color: purple
}
There used to be a time where the link would appear red, green or purple depending on the browser. (Perhaps it's still the case; I haven't tested.) Because, some would treat #foo as more important than .bar (it's an ID vs a class) and both of these as more important than :visited for similar reasons. Some would treat #foo, .bar and :visited as if they had the same importance, as a property of the tag itself. Some might have treated #foo and .bar as equals but more important than :visited on grounds the latter is a mere pseudo class. And so forth.
Now, consider this CSS, which is the kind of stuff you might encounter in a stylesheet today:
a.bar {
color: green;
}
:visited {
color: purple
}
Even assuming that tags, ID, classes and pseudo classes are all treated equal, we still have a potential problem, in that a.bar can also be considered more specific than plain :visited by some browsers.
Ergo, you end up needing to specify a:visited in the declaration to ensure the behavior is consistent in all browsers -- and chances are there are still a few bad apples around that'll make you want to write a:visited, a.bar:visited just to be sure.
Once you've run into the problem a few times, force of habit kicks in and you'll end up always writing a:hover or a:visited.

:visited is a pseudo class selector used only for anchor link elements that matches when the href attribute of that anchor link has been visited in the past by this browser. It is meant to be useful feedback for a user, so they can tell the difference between links they have been to and links they have not.
REFERENCE
The syntax of a pseudo class is as follows
selector:pseudo-class {
property:value;
}
So you have to use a selector when using a pseudo class and since it supports only links, in this case, the selector would be a.

Related

Should I add a element name in front of '#id' or '.class' selector?

I'm reading the book: CSS Mastery: Advanced Web Standards Solutions, and finding the css code inside is almost writed in this format:
elementName#idName
elementName.className
but, I'm used to write code ignoring element name with this format:
#idName
.className
so, I want to figure out what difference is between the two format.
Actually, I understand when should use type.class. And, I just want to find out the impact when I use type.class insead of only using .class when there is only one kind of tag here.
There must be some impact on performance.
Here's a real life scenario as when to use elementName and when to just use class or id name:
HTML:
<a class="blue">I'm blue and underline</a>
<span class"blue">I'm blue and bold</a>
CSS:
.blue {
color:blue //will make both <a> and <span> blue
}
a.blue {
text-decoration:underline // will make only the <a> tags underline
}
span.blue {
font-weight:bold //will make only the <span> tags bold
}
but remember when it comes to IDs you should not have duplicate IDs on your page anyway, this is more practical for classes
The difference between the two is that the first:
element.class
Is calling the element with that specific class.
And the second:
.class
Is calling all elements that contain this class
I think that the element inclusion in the selector is a holdover from days where some browsers required it (I think IE5 does, but I could be wrong). This is no longer necessary, and it does not make sense to include element selector for at least three reasons:
It slows the selector down since the element selector is slower than the other two -- especially id. Assuming selection is optimized so that fast selection is done first (e.g. the element with the matching id is found before the element selector is checked), there is still the additional step of checking the element selector.
It's not as extensible since you can't change the element without also having to change the selector. The implication is also that div.class would function differently than label.class, but I think that the class should be descriptive enough.
It changes the specificity of the selector. This could be very frustrating for some developers who may want to change <div class="foo"> from green to red:
div.foo { color: green; }
/* below is not applied since the above has higher specificity */
.foo { color: red; }
I've never heard an argument that supports type.class unless old browsers need to be supported.

What's the :any-link pseudo-class for?

I don't know if it's a part of any standard, but at least two major browsers have implemented it:
:-webkit-any-link in Chrome
:-moz-any-link in Firefox
I can't find any documentation for it. I would like to know its purpose, browser support, and examples of usage.
:any-link is a new pseudo-class proposed in Selectors level 4, that matches all elements that would be matched by :link, :visited. From what I see, its main purpose is to simplify selectors that need to select any hyperlinks, since the naming of :link is misleading; it specifically means unvisited links only, rather than all hyperlinks (which makes it essentially the opposite of :visited).
For the purposes of :link and :visited, WHATWG HTML and W3C HTML5 both define a "hyperlink" as any one of:
An <a> element that has an href attribute. This excludes named anchors (that is, <a> elements without an href attribute but instead with a name attribute), which were used traditionally to mark anchors in a page, now superseded by the use of an id attribute on any element. See named anchors in HTML 4.
An <area> element that has an href attribute.
A <link> element that has an href attribute.
For example, consider a scenario where links in the page header should be colored differently from all other links:
body > header > a:link, body > header > a:visited {
color: white;
}
Notice the body > header part is duplicated across both selectors. This seems redundant, but is currently necessary in order to color links in the page header differently from the rest, but regardless of their visited state. This is because body > header > a is not specific enough which requires using !important to override anyway, and body > header > a:link troublesomely only applies to unvisited links.
With the :any-link pseudo-class, you can simply do this instead:
body > header > a:any-link {
color: white;
}
Specificity is exactly the same as with each individual half, so there should be no issues there.
Of course, since no browser implements it unprefixed yet, that won't work. As an alternative, considering you're most likely working with an HTML document anyway you can just use a[href] instead, which works in all browsers including IE7+ on top of also being equally specific:
body > header > a[href] {
color: white;
}
There's a much more elaborate explanation regarding the use of a versus a:link, a:visited versus a:any-link versus a[href] in this other answer of mine.
Like anything else that has a prefix in CSS, :-moz-any-link and :-webkit-any-link exist only for experimental purposes, so you shouldn't use them with your sites. Besides, even if you were to use them right now, you'd have to duplicate the rules themselves (and not just the selectors!) since browsers have to drop entire rules on unrecognized selectors, rendering them pretty useless in real-world code!
As of early 2013, no other implementations of :any-link exist that I know of. I'm unsure as well as to whether this was implemented by the respective vendors and then proposed for inclusion in Selectors 4, or if it was preliminarily specced before the vendors began implementing it, but I don't think that matters.
Speaking of which, be sure not to confuse the :-moz-any-link/:-webkit-any-link pseudo-class with :-moz-any()/:-webkit-any(), the latter of which is specced as :matches() instead (possibly to avoid naming confusion?).
In the Mozilla CSS Extensions document, :-moz-any-link is mentioned with the note “(matches :link and :visited)”. The link to detailed information is dead, but the apparent reason for using such a pseudo-class is the odd design of CSS as regards to links: :link matches unvisited links only, whereas :visited matches visited links. Using a single selector is useful in complex cases where you would otherwise need to write two complicated selectors that differ in one pseudo-class only.
They could use a[href], except that this would bind the selector to a specific element (and attribute) used to create links (which is a markup language issue).
Using Firebug and inspecting a link in it, you will see the following styles from the browser default style sheet:
*|*:-moz-any-link:not(svg|a) {
text-decoration: underline;
}
:-moz-any-link {
cursor: pointer;
}
The latter sets the shape of the mouse pointer (“cursor”) on all links. The former makes links underlined, except inside an svg element.

An element on a canvas jumps after the canvas itself is dragged

As mentioned, an element on a canvas jumps after the canvas itself is dragged. I'm using -webkit-transform: translate(x,y) to drag the canvas around. Any ideas on what to look into for this problem?
Look for changes that cause a reflow in CSS:
visibility:hidden/visible
display:none
:hover
and JavaScript:
offsetWidth or offsetHeight
scroll event
The sad truth about CSS3 selectors is that they really shouldn’t be used at all if you care about page performance. Decorating your markup with classes and ids and matching purely on those while avoiding all uses of sibling, descendant and child selectors will actually make a page perform significantly better in all browsers.
With parent selectors it becomes extremely easy to accidentally cause a document-wide grovel. People can and will misuse this selector. Supporting it is giving people a whole lot of rope to hang themselves with.
The complete profile is appropriate for contexts which aren't extremely performance sensitive. For example, implementations of the Selectors API specification [SELECTORS-API] should use the ‘complete’ profile. It includes all of the selectors defined in this document.
CSS implementations conformant to Selectors Level 4 must use the ‘fast’ profile for CSS selection.
The fast profile is appropriate for use in any context, including dynamic browser CSS selector matching. It includes every selector defined in this document, except for:
Combinators within :matches(), :not(), :nth-match(), and :nth-last-match().
The reference combinator
The subject indicator
In particular, in the situation the browser is looking at most of the selectors it's considering don't match the element in question. So the problem becomes one of deciding that a selector doesn't match as fast as possible; if that requires a bit of extra work in the cases that do match you still win due to all the work you save in the cases that don't match.
Use browser specific selectors to target the document itself:
#-moz-document url-prefix()
{
#media all
{
.foo { color: red } /* Firefox */
}
}
*::-ms-backdrop, .foo { color: red } /* IE11 */
*:-webkit-any-link, .foo { color: red } /* Webkit */
If you want to reference a child element based on its context, use the XML serialization of HTML5 and CSS3 namespaces:
#namespace m "http://www.w3.org/1998/Math/MathML/";
m|math { border: 1px solid blue; }
If you want to display a child element based on a parent pseudo class, you can define the default state of the child element, then redefine it for each state change of the parent:
li:hover > a * { display: none; }
li:hover > a:hover * { display: block; }
References
XHTML5 + CSS Namespaces
CSS Selectors: Should You Optimize Them To Perform Better?
Performance Impact of CSS Selectors
Why do browsers match CSS selectors from right to left?
List of suggested extensions to CSS
Force Element to Self-Clear its Children
The IE8 “hover” Bug: The Most Awesome IE Bug Ever?
MDN: #document
Issues for CSS Selectors Level 4
Reflows and Repaints: CSS Performance making your JavaScript Slow
How Browsers Work

Why doesn't this a:visited css style work?

Is there any reason why this does not work on Internet Explorer or Chrome:
<html>
<head>
<style>
A {font-weight: bold; color:black;}
A:visited {font-weight: normal; color: black; }
.Empty {font-weight: bold; color: black; }
</style>
</head>
<body>
click me
</body>
</html>
The link I click never goes to normal and just stays bold. On some other browsers it works.
Changing case did not affect it. Changing a to a:link did not affect it. Changing color works, just not font-weight.
One workaround was to change accessibility to ignore web colors. I do not have access to the source, so I had to do it this way.
Actually, this has nothing to do with case sensitivity. This is a security feature. The functionality of :visited pseudoclass has been restricted in many modern browsers (Fx4, IE9, Chrome) to prevent CSS exploit: read about it here.
Nowadays, getComputedStyle() in these browsers usually returns values for visited links as if they weren't visited. However, I can simply imagine circumventing of that: using font-weight for visited links, the element's width changes so browsers that would allow changing font-weight for :visited links wouldn't actually fix the security hole.
You can see there are some specific things browsers do to protect against this:
The window.getComputedStyle method, and similar functions such as element.querySelector, will always return values indicating that a user has never visited any of the links on a page.
If you use a sibling selector such as :visited + span, the adjacent element (span in this example) will be styled as if the link were unvisited.
In rare scenarios, if you're using nested link elements and the element being matched is different from the link whose presence in history is being tested, the element will be rendered as if the link were unvisited, as well.
Thus, there's no workaround for this issue.
One useful attribute that does work with :visited is background-color. So try:
:visited {background-color:red;}
:visited also works on non-a elements.
The problem has to do with history sniffing, changing css properties is disabled for visited links due to privacy issues.
I came up with the following workaround to reach the desired effect.
It is possible to change the background-color of the visited link.
The solution is very simple:
set a background-image on the link with the same height as your link
and 1px width and repeat the image horizontally
the image has the same color as the background of the link
make one pixel of that image transparent, in the vertical middle
on :visited state just change the backgroundcolor of that link to the text-color of the link
Only one line of the background-color wil be visible, because the background-image is masking it
Here's an example:
a:link {
color:#000;
background:#FFF url('../img/linethrough.png') repeat-x top left;
}
a:visited {
background-color:#000;
color:#000;
}
CSS itself is not case-sensitive, but if the HTML file using this style has an XML declaration and an XHTML doctype, that CSS is not going to work, because tags are case-sensitive. You'll have to set the "a" tags to lower-case.
Explained here:
http://reference.sitepoint.com/css/casesensitivity
Perhaps try changing the color attribute and see whether that has an effect at all.
To troubleshoot, you might want to try to utilize the developer tools in chrome to see what style is applied.
You need to have separate declarations for a:link, a:visited, a:active, etc.
Remove your first style that does not contain a colon. It's overriding. Replace with a:link.

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