Page is a not externally linkable
- Code, Content, and Presentation
-- CSS
---- CSS Selectors and Page Speed


SuzyUK - 11:41 am on Mar 1, 2011 (gmt 0)


I've ranted on long enough about the "warnings" that Google's PageSpeed puts out about "inefficient selectors" and "remove unused CSS, and I thought I might try and discover what might actually make them more "efficient" or to see if looking for those "needle in haystack" unused ones would be worth it.

As part of my quest I watch a very long (and sorry, but very boring/dry) video talk by David Baron : Faster HTML and CSS: Layout Engine Internals for Web Developers [youtube.com], I did take from it a bit about Mozilla's theory about how they parse CSS in relation to everything else that needs to go to output a page. and why they have to do it like this because of subsequent or immediate changes any scripts may make to the page rendering

Also I came across an Article by Snook [snook.ca], which starts off an subject you wouldn't think is related, but it is.. the article as well as explaining the "lookback" dilemma nicely, then has a further enlightening bit, from snook, in the comments ref: simplifying selectors:

Complex applications like Yahoo! Mail benefit from simplified selectors and improved rendering times because of the amount of work that is being done on the client. If you have a blog then it really isn't an issue because the page is rendered once, with few rules needing to get evaluated. Changing everything to ID or class selectors won't be worth the maintenance headache.


This is what I'd always thought, I knew it was Yahoo's (Grids) and Googles (Blueprint) policy to want us all to use class names for everything.. it turns out that it is because they have to as it does affect their rendering, Yahoo page especially is in a constant state of change, so the quicker the make a selector unique (reading it from the right side) the better.. for most normal websites it isn't worth it. The time to lookback through a rarely changing page would be minimal to none. IMO an exception is possibly those dropdown menus.. which I might get to refining later

So I made a page, a very simple test page (no images!), made sure it "passed" the test on all points - compression and minimised HTML especially.. IOW I wanted to get to a point where the CSS and only the CSS was affecting the "score"

the results slightly surprised me, but not much

with 5 very inefficient selectors I still got a score of 100, with a green tick next to the "inefficient selectors" although the arrow could still be clicked to see those 5

repeating those same 5 to have 10, the score did drop - to 99 - with the yellow triangle

repeating the 10 to 20 no change, in fact repeating on up to 80 there was no change, however the rules were only repeated which may have had an effect, but I think it's more likely that the "warning" is only worth a minor score drop. The fact that the selectors were repeated did not give "unused selector" warnings I wanted it that way as I didn't want one warning contaminating another.

However onto them, Unused Selectors, I deliberately input some, so with the page score at 100 with - 1 very inefficient rule - I added 10 unused EFFICIENT ones (I copied the 1, made it efficient, and changed the class name on all 10 rules to 10 names not in use) then 20 then 30.. no change to score.. it remained at 100, when I made these unused selector inefficient again, the score again dropped to 99 and
that was because of the inefficient selector warning not the unused warning!

my conclusion (would welcome views!) is that it doesn't matter one single bit about the unused selectors, though in theory it should as they are unnecessary lookbacks.. what was more important was the efficiency of them. IF unused selectors are efficient the "lookback" load must be so tiny it's not worth the effort, nor necessary to "penalise".

Further conclusion, if you want the nice green tick, and to actually affect page performance make all selectors, used or not, "VERY efficient"

How do you do that?

Well the good news is that it doesn't matter about "qualifying" class names or IDs (though qualifying a unique ID shouldn't be necessary if that ID is indeed unique!) - I thought PageSpeed much have got smart enough to figure that out, it was one of my biggest gripes as reuse of class names is a big part of CSS), indeed by the end of my tests I finally realised why that particular warning was there at all!

"qualifying a tag" means that you add the element name it belongs to your selector e.g.
ul.one li p a - you have qualified the ".one" class by adding the "ul" element to it. This always irked me that it, "qualifying", appeared in warning messages, as it's possible to use a class name on multiple elements (tags) and you may very well need to qualify the class in order to get specific. Theoretically modules or plugins can introduce identical class names too so it's not just a simple case of ensuring your own CSS only attaches a class name to a particular element, e.g. class="list" can only be used on <li> elements, which is most people understanding of the warnings given.

