css performance with direct descendents - css

I searched but I don't get a concrete answer.
I will ask a simple question
Is it more effective to do this :
body > html > section > div.class1,
body > html > section > table > tbody > tr > td > div.class1
{
background-color : red;
}
or this :
div.class1 {
background-color: red;
}

Browsers will check and convert every code you give to them (HTML and CSS inclued), for each selector the browser set the attributes to the right HTML markers. For very small website it doesn't affect a lot but for large website like Amazon that have more than 1 million lines of code, it will affect a lot the performances.
I think this is a good exemple: https://www.html5rocks.com/en/tutorials/internals/howbrowserswork/#Main_flow_examples

Less specificity is faster. Every selector is another run of a loop. Rule
of thumb, after 3 selectors deep perf will start to be impacted.
https://csswizardry.com/2011/09/writing-efficient-css-selectors/
Also note that well perf is in question, the real performance hit will be when you specify too deeply. I promise you that the long term maintenance become the real problem. Again 3 selectors deep is again a good Rule of Thumb.
Lastly, if you need help with css structure/architecture try:
1- http://getbem.com/
2- https://www.xfive.co/blog/itcss-scalable-maintainable-css-architecture/

Related

CSS: Best practice for selecting deeply nested elements [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I frequently need to address generic elements inside some specific sections of a page. I find this approach most easy to understand in terms of what any rule is affecting:
.shop > .products > .product > .description > .warning {
color: red;
}
But I often see this:
.shopProductsProductDesc > .warning {
color: red;
}
Does it really matter which approach is taken?
It really depends on the problem you are trying to solve.
The selector .shop > .products > .product > .description > .warning to my understanding would be used for two cases:
You have multiple warning elements but you only want to select the elements inside your description and there are other selectors used for warning that you don't want to overwrite.
You need to overwrite a previous selector that is less specific. Ex. .shop > .products > .product > .description .warning
The other selector .shopProductsProductDesc > .warning is less specific than the first one but assuming the container of .warning has those two classes .description.shopProductsProductDesc then the outcome would be the same as the first one.
CSS is all about specificity, if your selector is more specific than the last one used the properties would change. This is why you have to be careful if you are using specific selectors because your last option to alter the properties would be to use !important.
I hope this helps to clear things out.
After trying a few different styles, I think that personal preference (or a set standard if you have collaborators) is really the way to go. I prefer the second version, but the first one is also quite legible.
If you consider efficiency of what the browser has to do under the hood to render CSS styles, BEM-style for example, is usually the ultimate winner as it is the most lightweight for the browser. I use BEM for some layout/common elements.
In real life unless you are doing something seriously wrong, modern browsers and devices make this difference of CSS parsing and rendering somewhat negligible. But that is if you code everything well.
I've worked with spaghetti CSS codebases that could take minutes to render all SCSS (it was a huge codebase, but a few files were big bottlenecks).
It matters because of specificity. The first style rule will always override the second, regardless of where they both appear in the stylesheet, because it is more specific (basically it has more class selectors in it).
That said, the first rule is a nightmare from a maintainability perspective, for a number of reasons:
It makes code incredibly hard to read and understand
It's harder to override (as we have seen).
If you change the structure of the HTML, it will break
You can only reuse it if you mirror the structure of the HTML exactly.
It's also bad from a performance perspective. When browsers are matching an element to a style rule they read each selector right-to-left and keep going till they either find a match or can exclude the rule. Therefore, the more simple the selector is, the faster a match can be determined. If a selector consists of just a single class name, the browser can match the element with the style rule more quickly than if it has to search upwards in the DOM tree.
The second rule is better, but optimal would be something like the following:
.shopProductsProductDesc--warning {
color: red;
}
This solves all the problems above, and it's long enough that there's unlikely to be name clashes elsewhere, (though obviously not impossible).
In general, nesting selectors in CSS is bad practise, in my opinion, and the best CSS methodologies are those that have ways of avoiding this, e.g. BEM, CSS-in-JS.
According to my own experience, the second option is often best, not for direct technical reasons (in fine, it will perform the same), but rather for UX consistency and code maintenance.
The first option produce an "heavy" selector, which will be harder to override. It can be wanted, but it is often the sign of an overall messy CSS, because if everything is overconstraint, it is less easily reusable/extensible.
From my understanding of CSS and frontend reusable components, you would always only need two levels.
The style of your warning component (no size, no margin, size depends on where you will display it, and margin is position, only internal design here):
.warning {
//Your design here
font-size: 1.5rem;
font-weight: bold;
color: orange;
}
And the positionining and variants inside containers:
.container > .warning {
//This is an example.
position: absolute;
right: 0;
border: solid 1px red;
}
Having long CSS selectors will make things more complex, hard to follow for your teammates, and hard to override because you will probably need a longer CSS selector, and it never ends. Plus, you will get an heavier bundle at the end.
If you want an efficient UX, the UI shouldn't be that different everywhere, so you should not need to have that many variants of the same component. Otherwise, maybe you need multiple different components, but you certainly want a simple and efficient UX, and that often goes with not so much visual concepts, so you must avoid tons of variants.

Overriding CSS and number of selectors

I'm trying to wrap my head around something about CSS. I've always thought that the order of including CSS files matters (the "cascading" part of it). I'm using Bootstrap 3, and trying to override the background color of the active top nav links.
The exact selector I have to use in order to do this is: (SCSS actually, but that shouldn't matter)
.navbar-default .navbar-nav > .active > a {
background: $sp-blue;
color: #fff;
}
And then scss-lint yells at me for having a depth of applicability greater than 3. But if I try this:
.navbar-nav > .active > a {
background: $sp-blue;
color: #fff;
}
then it stops working. This is what I don't understand. Why do I have to include .navbar-default in the selector? If .navbar-nav is within it, I shouldn't need more than that. It's annoying to have to copy the selector exactly as it's used in the previous stylesheet. Now, if I use !important, then it works, but we all know that's bad practice.
Can someone help me grasp this aspect of CSS?
That's becuase .navbar-default .navbar-nav > .active > a is more specific than .navbar-nav > .active > a.
Although the ordering of stylesheets have something to do on how the browser will analyze which css is more relevant, CSS specificity also plays a role.
Basically, the more specific your CSS selector is, the more relevant it is for the browser. Say, we have your css ordered like this:
/*this will be followed*/
.navbar-default .navbar-nav > .active > a {
background: #fff;
}
/*this will be ignored*/
.navbar-nav > .active > a {
background: #000;
}
Although the second selector is ordered last, it cannot override the previous selector, simply because it has a weaker specificity. It can override another css only if it has an equal or greater specificity than the previous one. But of course, !important is an exception to that rule.
Further Reading: http://css-tricks.com/specifics-on-css-specificity/
This is a FANTASTIC question! This shows you are actually thinking through css rather than the millions of novices who don't ask and just 'important!' whenever there's a problem. But you are EXACTLY right. Supposedly well-written CSS has the following constraints:
Do not use 'important!.
'important!' breaks the cascading nature of CSS and opens your design to problems with maintainability and simplicity:
See: What are the implications of using "!important" in CSS?
Avoid a large 'depth of applicability' For the same reasons as 'important!' again this results in a design that is not as maintainable, simple, or easily redesigned:
See: https://smacss.com/book/applicability
Don't modify your framework code Certainly you shouldn't go back and modify your framework's CSS. What if you need to update this code in the future, or some automated process overwrites it? Your code breaks.
One solution (if you believe in the above) is to use the CSS rules them self and target your elements in a more efficient way. Using a CSS specificity calculator such as this one:
http://specificity.keegan.st/
We can see other ways to target your element better. According to the calculator, the specificity of your element is 0031. However, a single id
#mynav {
background: $sp-blue;
color: #fff;
}
scores 0100 and would satisfy the above constraints. One problem is that some ALSO say...
Don't use IDs For similar reasons as the above:
See: http://oli.jp/2011/ids/
We could also use 'inline style' (as you can see from the calculator), however....
Don't use inline styles What's so bad about in-line CSS?
So is there any other way to 1) increase the specificity 2) without increasing the depth, and not using 3) IDs 4) 'important!' 5) inline styles, or 6) modifying your framework code? Well by assigning multiple classes to an element (or parent), we can increase specificity without increasing depth of applicability. Of course this would also work
.thislink1.thislink2.thislink3.thislink4 {
background: $sp-blue;
color: #fff;
}
Now, of course, you don't have to assign 4 different classes to your anchor just to be specific enough or to have your depth less than 3. If you assign a class to the parent
.navbar-nav.mynav > .active.myactivelink {
background: $sp-blue;
color: #fff;
}
this scores 0040 (depth of 2). You could perhaps simplify this further if you are sure that your css modifications are loaded last (since the later loaded rules take priority).
.navbar-nav > .active > a.mylink {
background: $sp-blue;
color: #fff;
}
this scores 0031 (with a depth of 3), like your bootstrap CSS, but if it's loaded after the bootstrap it will be applied.
The takeaway: CSS is not a computer language studied by experts to quantify metrics such as cyclomatic complexity and code quality, it is a style sheet language without much rigorous study of objective measures. It is easy enough to learn that you have many inexperienced armatures and more bad advice than hard evidence. I am certainly no expert so take the above as 'options'. Realize that style is important to learn from the pitfalls others have suffered from. But your particular situation includes your preferences and type of development environment you are in, and how much time it takes to learn all this advice.

