At the start of the year, I put together an article on BEM and SMACSS that focused on the confusion of choosing a CSS methodology. I contacted a range of different developers and got their words of advice, their success stories and their horror stories in the hope that others could learn from their experiences with these popular CSS methodologies.
The article was quite well received, but there was a recurring question I’d seen over and over again with BEM that the article didn’t cover clearly: How do you deal with BEM at scale?
It was all well and good to say BEM is beneficial (it is!), but often the guides on the web for BEM stick to the basics. They tell you to arrange things into but there isn’t a lot of guidance on what to do when things get messy. Is okay? Is there a best practice for arranging your CSS files? Should you use to inherit parent class values or should you list those in your HTML?
Watch Become the CSS Hero of Your Office with CSS Architecture
Craft structured, maintainable and scalable CSS
Watch This CourseWatch This Course
In this article, I wanted to get the thoughts of developers who’ve had experience working with BEM at scale already — what do they do? What lessons have they learned in the process that would be good for us to know beforehand?
One thing you’ll find is there are some differing opinions — but that’s okay. I’ve tried to include as many of the responses as possible, even if they include contradictory views, so that readers can make up their own minds.
BEM originated at Yandex, a Russian search engine. It has since evolved into two different streams of use — it can be either the whole BEM stack that Yandex created (CSS, JS, HTML templating and development tools) or it can be solely the CSS methodology behind it.
The latter approach has evolved from the Yandex concept via ideas by Nicolas Gallagher, Harry Roberts, and many others. The team at CSS-Tricks did a great write up on the CSS BEM methodology recently too — worth checking out!
This article will cover a bit of both worlds as I thought it was best to include both perspectives. However, quite a large proportion of the respondents focus solely on the CSS methodology rather than the Yandex BEM stack.
The talented developers that let me into their minds
I’ll start by introducing the developers who were kind enough to let me into their minds to get some tips and advice on using BEM at scale. I was lucky enough to find BEM enthusiasts from all over the world — I’ve got responses from the Netherlands, Sweden, UK, Crimea, and Estonia! A very big thank you to all of them for taking the time to answer my questions.
- Bob Donderwinkel, a front-end developer from Rotterdam – Website, Twitter
- Hamish Taplin, a front-end developer working for Bluegg in Cardiff – Website, Twitter
- Harry Roberts, a Consultant Front-end Architect, designer, developer and absolute BEM guru from the UK – Website, Twitter
- Serge Herkül, a developer at Teamweek – Website, Twitter
- Vladimir Grinenko, the head of the BEM development group at Yandex – Website, Twitter
- Vladimir Starkov, a front-end developer from Sweden who is one of the founders of getbem.com and previously also worked at Yandex – Website, Twitter
Let’s get started looking at the advice from these developers!
Be careful with nesting
Nesting is one of the biggest dangers I’ve seen with development teams using BEM. It is very easy to go overboard and make things much more complicated than necessary. I wanted to know, is naming a class okay? Or should you stick to no more than the two levels of parent and child in ? Different developers have different levels of nesting that they’re okay with, so I’ll cover both viewpoints.
No nesting beyond two levels
This was my personal preference and appears to be the most commonly followed practice by the developers I interviewed.
Vladimir Starkov pointed out his concern for nested classes, saying “it is the wrong way, you should always have an option to use one element without another.”
Bob Donderwinkel also gradually moved to this approach:
“I used the notation at first, but that is not optimal and a little superfluous. So I try to sticking with now, and that’s also easier on the eye ;)”
“It doesn’t really serve a purpose and over complicates your CSS. And also perhaps the extra file size hit which some styles of Sass/LESS nesting can produce. The resulting CSS can get pretty extensive.”
Vladimir Grinenko from Yandex agrees with avoiding nesting too, suggesting making the element name longer if needed, rather than adding more levels of nesting:
“There’s no need to resemble nesting in entity names. DOM structure is enough for that. Nesting may change in the future and the best way to avoid renaming things while refactoring is to name them properly from the very beginning.
In case you really need to resemble nesting in the name, consider doing it with just longer name of an element: ”
Harry Roberts explained the idea of this to me in quite possibly the best way I’ve ever seen, so I’ve included it below almost completely unedited:
“One important thing to know about BEM—and something that I feel causes problems for a lot of developers—is that you do not step through each layer of the DOM. To use a metaphor, the following is incorrect:
“This is terribly verbose and also forces a DOM structure upon us; it is very inflexible. Instead we should write:
“This is much more terse; it doesn’t force any DOM structure upon us, and we can visually indent rulesets to show us an implied DOM structure.
“If you do need to nest one Block inside another then just use traditional nesting. To continue our metaphor:
“This time we want to style Person because it’s Outside—we don’t need to invoke or use anything BEMmy here. (N.B. we are using Sass’ parent selector nesting for better encapsulation here.) Alternatively, though, we could use something like this:
“We can use BEM here in order to create a variation of a person who can be covered regardless of where they are.”
Hamish Taplin doesn’t really follow a strict rule with this but aims to keep things to element and subelement where possible:
“I try to keep things as simple as possible. I have no real preference as it happens so rarely but I generally find that just separating the element/subelement into its own element is enough. An example of this would be whenever you have some of repeating elements inside an element that has its own components (such as header/footer). For example, you could do this:
“However, I prefer to just separate those elements:
“So now we have a ‘list’ element and a ‘list-item’ element that isn’t tied to the ‘list’. I can’t really comment on the pros and cons of this approach because I haven’t given it a great deal of thought, but it’s worked well for me so far!”
However, not everyone agrees with the strict approach
Serge Herkül had a different approach to the nesting restrictions which warrants a mention as I know of other teams that do the same. His team does go beyond two levels deep. He said:
“We use when needed. Try not to get too strict with how the ‘original’ BEM sees things and bend things to your own needs.”
Be cautious with where you start your block scope
A common mistake Harry Roberts has seen is developers starting their Block scope too high up. He gives the following example of incorrect CSS:
Harry explains, “Here we can see we’re scoping the laptop to the desk to the room. The issue here is that that laptop could be in my bag in the trunk of a car; that desk could be moved into the corridor; the laptop could be placed straight on the floor of the room.”
Instead, the focus should be on separating out the DOM elements that can live independently of one another. Start your Block scope from “the smallest, most self-sufficient bit”. As an example, Harry provided the following solution to the incorrect CSS above:
Harry points out, “The laptop now has no dependency on anything, nor does the desk. This is how it should be.”
Separate your CSS in easy to understand files
Serge Herkül had a focus on keeping things modular and in separate files to assist in scaling up BEM. He said, “Our entire SPA is made out of modules. Roughly speaking we have a SCSS file for each module or module group (if it’s made of smaller modules).” He recommends the modular approach for both CSS and JS: “Try combining your JS and CSS modules so they would share the same name ( and ).”
Harry Roberts says “each file should be as small as possible but as large as necessary”.
Vladimir Starkov had separated files per block, modifiers and elements when previously working at Yandex but has found it is easier to focus on separating by block:
“In Yandex we usually separate styles per block, its modifiers, its elements and for their modifiers. But in reality it is very hard to support all these separations. That’s why in pet projects I and ex-Yandexers support a one-file-per-block structure, which is flexible and good enough to support and maintain. Best tip is to extract blocks into different files, one block per file. There is a brilliant article in English by Vladimir (@mistakster) at frontendbabel.info/articles/bem-with-css-preprocessors/ explaining how to maintain your selector’s structure inside block files.”
Bob Donderwinkel considers his approach on a project by project basis depending on how complex things get, but also adapts some SMACSS concepts:
“It depends on the project. I started out by using different files for each Block, and then perhaps files for each Element and Modifier if those got extensive. But nowadays I also use a SMACSS baseline for files often, and fill those with BEM CSS.”
Vladimir Grinenko says Yandex’s focus is on separating by block, with elements and modifiers separated when necessary:
“We store each block in a separate folder. For elements and modifiers additional folders are optional (having them in different files gives us possibility to build a project with just needed parts). e.g.
“Then build tools look at what BEM entities (blocks, elements and modifiers) are there and concatenate needed files in their proper order.”
Hamish Taplin has found his style for structuring CSS files has changed over time and provided an insight into where he’s moving towards and why:
“Previously, I was building my Sass in a structure inspired by SMACSS:
- base (base-styling for typography, forms, tables, grid, etc)
- helpers (Sass functions and mixins)
- modules (My BEM modules)
- vendor (3rd party stuff)
“The contents of everything other than ‘modules’ would remain pretty much the same from project-to-project with only some ‘base’ styling being done on a per-project basis. This would include the basic typographical styling (headings, body copy, etc) for that project and things like tables and forms will be styled.
“Everything else goes in ‘modules’ with one file per module. This might look something like:
“However, dumping everything in a ‘module’ wasn’t really working for me as not every bit of styling can be abstracted into a re-usable module. Obviously, writing re-usable code should be done as much as possible but the realities of deadlines and budgets dictate that sometimes you just need to get something styled and move on. I had it in the back of my mind to look for a better way and had experimented with dropping the BEM syntax for styling that wasn’t intended to be re-usable. I tried this out on a couple of projects and wasn’t really that happy with it.”
Hamish was then influenced by an article by Harry Roberts on namespacing, which Harry himself actually explains a bit further down in this article (it’s wonderful when responses link together so nicely!):
“A few weeks ago, Harry Roberts published an article on using namespacing to get better control over large scale codebases. Although I haven’t completely adopted his approach, he makes some really good points about the types of abstractions he uses. This made a few things ‘click’ for me and I came up with a new approach to structuring my Sass that I’ve been trialing recently:
“The only real difference so far is that I’ve split what I previously called ‘modules’ into two folders called ‘objects’ and ‘components’. Basically, ‘objects’ are pure abstractions such as the ‘media’ object and my own grid system whereas ‘components’ are self-contained implementations of styling such as ‘dropdown’ or ‘signup form’. Those components might even be based on an ‘object’ but will more likely be project-specific whereas the ‘objects’ are much more re-usable between projects.”
ITCSS and source ordering
Harry Roberts has his own methodology for structuring BEM CSS called ITCSS, which keeps things easier to manage and scale. Harry explains it as a methodology that allows you to “break your projects up based around Specificity, Explicitness, and Reach”. He focuses on a specific CSS source order, arranging styles into layers of different levels of specificity. More specific stylings have layers placed near the end of your CSS and globally shared variables, mixins and styles are in layers at the start.
If you’d like more info on the ITCSS framework, Harry’s presentation “Managing CSS Projects with ITCSS” is a great resource (if you’d prefer just slides rather than a YouTube link, they can be found here). ITCSS is a really well thought out framework for keeping CSS manageable at scale and is definitely worth a look.
Harry Roberts recommends augmenting BEM with namespaces. This involves creating a set of namespaces for things like theme classes (in other words, this class is restyling child elements to match a certain theme), state classes (e.g. ) and many more. I’ve seen various developers using namespacing recently in various ways, some using ideas from SMACSS (such as state classes of and layout classes for overall layout containers).
Harry explained the beneficial relationship between BEM and namespacing really well. He said, “I augment BEM with my own suite of namespaces. This adds a whole other layer to the meaningful naming that BEM gives us by signalling the role of a class in non-relative terms: where BEM tells us how classes are related to each other (e.g. must live inside of ), namespacing tells us what a class does in absolute terms (e.g. tells us this class is theme related).”
Harry’s post outlining the namespaces he uses (the one Hamish mentioned earlier) provides more details and can be found at More Transparent UI Code with Namespaces.
Don’t be afraid of long class names
Serge Herkül also suggests a focus on self documenting class names. Don’t be afraid of long class names! His advice – “Use long, descriptive class names over short names that don’t document themselves.”
Avoid Sass’ @extend
I provided the two different formats I’ve seen people use with BEM to the developers to get their thoughts on which they use and why. The first was the style similar to object oriented CSS:
The second was the style that uses Sass to handle inheritance:
I had a unanimous agreement from all the developers on this one. Don’t use where possible — go with the first option!
Harry Roberts recommends avoiding and instead keeping styles defined within classes in your markup (like the first markup example above). His thoughts on this were:
“You can create a greater number of combinations in the view by not ‘tying’ classes together in Sass. The HTML has a much better paper trail in that you can see every class acting on a piece of the DOM. Your CSS stays much slimmer in that you don’t have to create new placeholder classes (or the manifest classes that combine them) every time you want to create a new piece of UI.”
Vladimir Starkov agreed with avoiding the second option as it leads to much bigger CSS files. He prefers “declarative in HTML” with “clean and minimum sized CSS”. He suggested the use of automatically generated systems:
“If you are confused with HTML classes that are a bit messy, then you can generate them automatically. You can try kizu/bemto on github for a jade templating system and azproduction/b_ on github for any nodejs-base templating systems to achieve that automation goal.”
Bob Donderwinkel also agreed with the object-oriented option:
“I personally use the object-oriented approach because it is a little more tech-agnostic. Concerning the Sass approach I actually tried to make things even more ‘organized’ by using multiple modifiers in a single BEM class name (https://gist.github.com/BobD/e51edd989e43aaf3d74d). But the CSS it produced was pretty awful.”
If you needed any more encouragement to avoid Sass’s , Hamish Taplin provided another good example of why it’s better to structure things into multiple classes:
“I very much encourage using the ‘multi-class’ approach in the first example over the ‘single-class’ in the second example. The biggest problem with the ‘single-class’ approach is related to nesting and makes it an anti-pattern, in my opinion. Consider the following example whereby we want to apply a small change to a inside a , making it full width. If we use the multi-class approach to modifiers we can do the following:
“Here, any instance of the will be styled accordingly in the relevant context. If we had adopted the single-class pattern and our had a modified then our CSS fails and we have to add every type of modifer to our styling context. This would be a maintenance nightmare for obvious reasons!”
Lint your CSS!
Harry Roberts also has a brilliant system for ensuring all CSS keeps to the right naming convention: he lints his CSS using scss-lint to ensure all team members stick to the convention correctly. As Harry put it, “It’s all well and good telling the team to use BEM, but it’s important to police it as well.”
Harry even wrote a regex to use with scss-lint that works to detect his style of namespaced BEM classes. You can find that at the More Transparent UI Code with Namespaces article mentioned earlier.
Choose the tools and workflow that work best for you
“One of the most important things about the BEM methodology is that it’s not just about CSS names but it’s all about the same things as Web Components: each BEM block knows everything about itself (styles, JS, templates, images, tests, documentation, etc).
“Also, we have such powerful concepts like mixes — when there could be more then one BEM block on one DOM node: ”
For details on the tools and the BEM stack from Yandex, see bem.info.
As I mentioned above, many developers I know prefer to focus just on the CSS aspect of BEM. However, this doesn’t mean sacrificing the ability to have a fully featured workflow. The Yandex tools can be beneficial for some projects but there are alternatives for those who prefer to use different workflows too. Yandex even provides workshops to help developers use BEM with things like Gulp, Angular, and more.
Vladimir Starkov prefers to focus on the CSS methodology and recommends finding the workflow that works best for your team:
“Basically BEM is only a CSS methodology, and all the stuff invented by Yandex is only their way to make code sharing between teams simpler.
“From this point of view it’s good to understand that you don’t need to use full yandex-bem-stack with bemjson, bh, priv and bem-tools, because this way is very inflexible and hard to be implemented in other workflows.
“To be honest it was a reason for us to create gulp-bem and getbem.com, we wanted to deliver BEM to people in the easiest way.”
One aspect of Vladimir Grinenko’s advice earlier stood out to me — documentation. BEM provides a great base of structured components (your Blocks) to document and keep consistent throughout your project. If you can keep your naming and structure throughout all levels of your site (CSS, JS, HTML templates and documentation) organised by Block components, your project becomes easier to follow and expand. Combine that with the brilliant concepts in Harry Robert’s ITCSS methodology and a well documented and structured site should be just that little bit easier.
I thought this piece of advice from Bob Donderwinkel was quite valuable:
“I guess my main word of advice would be to keep your BEM CSS portable to other projects if needed. This means not over-automating things so they are only useful in a single project environment. That is not to say you will eventually re-use that specific piece of CSS, but at the very least it will result in a clean CSS approach.”
Still haven’t tried using BEM in your team?
For those who haven’t taken the leap into giving BEM a go just yet, I thought I’d finish up the article with some words from Serge Herkül on his positive experience with BEM and Teamweek:
“We originally did not have any specific CSS structure and stuff just started to slip out of hand. There was a lot of Sass nesting going on, resulting in long CSS rules. Some styles were affecting other elements, that they were not supposed to, etc.
“Moving to BEM was a pretty straightforward process, a lot of manual labor but not too hard. In the end I cannot think of a better way, all of the problems we had before are gone.”
I hope this series of interviews has provided a good set of tips and ideas for developers looking to implement BEM on large scale projects (or even small projects which always have the tendency to grow exponentially in ways you least expect). If you were previously unsure about using BEM on your next project, maybe this will give you a little bit more of a push to give it a go — the benefits are worth it!
Have you got any tips or ideas on using BEM at scale that weren’t covered? Feel free to include your thoughts in the comments below.
PatCat is the founder of Dev Diner, a site that explores developing for emerging tech such as virtual and augmented reality, the Internet of Things, artificial intelligence and wearables. He is a SitePoint contributing editor for emerging tech, an instructor at SitePoint Premium and O'Reilly, a Meta Pioneer and freelance developer who loves every opportunity to tinker with something new in a tech demo.
1653 days since this post was last revised. Specific details are likely out of date.
This is the ‘text version’ of the presentation I gave at the 2013 CSS Summit. If you’d rather just look at the slides, here’s a direct link to them as a PDF.
Who this is for
This is aimed at users that are comfortable with writing HTML and CSS/Sass but would like to know about how Chrome Developer Tools can help them write more performant Sass/CSS or troubleshoot stylesheet problems. Before we look at the parts of the Developer Tools that can specifically help with CSS we will have a little orientation; covering some Dev Tool essentials. Then we’ll get into testing your CSS.
I have no affiliation with Google. I’m writing about the Chrome Developer Tools simply because I have found them the easiest to work with and the Chrome developer relations team do a great job of documenting the new features they introduce. I’ve put together a list of some of my favourite videos/talks/slides on the Chrome Dev Tools over on this Gist. The majority of what I’ll cover is covered in one of those talks too.
Here’s what we will cover in the Dev Tools Essentials section:
- Selecting elements with the magnifying glass
- How to move nodes
- Edit nodes (adding classes, editing IDs, deleting nodes, hiding nodes)
- Dock the Dev Tools left or right
- Viewing the hierarchy of nodes
- Styles panel – adding styles
- Viewing the computed style of an element
- Toggling the pseudo state (hover/active) on elements
Then here’s what we will cover with the Chrome Dev Tools in specific relation to Sass/CSS:
- Dealing with ‘Rule Rot’. How to find out which rules from your stylesheets are actually being used across the pages of a site. Useful if you need to remove old rules. Copy/paste into Excel.
- Find out if you are using any invalid CSS properties or values in your stylesheets.
- Find out how ‘performant’ your CSS is. Are any of CSS property/value pairs causing slow pages?
- Is your CSS inefficient. When you scroll and interact with your page, how much work are you causing for the browser?
- Cut out round-trips to the text editor. Link to post.
- Extra – configuring and using CSS Lint
Before we get into testing stylesheets with the Chrome Developer Tools, it’s important to know that every browser will be slightly different in how they interpret and apply CSS. Therefore, just because rules and pages are tested and perform well in Chrome, does not mean they will display similarly/faultlessly on other browsers.
However, doing some (any) testing of your CSS is better than none. Perhaps when you have got the bug for testing in Chrome, you can become familiar with the similar(ish) tools available in other browsers.
Chrome Dev Tool Essentials
If you’ve never used the Dev Tools, or use them infrequently, it’s probably worth reading this section. If you’re already pretty proficient with the Chrome Developer Tools, you can probably skip ahead.
Invoking the Developer Tools
To open the Chrome Dev Tools either right/cmd-click an element on the page and click ‘Inspect Element’ from the contextual menu or choose View, Developer, Developer Tools from the main Chrome menu (there’ll be a shortcut key combo listed there too).
Positioning the Chrome Dev Tools: bottom, right or floating
When the Developer Tools are active, you can click and hold the big grey header bar and drag it over to the right if you prefer them docked to the side (really handy for trouble shooting slimmer viewports when doing responsive web work). If you want them back at the bottom you can click and drag them back. Alternatively, you can switch Dev Tool positions by simply clicking and holding the view button bottom left:
Selecting elements on the page
You can choose the elements/nodes you want to inspect by either clicking on the relevant node in the Elements panel or clicking the magnifying glass at the bottom left area of the Developer Tools and then hovering the mouse over the area you want to inspect in the viewport.
‘Nodes’ is just the term for elements within the DOM (Document Object Model) – a.k.a. the hierarchy of elements in the web page.
Expanding the DOM tree
Within the Element panel of the Dev Tools, for each node that contains other nodes a disclosure triangle can be clicked to disclose the contents of the selected node. Any ‘leaf’ of the node tree lacks a disclosure triangle, making it easy to know when you have reached the final node of a branch. A hierarchical path of the current selected node from the root is displayed at the bottom of the Dev Tools window.
How to move/edit/delete nodes
In the Chrome Dev Tools you can actually move, edit and delete nodes and see the results instantly in the browser window:
Move a node
To move a node, simply click and hold the disclosure triangle and then drag it somewhere else in the DOM:
Edit a node
To edit a node, just double-click the attribute you want to edit, amend and then press Tab – the change will update instantly in the browser window.
Add attributes to a node
If you want to add an attribute that wasn’t there already, just move before or after the attribute you clicked and add what you want:
Delete a node
If you want to delete nodes, simply right-click on the relevant element in the tree and choose ‘Delete Node’ from the contextual menu:
Toggle the visibility of a node
If you need to toggle the visibility of an element (note: toggling the visibility of an item is not equivalent to display: none; – it retains it’s physical space and just turns off any visible styles, we’ll see why this is useful shortly), with a node selected simply press ‘H’. You’ll notice this will add the class to the element when active.
Using the styles panel
The styles panel is your direct access area to the CSS rules that are applied to the page. You can edit existing properties, add new ones and even save the values you amend directly back to the source Sass/CSS files.
Edit existing styles and adding new properties and values
With an element highlighted, the applied rules show in the styles panel:
‘Computed styles’ are what the browser is actually rendering to the browser window. This is useful for comparing what you think should be applied and what the browser is actually applying.
‘Styles’ contains a window to add an inline rule directly to the selected element.
To the side of the Styles header from left to right are some extra buttons:
The first is the ‘New Style Rule’ button. This allows you to add a new rule into a Web Inspector stylesheet (as opposed to inline on the element). Next is the toggle element states button (hover, active, visited and focus). Finally, a settings button to toggle how colour values are displayed (RGB/HEX/HSL).
The ‘Matched CSS Rules’ section includes rules from any stylesheets that are being applied to the selected element. Rules that are being overwritten via specificity have a line through. You can also switch individual properties on an off with the tick box to the side. Rules that have been commented out in the source Sass/CSS with a CSS comment show here but have a line through and are also unselected.
- You double-click to edit any value.
- Increment numeric values with the up and down keys (hold down shift to increment in 10s, hold down alt to increment in .1s).
- To add a new property to a rule, simply click to the right of the closing curly brace.
- Chrome will also auto-complete CSS property and value pairs – handy when you can’t remember the correct value.
Also note that in the Matched CSS Rules section, an indication of where the rule originated is given. Clicking this will open the source stylesheet file in the Sources tab of Dev Tools.
If you’re working with Sass (*cough* buy my book Sass and Compass for Designers *cough*) and you have source map support enabled you’ll see the partial file that generated the styles rather than the resultant CSS file. Clicking that partial name will open it in the Source panel. From there you can save it directly back to the source Sass files. Full info on how to enable source map support with Sass here.
Essentials Section Summary
That was by no means an exhaustive list of the Element/Styles panel features of the Chrome Developer Tools but it covers enough for us to crack on with the Sass/CSS specific testing we need to do. Pull on your starched white lab coat.
Troubleshooting CSS (and Sass) with the Chrome Developer Tools
Chrome Release Channels
Chrome has a number of release ‘channels’: Stable, Beta, Dev and Canary.
– Stable is the version that normal ‘muggles’ get.
– Beta is slightly ahead of Stable in terms of the features it ships with but is quite stable.
– Dev contains more experimental features and enjoys more frequent updates but is still relatively stable.
– Canary on the other hand is the bleeding edge version that is full of the new dark arts stuff (between you and me, I heard a rumour that it’s built purely from hawcruxes and crow spit).
As it’s such a maverick, Canary will live happily alongside your other version (either Beta, Dev or Stable) of Chrome so it’s still worth keeping around.
You can download any of the various releases here: http://www.chromium.org/getting-involved/dev-channel
Dealing with ‘Rule Rot’.
Sadly Chrome has now removed the CSS selector profile feature which I feel is a great shame. I asked Paul Irish (Chrome Dev Team) via Twitter and he replied:
I’ve left the info in here for posterity but be aware that it’s unlikely we will see the tool in this format again.
Chrome can tell you which rules in your stylesheets are actually being applied. Browse to any site you like. Open the Dev Tools. Now switch to the Profiles panel. Select the ‘Collect CSS Selector Profile’ option.
Now click the Start button from the bottom of the interface (a circle). The circle will go red to indicate that a recording has started.
Chrome is now recording the actions we take and counting how many times a selector used in our stylesheet is matched and how long it took to match. The best part is that it isn’t limited to a single page. Click around a site whilst Chrome records in this manner and try to invoke every style. Activate buttons, make hover styles appear and when you feel you have viewed all pages, click the stop/record button again. Don’t worry if you screw it up. Just select the profile on the left and click ‘Clear all profiles’ button (the one next to record). Then start again. Once you have a profile recorded, select it over on the left:
You’ll be presented by a four column table. The columns:
- Selector – the CSS selector in question
- Source – where the rule originated (handy if multiple stylesheets are being loaded)
- Total – how long did it take, in percentage terms to select this element
- Matches – how many times was the selector matched during the profile recording
Obviously, the more data you have recorded the more useful it will be. It’s important to keep in mind that these kind of optimisations are more worthwhile the bigger the site/application being styled is.
With this data, we’re typically looking to find low-hanging fruit. For example, rules in our stylesheets that simply aren’t being employed. I term this ‘Rule Rot’ simply because they are generally more prevalent on older sites where refactors have taken place and unneeded styles have not been removed.
To look for possible rule rot, if you click the Matches column it will sort the results by that column. Take a look at the rules that have no matches and crucially reside in your authored stylesheets. Are these rules intentional? Are they old rules that are no longer needed? If so, you now know where they are (the source column provides the line number). Don’t forget however that this information is only based upon the styles that were used (or not) whilst the profile in question was being recorded so ensure you haven’t forgotten to visit an important page or section so that the required styles were triggered (for safety, before starting a large refactor, I tend to run 3 or more profiles to be sure).
A great post for a ‘Deep Dive’ on CSS performance: http://perfectionkills.com/profiling-css-for-fun-and-profit-optimization-notes/
Export to Excel
Pro Tip: within the Profile window, select all the contents (e.g. command+A on the Mac) and copy them.
Now open Excel (or spreadsheet program of choice) and paste the contents in. You can now prettify this, show it and share it with colleagues or, if you really have nothing better to do, go crazy and make a chart or one of those pivot things I don’t understand.
Testing the performance of your styles
There are long held beliefs when it comes to CSS performance. However, whilst many hold true, they may not be true or be of negligible importance on YOUR site. Remember, the reason to use these tools is to replace conjecture with data. With said data it’s then possible to take action relevant to your site. Choices can then be made on empirical facts and not generalisations.
There are a number of tools available in the Chrome Developer Tools to test performance. For CSS performance, the two features I have found most useful are ‘Show paint rectangles’ and ‘Enable continuous page repainting’.
Depending upon when you’re reading this and what version of Chrome you are running these features may sit behind a guarded door. If you don’t see these options easily, in the Chrome address bar type and press enter. Now scroll down the page until you see ‘Enable Developer Tools experiments’ (or command+F and search for it) and enable it. Now restart Chrome.
Continuous page repainting
Click the cog at the bottom right of the Developer Tools window and under the General section, enable ‘Continuous page repainting’:
You’ll now see a tiny graph at the top right. It’s showing you how long, in milliseconds, it takes Chrome to paint the the current viewport (decrease the page width and the paint time typically reduces as there is less to paint). At the bottom is a graph showing previous paints. The line above indicates a 16ms threshold. Typically, something on desktop that has a paint time that exceeds 16ms could struggle on lower powered devices (e.g. mobile). 16ms isn’t an arbitrary number either. On a 60Hz screen (which includes many common devices but certainly not all), 16ms is the time available between refreshes of the screen to complete a frame. Therefore, the aim of this game is to reduce the paint time to get things below this threshold. ‘Expensive’ styles can come from surprising places. Luckily it’s easy to toggle styles and properties in the styles panel, or visually hide an element entirely by selecting it in the Elements area and pressing ‘H’. This way you can weed out suspects and deal with them accordingly.
Example: http://www.apple.com/iphone/ios/ – scroll down to this section:
That’s a pretty high paint time. But what’s causing it? All those images? Fancy text? Nope, turns out that it’s an inset box-shadow style. Try for yourself. Select the relevant and toggle the two box-shadow styles (it’s a vendor stack so one is a prefixed version of the same rule). Removing those properties and values makes little difference to the visuals but an enormous difference to the paint time of this element. There’s a box shadow style there too. Removing either one drops the paint time considerably so there’s clearly a high cost to having both styles on there at once.
Remember, this doesn’t mean you have to remove such effects (but come on, gradients are about as cool as flares right now – or are they cool again and I missed the memo?). However, such tests gives you some data on which to make some choices. Your choices.
*Updated info thanks to clarification from Paul Irish (Google)*: Selectors, technically, have zero effect on paint times. When testing paint times it’s therefore essential to concentrate on properties and values in your CSS, not the selectors (plus selectors are very fast regardless). Furthermore, when looking at the performance of a page holistically (and not just the isolated performance of CSS) he recommends always starting with a Timeline recording (more info on this as I update the post) which should be done before you focus on selector matching, painting, or layout.
Again, for the people at the back in the cheap seats – note: this is just Chrome. Other browsers may be better/worse at similar painting jobs.
Show paint rectangles
A related feature to ‘Enable continuous page repainting’ is ‘Show paint rectangles’. With this enabled, Chrome gives a visual indication of which areas of a page are being repainted as you interact with it. Here is how you enable it:
In browser terms, the ‘painting’ means what you expect. As the browser interprets the various data (e.g. HTML, CSS, JS) it composites the design to the screen as a series of ‘tiles’. If nothing changes, visually, as you interact with a page, there are likely few page repaints. This results in better performance as the browser isn’t having to perform re-calculations constantly. Let’s look at an example: http://store.apple.com/us
With paint rectangles enabled scroll up and down the page. You’ll see red rectangles flashing in certain areas as you scroll up and down but not in others. These are the areas that are being repainted by Chrome each time the page is scrolled.
As with the continuous page repainting mode, it’s then possible to switch off properties relevant to that element. In this instance, it’s a style being applied on hover, perhaps not a problem in itself but this also occurs as the page is scrolled and perhaps those hover states are unneeded. This is a very common scenario and there are some easy to implement workarounds if it’s a problem for your page/application. Here’s a great post on paint times by Paul Lewis of Google over at HTML5 Rocks.
Resource bloat and asset encoding
The Chrome Developer Tools can tell you quickly and easily what assets (scripts, stylesheets, images) a page is loading; how many separate requests (number of files downloaded) a page is making and the total file size of said requests. Let’s have a look at another Apple page: http://www.apple.com/ipad/
With the Developer Tools open, switch to the Network panel. Now refresh the page. You’ll now see a long list of all assets that page is loading. Scroll to the bottom and you’ll see the totals in a grey bar. In this instance: 133 requests ❘ 4.4 MB transferred ❘ 5.06 s (load: 1.79 s, DOMContentLoaded: 1.37 s).
You can use the column headers to sort the assets and key for us is ‘Type’ as this allows us to look at all the CSS files. Could the files be combined to minimise the number of requests (for stylesheets, if using Sass this is obviously trivial)? Could smaller image assets be converted into SVGs for resolution independence? And embedded into the stylesheets as Data URIs (use Compass alongside Sass for easy conversion)?
Some recent data on usage of Data URIs indicates that they may be considerably more expensive, performance wise, than image files on mobile handsets. Go take a read of this post for more info: http://www.mobify.com/blog/data-uris-are-slow-on-mobile/
Furthermore, you can also check if the assets you are using are being served ‘gzipped’ (Gzip is just the server equivalent of Zip’ing a file. It compresses the asset for smaller data size ‘over the wire’ and the browser automatically deflates it on receipt). Command/right-click the headers area and tick the ‘Content-Encoding’ option. This additional column will indicate which of the assets were sent gzipped. If none are, it’s time to look at how you can make that happen. Most servers use Apache to serve files and the HTML5 Boilerplate project has a great .htaccess file that typically makes gzipping happen automagically.
If you’ve never used the Dev Tools before to look at the performance of your CSS/Sass, hopefully, those features will give you some ideas about what you can achieve.
If that’s CSS performance, what about CSS quality? Chrome can help here too and we’ll also take a look at CSS Lint, a (sometimes maligned) tool that can automate CSS quality control to a degree.
CSS Errors in Chrome
In Chrome Developer Tools, switch to the Console tab. Here you will see any errors and warnings that Chrome has for the page. If you just want to see CSS errors, click the Filter button and un-tick anything other than CSS:
You’ll now see any CSS rules that Chrome deems ‘invalid’. These can’t be taken ‘as read’. Some may be vendor prefixed rules that apply to other browser vendors and others may be there for a specific reason you know about but it’s a handy way to catch common mistakes. As an example, I have a bad habit of writing ‘font’ instead of ‘font-family’ and this feature of the Chrome Developer Tools catches me when I drop the ball.
CSS Lint (note: nothing to do with Chrome)
Whilst we are on the subject of CSS code quality, I think it’s worth mentioning CSS Lint. It’s a configurable tool that let’s you specify the CSS faux pas you are looking for. Paste your CSS into the big empty box and then click the big down arrow:
There are plenty of options enabled by default I don’t consider a problem. But remember, these are your style sheets so take a look what it’s checking. Also be aware that many text editors have plugins for this. Sublime users will want to check out https://github.com/SublimeLinter/SublimeLinter.
Typical examples of the kind of problems it can spot are declaring a float alongside display: inline-block; – which will have no affect. Conversely I don’t give a monkeys about ‘Avoiding un-anchored hovers’ (generally only affects IE7 badly) so I un-tick that before linting. Like the Chrome Developer Tools console errors, CSS Lint is generally worth using before pushing styles into production rather than throughout the iteration stage. A final sanity check before going live.
Chrome Developer Tools Voodoo
Perhaps the most innovative and time saving feature of the Chrome Developer Tools of late is the ability to save amends made in the developer tools back to the source files. This prevents round-trips to the editor. See a problem or need to change a style? Simply Command-click a property or value and the relevant file opens in the Sources tab. Now edit the value and press command+S and the file is saved and the change reloaded straight into the browser. No need to head back to your text editor! At present, the setup of this is relatively long winded but I have an exhaustive post covering how this can be set up. Interested parties should head here: http://benfra.in/1z1.
If you’ve never looked at this sort of testing before, well done for reading this far. We’ve covered a lot of ground.
Remember, here are further resources on all things Chrome Dev Tools related: https://gist.github.com/benfrain/5908652.
I hope it’s given you a little insight into how you can use the Chrome Developer Tools to get real data about your stylesheets and make them leaner and more performant.