CSS Performance between class and attribute selectors - css

I'm wondering if there is a performance issue using attribute selectors instead of class selectors.
div.test {}
div[test] {}
P.S. : I'm only interested in CSS performance, not JS.

According to this article, class selectors are more efficient than attribute selectors.

Someone has actually created a real life selector test that showcases selector matching performance.
The table outlines that attribute selectors are approximately 3x slower compared to standard classes.
Relying on attribute selectors also requires more characters to target an element. It's better to define short and concise class names to keep your stylesheet small.
Example:
// 17 Characters (attribute)
[title="example"] {
...
}
// 6 Characters (class)
.title {
...
}
http://scope.bitbucket.org/tests/selector-matching-performance/

According to this project there is no real performance issue.
This surprised us, since selector performance hasn't been a real
concern in our day-to-day work for a while. Front-end performance is a
huge deal, of course, but CSS selectors appear to contribute such a
minuscule amount to the total page load time that it didn't occur to
us that it might be a major concern to many people.
They have benchmarks as well.
EDIT: see comment: they have benchmark ideas*, not benchmarks.
https://github.com/amcss/am-benchmarks

There is no performance issue. Both act same. But there is difference in specificity of the css with class versus Elements.
Specificity - Specificity determines, which CSS rule is applied by browsers.
If two selectors apply to the same element, the one with higher specificity wins.
But specificity has hierarchy.
Inline styles (Presence of style in document).
An inline style lives within your XHTML document. It is attached directly to the element to be styled. E.g.
IDs (# of ID selectors)
ID is an identifier for your page elements, such as #div.
Classes, attributes and pseudo-classes (# of class selectors).
This group includes .classes, [attributes] and pseudo-classes such as :hover, :focus etc.
Elements and pseudo-elements (# of Element (type) selectors).
Including for instance :before and :after.
Source: http://coding.smashingmagazine.com/2007/07/27/css-specificity-things-you-should-know/
Hence div.test {} is more specific.

Related

CSS specificity on Font Awesome icon

I am picking up my icon color from icon--apply instead of .classname__icon--apply. Doesn't this violate CSS specificity rules? Am I missing something here?
You're confusing BEM with specificity.
Don't think of specificity like a set of rules, it's more like a mechanism. A mechanism which decides which rule should be more important than others.
There's a whole bunch of selectors but for our purposes, we can break
it down into three types, of increasing importance:
Element selectors (and pseudo-element selectors) Eg. p {color:red;}
Class selectors (and attribute selectors) Eg. .myclass {color:red;}
ID selectors. Eg. #myid {color:red;}
https://snook.ca/archives/html_and_css/understanding_c
BEM is a naming convention for your CSS classes. You can decide if you want to use it. It's optional.
The Block, Element, Modifier methodology (commonly referred to as BEM)
is a popular naming convention for classes in HTML and CSS. Developed
by the team at Yandex, its goal is to help developers better
understand the relationship between the HTML and CSS in a given
project.
https://css-tricks.com/bem-101/
Another naming convention would be Atomic CSS, where you use a lot of small, single purpose classes - for example .color-red.
You can read more about it here: https://css-tricks.com/lets-define-exactly-atomic-css/

CSS selectors, tagname + class vs class

Lets imagine very simple case:
div.className{}
vs
.className{}
Which option is faster and why ?
.className{} is faster in downloading, because of smaller size of the css file.
It is also faster when rendering page, because it is not necessary to look for div elements.
A guideline from google:
Avoid qualifying ID and class names with type selectors. Unless
necessary (for example with helper classes), do not use element names
in conjunction with IDs or classes.
Avoiding unnecessary ancestor selectors is useful for performance reasons .
One very important difference between div.classname and simply .classname is in something called selector specificity. It is a set of rules which defines which selector gets more weight once the browser starts going through all the selectors that potentially have influence on a particular element.
ne of the most basic rules of CSS is that selectors can be redefined in a way that whatever definition comes last and has influence on a particular element its the one that is going to be used (the sole exception being when using !important which always takes precedence).
Now in the above example redefining the .class selector should actually hide the text but instead its still visible. How is that possible if we said that latter rules always take precedence? Its because the div.classname rule has a higher specificity that .box since it actually gets points for containing both an element (div) and a class selector (.class) in its selector declaration (div.class).
Of course the div.class rule will be applied only on a div element but since class selectors are often reusable pieces of code there is plenty of situations when they are used on divs.
Although the rules in the official W3 specification are not that hard to understand they are sometimes pretty hard to remember. That's why I would like to recommend an excellent article on CSS selector specificity which can be found here.
In my opinion selector specificity is by far the most important thing to master when it comes to tracing inheritance problems with CSS stylesheets.
For Example
Find some more info
Follow Up

What's the point of writing div#id_name vs. #id_name?

I've noticed that a lot of css style recipes are often stated like this:
div#id_name {
blah: blah;
}
But since IDs are unique, what's the point of sticking "div" in front of #id_name? Is there any advantage over the following snippet?
#id_name {
blah: blah;
}
I would argue that the latter is superior because you might decide to make the id_name element into something besides a div.
This is primarily done to advance specificity and to hint the document as to what type of element #id_name is.
First, specificity:
Specificity determines which styles are actually applied to your element. The more specific you are in calling your element out, the more priority that block of properties takes over another.
For example:
Given HTML
<div id="id_name">
Look at this blue text!
</div>
With CSS
div#id_name {
color: red;
}
#id_name {
color: blue;
}
Results in
This will render a div with red text as opposed to blue text. This is beneficial when writing a framework if you want to guard your styles from being arbitrarily overwritten by local styles.
Secondly, hinting:
Oftentimes, CSS is an afterthought. It's a shame, too, as it's gotten increasingly more powerful and has taken many of the responsibilities previously reserved for client-side scripting languages like JavaScript. There is no implicit inheritance in CSS, rather it's explicit via a long declaration.
What I'm talking about with this is that you don't see
div {
.my-class {
/* RULES! */
}
#my-id {
/* RULES! */
}
}
as a part of CSS unless you're using a precompiler like LESS or SASS. Hinting a document with the element name instead of only the id or class allows for much greater readability for not only future you, but any collaborators you may have on the project.
And finally:
Sometimes it just doesn't make sense to not add a an element guard to your rule. If I have a rule that sets things like height, width or padding, I wouldn't want that same rule applied to a span. I would rather see it fail loud than silent to prevent rules being applied that have no place being there. It can cause messy and unexpected results given the exact scenario you described.
In addition, there's no guarantee that #id-name won't be re-used on a later page for an element that is not a div in the scenario you gave. So there's that, too.
Using ID's have a very strict specificity issue. Realistically, according to the standards, you can only use an ID once in any given HTML document. That doesn't mean you can't use ID's as styling selectors, though, it does come with dangerous pitfalls in larger projects. They're fine if you're using them as targets in Javascript. Go crazy.
ID selectors are very, very specific in targeting elements and in return, you end up with problems later down the line dealing with CSS specificity. Class selectors are reusable and have much looser specificity. Styling with ID's doesn't have anything different that a class selector doesn't have, so why use them if they're causing specificity issues? Read this and this. They are both fantastic articles on why ID's are not cool for CSS. It is a personal preference, but, making your CSS very specific is a front-end disaster in all real-world cases web development.
So, to answer your question properly, adding div at the start of and id selector, like div#id_name means you can only apply that id to a <div> element. You couldn't add it to a <span>, or any other element for example, which is an insanely restrictive method of styling in CSS. If you just use #id_name, you can apply this selector on any element instead.
The only difference is that div#id_name has higher specificity. This is seldom relevant, and there are other ways to make a selector more specific. People may include the element (tag) name for documentation purposes, but then they take the risk that was referred to in the question: someone might change the div to, say, p and forget to modify the CSS selector(s).