CSS for td in table using a wildcard

I'm having some trouble with some CSS. I have a number of unique tables with a similar format name, and I need to set the background color on some of them. However, if I try and use a wildcard the style gets overwritten by a parent CSS file.
The background colour here works fine:
#AllProtectedServers1 td.status.online{
color: green;
background-color: yellow;
font-weight: bold;
}
But the background colour doesn't work here as it's being overwritten higher up (although everything else does):
td.status.online {
color: green;
background-color: yellow;
font-weight: bold;
}
I'm going to have 20+ tables all starting with "AllProtectedServers", so naming them all individually is going to make the css huge. Is there anyway I could use a wildcard? I've tried using div[id^='id_'] and similar selectors without any luck.
Anyone have any ideas of what I could use instead?
Update:
Please note the ID's are unique (AllProtectedServersCompany1, AllProtectedServersCompany2, etc), but they all start with AllProtectedServers. I want to create some CSS that will override the stylesheet for the table that is overriding my changes and use a wildcard so I don't have to specify each one.
Maybe this would help:
td.status.online
{
color: green;
background-color: yellow !important;
font-weight: bold;
}
Alpipego's comment is not correct. You're perfectly fine using ID selectors (#) for CSS. These can be overwritten by other ID selectors of the same or higher specificity (depending on page order) or the !important rule.
However, you want to avoid using !important as a CSS rule because that can back you into a corner and become a maintenance nightmare.
As a matter of fact what you need to learn about is CSS Specificity. I recommend reading the CSS: Specificity Wars for an entertaining but educational overview of how CSS Specificity works.
http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html
Smashing Magazine also published an article on it that's more extensive:
http://www.smashingmagazine.com/2007/07/27/css-specificity-things-you-should-know/
You do want to be careful about not going crazy with specificity. ID's are (supposed to be) unique per page, so if you end up with a lot of deeply nested rules (#foo .bar .baz .goo), you're probably looking at needing some refactoring.
So, if you use Chrome, pop open the developer tool and look at the CSS selector and determine the specificity. All you need to do is:
a) Match the specificity but make your style come later in the DOM page order
or
b) Use a higher specificity
That's all there really is to it.
I hope that helps!
Cheers.
jmbertucci's answer is quite correct, if perhaps a little incomplete, I will expand with some examlpes.
One of the most overlooked aspects of CSS is specificity rules. As mentioned by jmbertucci please see:
http://csswizardry.com/2014/07/hacks-for-dealing-with-specificity/
http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html
A little more googling will present a wealth of articles for you.
Let's take some base html and css and a bit of a guess as to what you have.
HTML
<table class="myTable">
<tr>
<td class="status online">Online</td>
<td class="status offline">Offline</td>
</tr>
</table>
CSS
table.myTable td.status
{
background-color:#fff;
}
td.status.online
{
background-color:#f00;
}
Fiddle
This will result in a white background for "online" as table.myTable td.status is more specific than td.status.online.
In this example we need to make the second selector more specific. As you mentioned adding an ID results in what you want as IDs have an extremely high specificity score and a very hard to over-write. So much so that some say never to use them*. A simple solution in this example is to add table to the seconde selector.
table td.status.online
{
background-color:#f00;
}
This results in a red background for "online"
Fiddle
Adding table may not work in your instance. YOu need to find the style rule that is being applied using Chrome Developer Tools or Firebug for Firefox and create a rule that is more specific.
If you provide more information I may be able to provide a more specific answer.
* A note on ID's ID's extremely high specificty is both their strenth and weakness. I believe they can be used, but with caution. If you want to style a specific part of a page in a specific manner, you may have a canditate for ID. Think along the lines of a header and footer before the days of HTML5. Another good example may be <section id="discalimer">, using an ID provies two benifits: it's an anchor for specific styling and it can be linked to, e.g: Disclaimer. A further read: http://www.zeldman.com/2012/11/21/in-defense-of-descendant-selectors-and-id-elements/
Keep in mind the arguments on weather to use IDs or not are a matter of optinion and their are good points on both sides. W3C, the standards guys, has no stance on this. If where you work has a coding guide, stick to that mandate. If you're unsure, don't use them in CSS to be safe. Most importantly keep IDs unique.
Andy68man, no wildcard needed, just use a class. Same class for all the tables if they all share the same properties. As in (first the HTML):
<table class="allProtectedServers"> ..... </table>
<table class="allProtectedServers"> ..... </table>
<table class="allProtectedServers secondClass"> ..... </table>
and the CSS:
.AllProtectedServers td.status.online { ... }
If there are one or more properties that only some of the tables have, create another class and give those particular tables both classes, as in the third line of HTML above.
Alternatively, if that still gets overruled by the CSS above, put a single div round all the tables or even the whole page (or there may already be one), give the div an id, and add that into your selector to increase it's specificty (your first bit of code above shows the extra id will be enough to overrule the other CSS that's causing your problem):
#myDiv td.status.online { ... }

