Given this:
<a class="details" href="#">more…</a>
...
<input type="submit" value="Gogogo">
Say that both should have very similar appearance, because that's what the designer wants. Do you do this:
<a class="fancybutton" ...
<input class="fancybutton" ...
.fancybutton { /* ... */ }
or this?
a.details, .someform input[type="submit"] { /* ... */ }
I'm struggling with this issue and I'm not sure where to go. It seems to be a choice between having a really clear stylesheet vs. nice markup that isn't littered with classes.
When do you choose one over the other?
The main reason to choose classes over more fancy CSS selectors is compatibility. Several versions of at least one major browser still in use don't support more advanced selectors properly and thus it's actually less painful to just use classes, since they "just work".
IE6 doesn't support input[type=submit], so if I'm developing for it, I'll definitely go for the class.
I'd generally use class because that has wider support than attribute selectors amoung browsers. Until the vast majority of the population have a browser that supports the CSS attribute selectors I would continue to uses classes in such a case.
I'd say, within complaint browsers, that the answer is specificity. Look to the breadth of the application of the style and define it with sufficient specificity to be unambiguous within the scope of your web-app.
Also, don't be afraid to use more than 1 style class on an element to develop a layered presentation approach, i.e. class="blackborder smalltext centred".
Like other users have said, using classes is good because it really simplifies the question of browser compatibility (problems arise when you try to use fancy CSS 2 selectors).
Another great reason to use simple class-based (or id-based, if possible) selectors over complex CSS 2 selectors is speed.
From google's "Optimize browser rendering", descriptions of why you should try to use simple selectors (class-only/id-only selectors are very simple):
Descendant selectors are inefficient because, for each element that matches the key, the browser must also traverse up the DOM tree, evaluating every ancestor element until it finds a match or reaches the root element. The less specific the key, the greater the number of nodes that need to be evaluated.
Child and adjacent selectors are inefficient because, for each matching element, the browser has to evaluate another node. It becomes doubly expensive for each child selector in the rule. Again, the less specific the key, the greater the number of nodes that need to be evaluated. However, while inefficient, they are still preferable to descendant selectors in terms of performance.
And a specific note about class-selectors over descendant selectors from the same article:
Use class selectors instead of descendant selectors.
For example, if you need two different styles for an ordered list item and an ordered list item, instead of using two rules:
ul li {color: blue;}
ol li {color: red;}
You could encode the styles into two class names and use those in your rules; e.g:
.unordered-list-item {color: blue;}
.ordered-list-item {color: red;}
If you must use descendant selectors, prefer child selectors, which at least only require evaluation of one additional node, not all the intermediate nodes up to an ancestor.
Related
I've always believed (although I now doubt the validity of these beliefs) that:
div.name
Was faster than:
.name
However I've read recently that most CSS selector engines read from right to left, in which case wouldn't the first example actually be slower? As the selector engine would simply find every element with a class of name, and then have to identify which of those were divs?
Which way do CSS selector engines read in general? Left to right or right to left? And if they generally read right to left could someone please offer me an explanation as to why (I can't see how it makes sense to read right to left in terms of a selector engine)?
However I've read recently that most CSS selector engines read from right to left, in which case wouldn't the first example actually be slower?
Which way to CSS selector engines read in general? Left to right or right to left? And if they generally read right to left could someone please offer me an explanation as to why (I can't see how it makes sense to read right to left in terms of a selector engine)?
Frankly, it's nigh impossible to tell which selector will be slower in a given browser, much less across browsers. Performance tends to fluctuate and be unpredictable, especially at such microscopic scales and with unpredictable document structures. Even if we talk about theoretical performance, it ultimately depends on the implementation.
Having said that, as shown in Boris Zbarsky's answer to this other question and in Guffa's answer to yours, a typical browser (this is currently true of all major layout engines) takes an element and evaluates all the candidate selectors to see which ones it matches, rather than finding a set of elements that match a given selector. This is a subtle but very important difference. Boris offers a technical explanation that's not only incredibly detailed, but also authoritative (as he works on Gecko, the engine used by Firefox), so I highly suggest reading it.
But I thought I should address what seems to be another concern in your question:
As the selector engine would simply find every element with a class of name, and then have to identify which of those were divs?
As well as Patrick McElhaney's comment:
The linked question explains why selectors are read right-to-left in general, so #foo ul.round.fancy li.current is read li.current, ul.round.fancy, #foo, but is it really read right-to-left within each element (.current, li, .fancy, .round, ul, #foo)? Should it be?
I have never implemented CSS, nor have I seen how other browsers implement it. We do know from the answers linked above that browsers use right-to-left matching to walk across combinators within selectors, such as the > combinators in this example:
section > div.second > div.third
If an element isn't a div.third, then there is no point checking if its parent is a div.second whose parent is a section.
However, I don't believe that this right-to-left order drills all the way down to the simple selector level. In other words, I don't believe that browsers use right-to-left evaluation for each part of a simple selector sequence (also known as a compound selector) within the right-to-left evaluation across a series of compound selectors separated by combinators.
For example, consider this contrived and highly exaggerated selector:
div.name[data-foo="bar"]:nth-child(5):hover::after
Now, there's no guarantee a browser will necessarily check these conditions for an element in the following order:
Is the pointer over this element?
Is this element the 5th child of its parent?
Does this element have a data-foo attribute with the value bar?
Does this element have a name class?
Is this a div element?
Nor would this selector, which is functionally identical to the above except with its simple selectors jumbled around, necessarily be evaluated in the following order:
div:hover[data-foo="bar"].name:nth-child(5)::after
Is this element the 5th child of its parent?
Does this element have a name class?
Does this element have a data-foo attribute with the value bar?
Is the pointer over this element?
Is this a div element?
There is simply no reason that such an order would be enforced for performance reasons. In fact, I'd think that performance would be enhanced by picking at certain kinds of simple selectors first, no matter where they are in a sequence. (You'll also notice that the ::after is not accounted for — that's because pseudo-elements are not simple selectors and never even enter into the matching equation.)
For example, it's very well-known that ID selectors are the fastest. Well, Boris says this in the last paragraph of his answer to the linked question:
Note also that there are other optimizations browsers already do to avoid even trying to match rules that definitely won't match. For example, if the rightmost selector has an id and that id doesn't match the element's id, then there will be no attempt to match that selector against that element at all in Gecko: the set of "selectors with IDs" that are attempted comes from a hashtable lookup on the element's ID. So this is 70% of the rules which have a pretty good chance of matching that still don't match after considering just the tag/class/id of the rightmost selector.
In other words, whether you have a selector that looks like this:
div#foo.bar:first-child
Or this:
div.bar:first-child#foo
Gecko will always check the ID and the class first, regardless of where it is positioned in the sequence. If the element doesn't have an ID and a class that matches the selector then it's instantly discarded. Pretty darn quick if you ask me.
That was just Gecko as an example. This may differ between implementations as well (e.g. Gecko and WebKit may do it differently from Trident or even Presto). There are strategies and approaches that are generally agreed upon by vendors, of course (there isn't likely to be a difference in checking IDs first), but the little details may differ.
The selector engine doesn't look for element to apply a rule, it looks for rules that apply to a specific element. Therefore it makes sense to read the selectors from right to left.
A selector like this:
div span.text a.demo
would make the selector engine do these checks to see if the selector applies to an element:
Is it an a element with the class demo?
Does it have an ancestor that is a span element with the class text?
Does that element have an ancestor that is a div element?
I'm currently working on making an accessible site using, among other things, ARIA tags. It occurred to me that attributes such as aria-invalid would be good selectors for my CSS to target, rather than using a .error class.
The benefit of this is leaner, more meaningful HTML, which is easier for me to hook into from CSS (and JS). That said, I haven't seen this done elsewhere so I'm suspicious there are downsides to leveraging accessibility tags for styling. I suspect the use of unconstrained attribute selectors makes for less performant CSS, but are there other downsides I haven't considered?
Attribute selectors are a very flexible way to manage styles for large-scale CSS because the attribute selectors will always have a specificity of 0-0-1-0.
[aria-*] selectors are perfectly fine to use as styling hooks, and I also recommend using custom [data-*] attributes to fill in the gaps where you might need a one-off. Certainly class selectors should continue to be used, however you can do some very elegant style extensions with attribute selectors:
[data-foo] {
color: red;
}
[data-foo="bar"] {
color: blue;
}
[data-foo="fizz"] {
color: green;
}
Each of these selectors has the same specificity, and the cascade will allow the styles to be applied appropriately.
You could create your own form of classes by using the [attr~="value"] selector if need be.
Using the "attribute contains" selector can be useful for a technique that I call "classy images"
One of the hidden benefits to using attributes over classes is a performance gain in JavaScript. Instead of having to check for the presence of a class on an element (which is remarkably easy to get wrong), browsers have supported getAttribute, hasAttribute, and setAttribute for a long time.
You need to understand that attributes like aria-invalid should be avoided in the first place. You should always use native semantics if available (e.g. required on input elements). This is called the first rule of ARIA.
I think what you really want is to add styling to computed ARIA states and properties. Unfortunately this is not supported in CSS at the moment.
In summary: There is nothing wrong with using [aria-invalid] as a CSS-selector. It will just not help you much because you should avoid that attribute in the first place.
To what extend should I be attempting to use other CSS selectors instead of element IDs/class names or vice versa.
For instance: body > header nav ul+ul { ... } when I could just do #socialnav { ... } to achieve the same thing.
Example HTML code being (obviously there are headers with child navs elsewhere in the code):
<header>
<nav>
<ul>...</ul>
<ul....</ul>
</nav>
</header>
What is the consensus on this? I mean, I find it manageable doing it using CSS selectors, but is there a disadvantage?
Your first guiding principal should be to keep the markup semantic. Your markup above is a great example of this - you're using header, nav, and ul tags in semantically meaningful ways.
Your second guiding principal should be to maintain separation of concerns (e.g., content and presentation). If adding a class names or id's to your markup does nothing for you semantically and you're able to craft CSS selectors w/out them, then you should avoid adding extra noise to the markup.
Sometimes, however, class names and id's are very useful (not just in CSS but also in JavaScript), so they have their place. Just don't resort to them if they're unneeded and are therefore adding unnecessary clutter to your markup.
It's up to your preferences.
I find it not wise to use body > header nav ul+ul, because a small change in your document structure, and you have to rewrite the CSS selector.
Use .classselectors and #id-selectors for elements which aren't an incredible important part of the main document, and use #one-special-item > ul > li > a:hover span to select the more specific elements.
Generally I try and avoid ID selectors in CSS.
I find it a lot easier to deal with classes than using IDs.
IDs can cause issues later on down the line if the markup is used in a Server-Side application, such as ASP.NET, where the IDs are rendered as something different to how they display in the markup.
However, ID selectors do take priority over class selectors:
http://jsfiddle.net/wcLrF/
You should write your stylesheets as rule sets for your site.
If you are writing a style which is you want to to work with a single specific piece of content, then it is good practice to reference that element's ID.
If you are writing a style which is part of your general site look and feel, then it should be written to reference tagnames and/or classes as much as possible.
There will be times when the actual html code is such that it becomes hard to follow those rules, but if you try to stick to that in general then you'll be okay. You may also need to bend your rules if you need to support older browsers (cough, IE, cough) that don't support all the CSS features that you'd normally want to use.
So yes, I would say that the way you've done it in the question is the recommended approach.
Using IDs and Classes as selectors is much faster than using normal css selectors. Some also argue that you should ONLY use classes because they encourage reusability in your stylesheets.
Here's a really good article about Object Oriented CSS: http://coding.smashingmagazine.com/2011/12/12/an-introduction-to-object-oriented-css-oocss/
Is p.error better or worse than .error?
I have read that element-specific selectors are bad and should be used only if really needed but noone seems to know why. I mean I do understand that .error is better for code reuse, but is there somekinda specific reason why I shouldn't address class with element always?
CSS selectors are read right to left. So p.error has one additional step to .error. This may result in a smaller set or not - depends on your markup.
However, this is a micro micro optimization. There is not going to be a performance hit unless we're talking about a massive amount of selectors.
Here's a great article on CSS selectors that elaborates on how they are evaluated : http://css-tricks.com/efficiently-rendering-css/
.error is more efficient than p.error .
To understand why this is more efficient I recommend you read this article over at css tricks.
no it's not bad, but it may not always be necessary
tools like Google's PageSpeed and YSlow! refer to these type of selectors as being "over qualified" perhaps that's where you're hearing the "it's bad" part from - reading material
take for example p#myid - an ID should always be unique on a page anyway, therefore there is no need at all to qualify it with the p element. an ID already has the highest weight when specificity is being counted so again it's totally redundant to add the extra part to try and add more specificty.
However with class names like your example it can sometimes definitely be desirable to add the qualifier as you may want the class to be re-usable on different type elements but have different properties depending on if it's a div or a p for example, the "qualifier" then makes the selector slightly more specific
.error {background: red; margin: 5px;}
p.error {margin: 2px;}
The code above means you can use the error class on any element and it will have 5px margins however if you set the error class on a p element the second selector is actually doing something, it's over-riding the first's margins but still getting the background color
So they do a job, but too often you see too many people over qualifying all their elements when it is not necessary.. for example if you're only ever applying that .error class to a p element then you wouldn't need the second selector.
The rule of thumb is to make the selector unique as quickly as possible starting from the right side of it.
Having a very specific selector will not amount to bad performance, but if there are a lot of declarations applicable for an element, then the performance will take a hit. The only concern otherwise is that it increases the no. of bytes to be downloaded for loading the stylesheet. Trust me, Every extra character in HTML passed is evil and will amount to lower page load speed.
During CSS cascading is applied by modern-day browsers, the following is the process that occurs for each CSS property for each web page element:
Gather all the declarations for the property from all the sources. This includes default browser styles and custom user style, as well as author style sheets. If there is more than one, proceed to 2.
Sort the declarations by importance and origin in the following order (from lowest to highest priority):
user agent style sheets (default browser styles)
normal declarations in a user style sheet (a user’s custom style sheet)
normal declarations in an author style sheet (web page style sheets; external, embedded, and inline styles)
!important declarations in an author style sheet
!important declarations in a user style sheet
The one with the highest priority wins. If more than one have the same priority then proceed to 3.
Sort by selector specificity. The one with the most specific selector wins. If no clear winner, proceed to 4.
The one that comes last in the source wins!
If the cascade does not set a CSS property on an element, then the browser will fall back to using an inherited property from the element’s parent (this only happens for some properties), otherwise the property is set to the CSS default value.
According to the above process, if you use a lot of more specific selectors, there would be a choice made after atleast 3 levels deep. Hence, the more the no. of declarations which might be applicable to an element, the lower the performance would be.
So, You must as specific as it makes sense to be.
The reason is specificity. For example...
+1 each access by class
+1 each access by tag
+10 each access by ID
etc.
So, if you have a class and a tag access, that style has a specificity of 2 (1+1).
Later, if you're trying to style all .error elements, but you have a conflicting style in the p.error elements, the higher specificity will win. This may cause some headaches down the line. That is why you may not want to always use tag+class.
(That being said, specificity solves many more problems than it creates, and is generally regarded as Pretty Awesome.)
As a general rule of thumb, the less selectors a browser has to evaluate the better.
p.error isn't necessarily "worse" than .error, if .error is used for multiple tags. e.g. div.error (see a foot note at the bottom).
But if it's only used on a paragraph anyway, then having p.error is just making the browser work harder i.e.
First it will have to find all elements with the class attribute error and then filter these by only having tags that are p.
Here is some interesting reading on Optimize browser rendering on Google's Page Speed site.
Foot Note
However if you need to use a class on multiple tags, it's probably best only to put in the css styles which apply to those tags instead of trying to separate it. e.g.
.error
{
color:red;
}
h1
{
font-size:2em;
}
p
{
font-size:0.8em;
}
<h1 class="error">Bad Heading!</h1>
<p class="error">bad!</p>
So that kind of defeats the need to prefix classes with tags anyway.
I hope this helps!
I'm wondering if there is any difference between div.class and .class as CSS selectors if there is only one tag (the DIV) with that attribute. Same thing for IDs: div#ID and #ID.
Any idea what, if anything, is the difference? For me, I use the class or ID in these situations; but only because it's quicker to type.
They are more specific, so long ones will override the shorter version if they conflict. div.foo will have a specificity of 11 while .foo has a specificity of 10.
Since they are more specific, you know exactly which nodename the class applies to instead of being a universal rule for all node names, this can help if you have a huge application with tons of elements that all have the same class names, it can lessen the time for you to find the element in the source/text editor.
There is only a VERY SLIGHT difference in specificity.
p#id is (0,1,0,1)
and
#id is (0,1,0,0)
in otherwords, the tag itself doesn't hold very much specificity at all compared to an ID, and relying on that kind of tiny specifity to overrule things is almost never needed in my experience.
More importantly, NOT tag-qualifiying selectors is more efficient for the browser to render.
Sticking to just a class or id, as you do, means that your CSS will still apply if the HTML tag is changed to a different tag.
Most of the time, this is probably exactly what you want — classes are there to allow you to add a custom layer of meaning on top of HTML.
In general, your selectors should be the minimum required to express your meaning.
Usually those longer selectors come in handy once the majority of the CSS has already been done. Sometimes you want to tweak a little thing here and there - say - differenciate between p.error and div.error for example. So instead of adding another class - and thus having to touch the HTML - you can simply add an element name to your selector instead, for more fine grained control.
No, there is no difference if you only have DIV tags of the specific class or ID.