So to the Good news.. if you make
ul.one li p a efficient.it becomes (for my code - do not take this as gospel without reading further!)
ul.one>li>p>a

by introducing the parent selector (>) you make things really easy for the browsers to lookback through the tree.. it starts at the <a> - reads selectors from right to left - it can immediately start reducing the amount of lookbacks as it no longer has to traverse very far up the tree to see if the next element, <p> is in the <a>'s ascendancy.. it only has to look at it's immediate parent, and so this goes on.. wheareas with the default descendant selector
li p a {} it might have to look back the whole document tree, all the way back to the root body tag at times.. to see if there's any chance there's a <p> in an <a>'s ascendancy, before it can then start the lookback all over again to see if all <p>'s matched have an <li> in their ascendancy.. in other words multiple lookbacks may have to occur

but with my code, it's not flexible enough.. what happens if I want to target all <a>'s inside an li, no matter if they're inside a <p> or not.. should I write the selector

  1. ul>li a {}
  2. ul>li>a {}



2. will not work to target the <a>'s inside any other element that happens to also be in the <li>.. e.g. <p> <div>

1. will work! no warnings

#1 was the surprise, I really expected it to throw the warning again, but apparently it's smart enough not to warn about the descendant selector if it "knows" that there could be other possibilites.. it fits with something David Baron said in that video too.. make a selector efficient/specific as soon as possible starting at the right side.. you see in my code those <a>'s could have been inside a <p> element which was inside the <li>.. or it could have been inside a <strong> element inside the <li> (they were actually!) - in other words it could not be made more any more efficient without me having to add more rules but .. e.g.
ul>li>p>a, ul>li>strong>a {} - btw I removed the <p> and <strong> elements, which would have meant that rule #2 would possibly have been my best choice for efficiency, then rechecked just in case PageSpeed had got really clever matching subtly unused to efficiency.. but no.. it still didn't flag ul>li a {} as inefficient, cool I would have hoped not that would really make "efficient" maintenance an impossibility ;)

Lightbulb moment, on qualifying..

..then I added a class somewhere into the mix, on the ul:
ul.one>li a - not an unreasonable request given that one way around most of the warnings is to add classes to everything - I got a warning again though this time it was not "Very Inefficient (good to fix on all pages):" like the previous ones had been.. just inefficient "Inefficient rules (good to fix on interactive pages):" and there's the clue.. interactive pages, most are these days what with JS libraries being built into most CMS'es and other fancy plugins abounding

so how to "fix" for all?

choices, adding selectors for every contingency
ul.one>li>p>a, ul.one>li>strong>a {} is one way, and changing the class to an ID so making it unique and removing the need to qualify the tag too, does it too #one>li a {} or simply ensuring that you never have clashing class names (fairly impossible) so removing the need to qualify too..

most modules or plugins to the page will come with its own "namespaced" CSS i.e. it will already be wrapped in a uniquely identified div, this is so the JS/required interactivity can be targeted.. the module CSS that accompanies it may not be as efficient as it can be however ;)

In the grand scale of things this was just an eye opening information exercise, it's probably not worth it for smaller sites as Snook points out, however if you want to squeeze every last drop of performance out of your page, or just want that green tick... refactor your CSS or at the very least your module/plugin/addon CSS, by adding to your selectors :o.. and if you're worried about unused selectors, DONT, just make them efficient, then it won't matter if they're there or not (it should no longer affect the score or speed) however the act of refactoring them to be more efficent should help you decide if they're required or not ;)

Any thoughts or other discoveries or any views on when/if it's worth it to refactor?

Suzy


Thread source:: http://www.webmasterworld.com/css/4274514.htm
Brought to you by WebmasterWorld: http://www.webmasterworld.com