Loading speed and use of resources with CSS advanced selectors

I am starting making use of "advanced" selectors, and even though with this I am being able to locate and identify all elements on my HTML without needing to classify them or give them an ID, I am worried about if this way of programming (which I suppose is the correct one as most of the online templates/plugins etc... use it) does not need more resources and increases loading times than just using classes and ID's as selectors.
For example, the code above could be done just with some simple selectors, IDs and classes, but I preferred to do it as you can see:
.impairsRight > div{
float: right;
width: 100%;
margin-bottom:15px;}
.content-hola .impairsRight > div:nth-child(odd) > p {
margin-left:30%;}
.content-hola .impairsRight > div:nth-child(even) > p {
margin-right:30%;}
.impairsRight > div:nth-child(even) > h5 {
text-align:right;}
.impairsRight > div:nth-child(odd) > h5 {
text-align:left;}
Is this heavier on size/speed/use of resources than simple ones? Is there any tool or website that can test this kind of things? (not only loading times, algo resources needings)
I have never heard of a case where the use of CSS selectors impair the speed of a web site to a noticable degree.
This is really nothing you have to worry about.

Use css syntax or custom class

Bit of a noob so need some real world advice.
I've just been reading an article written by mozilla regarding the use of css selectors.
Basically, they're saying don't use complex selector trees, for instance:
.class-a .class-b > .class-c is better expressed as custom-class-abc
Obviously they would because the second option is going to be better for the performance of the browser, but if this is the best solution, then it sort of renders a lot of css basics redundant.
I have a UL containing LI's that contain A's. My first A needs to be treated differently, so I use the following syntax:
#footer li:first-child a {}
If I was to follow Mozillas best practice, this would be:
#footer a.first or #footer .first (after adding a class to the first A element)
There is enough to learn as it is, so would appreciate some advice on how this all works in the real world.
Your selector is just fine. Having not read the article you mention I would guess they mean to avoid something like
html body div.wrapper div.navigation ul.nav li:first-child a.item { }
and just do
.nav li:first-child a.item
This article gives a little bit more on why fewer selectors are better for performance. Of course there are extremes of everything and mozilla should recommend how to make things as fast as possible but selectors are already extremely fast so in most cases it makes no difference.
On a related note reading up on specificity in css may also help you determine how much you actually need to select. http://coding.smashingmagazine.com/2007/07/27/css-specificity-things-you-should-know/
I think the article may be out of date to cater for the dumber browsers, but most up to date browsers understand :first-child now. Your example
#footer li:first-child a {}
is how I rock. ie8 doesn't understand :last-child take note.

Resources