I've been re-examining how we declare and manage CSS objects at LP, recently using the placeholder syntax (%) in Sass over a class. I had a couple of reservations around this, partly because its a leap away from the traditional OOCSS method of using multiple classes as building blocks but also in its usability and impact on performance.
The more Ive been dabbling with the placeholder approach though; the more I can see that traversing the middle ground between the two is going to result in suboptimal code. So I decided to do some research and disprove my reservations.
For those who haven't yet used them, selectors with placeholders will not be included in the CSS output but they are able to be extended. For example:
%some-unused-class
color: red
background: black
%base-button-class
padding: 10px
display: inline-block
.checkout-button
@extend %base-button-class
background-color: red
.submit-button
@extend %base-button-class
background-color: black
will output to:
.checkout-button,
.submit-button {
padding: 10px;
display: inline-block;
}
.checkout-button {
background-color: red;
}
.submit-button {
background-color: black;
}
And an example using everyones favourite media object would mean we no longer have to chain the .media class to benefit from its abstraction:
%media
the media object
.comment-block
@extend %media
Effectively what this allows us to do is construct our css objects in our css as opposed to in the markup. There are definitely pros and cons to this approach and all could be subjective depending on your existing codebase and workflow. I've highlighted some below but I'd be keen to hear of any that I have missed.
Lets compare the two from a maintainability standpoint.
OOCSS | OOSass |
---|---|
Styles are defined by the markup | Styles are solely defined in the Sass |
Simpler, all declarations are available for use in the dom | Only some style declarations are exposed |
Potentially leaner stylesheet | Leaner markup |
OOSass pros and cons:
Pros
- More readable style declarations - theres no need to keep your naming short
- Leaner markup
- More selective use of styles (only really applicable to sites with multiple stylesheets responsible for different areas)
Cons - all debatable
- Back end devs have to write Sass if they want to build up styles
- Slower to iterate on styles than directly on the dom
- Only possible using preprocessors
Questionables (makes sense to me but is it actually a Pro?)
- OO happens within the CSS
Performance
If you're working with OOCSS chances are you care about performance and metrics. So, whilst the placeholder syntax is feeling like a nice approach to me, I wanted to run some tests to see the effect on css size.
I took the css for ianfeather.co.uk as the base file. It was written a long time ago with loose OOCSS and is fairly performant but not heavily optimised.
Following this, I optimised the CSS by abstracting out some classes and thinning down a few selectors. I wasn't expecting big improvements but I wanted to ensure that I had a performant baseline file to test against.
My main concern was that the gzipped file size would actually increase because of less repetition in the code so it was good to see that this is minimal and that the final code is still smaller. (This blocker could potentially be removed only by extending placeholders which have at least two rule declarations inside.)
File size | When Gzipped | Compression rate | |
---|---|---|---|
Base | 26514 | 7055 | 73% |
After optimisation | 26411 | 6196 | 77% |
Using OOSass | 24520 | 5920 | 76% |
Performance in the browser
The CSS file size is key to the critical path but I also wanted to ensure that using this method wouldnt increase the selector matching or paint time.
I created two pages, each with 1200 buttons, one using chained classes and one using extended classes. I then profiled them using Operas CSS Profiler. Unfortunately the results were absolutely identical so this test was inconclusive. Perhaps a larger test file with more variance would be required to create a true test.
The Profiled results for both pages:
Conclusions
Whilst our test showed there was no huge performance benefit for this approach, it also failed to show a downside for it. This, for me, is a validation of the approach and allows us to look at the more intangible benefits we outlined earlier.
I also think there are performance gains to be made when scaling up. We'll use our Sass gem, Beaker, across a fairly wide range of projects and using this will mean each project has access to all objects and base classes as well as the ability to pick and choose which are required and which will be output to their project.css file.
Whether or not this approach is right for you is likely dependant on your existing css architecture. For us, we have the opportunity to shape our future CSS and I think this is a healthy way of doing it.