Modernizr and descendants selector?

According to mdn :
The descendant selector is the most expensive selector in CSS. It is
dreadfully expensive—especially if the selector is in the Tag or
Universal Category.
When Modernizr is up , it adds all the non supported classes to the html tag.
Meaning he can later do :
.myNotSupportedClass .myLastDiv <-- notice descendants selecotr[ ]
{
color:red;
}
But this is absolutely slow operation an operation which can be optimized.... which has to go through all the DOM tree in order to find the div.
I know there isn't another way of doing it , but still :
1) they could have added those classes to the body/form which is closer to the elements. soo there will be less of searching.
Or am I wrong ...,?
But this is absolutely slow operation
Eh.
they could have added those classes to the body/form which is closer to the elements. soo there will be less of searching.
body: how much less searching? 1 level less? How much of a difference does that make?
form: not every page has a form, and pages can have more than one form. The form element itself can be placed anywhere in the page body too, so the elements that should be affected by selectors in Modernizr class context may very well be unrelated to it, making searching completely impossible.
Do whatever you like, but since Modernizr chooses to place classes on the html element, write contextual selectors that make use of those classes and the descendant selector. If you're that obsessive about descendant selector performance, you have the choice not to use Modernizr and lose all the feature detection goodness it brings.
Why it chooses to place classes on the html element is anybody's guess. It could have been the most convenient element to place them on.

Choosing efficient selectors based on computational complexity

Given the CSS processing specifics, most notably RTL matching and selector efficiency, how should selectors be written purely from the perspective of rendering engine performance?
This should cover general aspects and include using or avoiding pseudo-classes, pseudo-elements and relationship selectors.
At runtime an HTML document is parsed into a DOM tree containing N elements with an average depth D. There is also a total of S CSS rules in the stylesheets applied.
Elements' styles are applied individually meaning there is a direct relationship between N and overall complexity. Worth noting, this can be somewhat offset by browser logic such as reference caching and recycling styles from identical elements. For instance, the following list items will have the same CSS properties applied (assuming no pseudo-classes such as :nth-child are applied):
<ul class="sample">
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
Selectors are matched right-to-left for individual rule eligibility - i.e. if the right-most key does not match a particular element, there is no need to further process the selector and it is discarded. This means that the right-most key should match as few elements as possible. Below, the p descriptor will match more elements including paragraphs outside of target container (which, of course, will not have the rule apply but will still result in more iterations of eligibility checking for that particular selector):
.custom-container p {}
.container .custom-paragraph {}
Relationship selectors: descendant selector requires for up to D elements to be iterated over. For instance, successfully matching .container .content may only require one step should the elements be in a parent-child relationship, but the DOM tree will need to be traversed all the way up to html before an element can be confirmed a mismatch and the rule safely discarded. This applies to chained descendant selectors as well, with some allowances.
On the other hand, a > child selector, an + adjacent selector or :first-child still require an additional element to be evaluated but only have an implied depth of one and will never require further tree traversal.
The behavior definition of pseudo-elements such as :before and :after implies they are not part of the RTL paradigm. The logic the assumption is that there is no pseudo element per se until a rule instructs for it to be inserted before or after an element's content (which in turn requires extra DOM manipulation but there is no additional computation required to match the selector itself).
I couldn't find any information on pseudo-classes such as :nth-child() or :disabled. Verifying an element state would require additional computation, but from the rule parsing perspective it would only make sense for them to be excluded from RTL processing.
Given these relationships, computational complexity O(N*D*S) should be lowered primarily by minimizing the depth of CSS selectors and addressing point 2 above. This will result in quantifiably stronger improvements when compared to minimizing the number of CSS rules or HTML elements alone^
Shallow, preferably one-level, specific selectors are processed faster. This is taken to a whole new level by Google (programmatically, not by hand!), for instance there is rarely a three-key selector and most of the rules in search results look like
#gb {}
#gbz, #gbg {}
#gbz {}
#gbg {}
#gbs {}
.gbto #gbs {}
#gbx3, #gbx4 {}
#gbx3 {}
#gbx4 {}
/*...*/
^ - while this is true from a rendering engine performance standpoint, there are always additional factors such as traffic overhead and DOM parsing etc.
Sources: 1 2 3 4 5

Resources