70% Repetition in Style Sheets: Data on How We Fail at CSS Optimization
meiert.com
meiert.com
- Optimizing your images.
- Concatenating+minimizing+gzip the JS and CSS.
- Optimizing Javascript.
Likely in order; mileage might vary. If those 3 are already in place, then it might make some difference to optimize the CSS.
First meassure what you actually want to improve (it is not page size per se, it is loading time). Then make sure that you optimize it and not something else.
I'm completely with you on the 3rd party stuff too. If I run ublock on the relatively JS heavy React site I work on, load times creep in at sub-second, I reckon I can get that down to half a second by hammering the code and applying some smoke & mirrors, but there are obviously diminishing returns on client side optimisation.
Disable ublock and that loadtime triples - likely due in no small part to the three (3!!!) different versions of jQuery the adverts & misc 3rd party scripts are currently loading.
I can't help but wonder if the secret to fixing the internet for the less tech savvy general public isn't messing about with stuff like AWP, offline first, whatever, but to force code going through DFP and GTM to respect the browser and the host site a little more.
There is still worth mentioning the issue of executing code once it's decompressed - so properly scoping a var is always better value for money than global.ancestor.foo.bar etc.
That said, my point still remains the same time invested in learning+using+tuning uncss would probably be better spent on any of my points or some others suggested here. AFTER that, sure! I got the whole page for the library I linked down to 10kb in TOTAL including images [in svg] for a competition. It has gained a bit since then though, mainly with analytics.
In terms of developer productivity, keeping stylesheets uncluttered and easier to maintain is a good idea anyway.
Quoting the article:
"CSS with this much repetition is also expensive: It’s expensive to create, and it’s particularly expensive to maintain (not even variables will save those who, on average, repeat each declaration nine times, like the Engadget and TED teams)."
In fact, I'd go further and say in a lot of cases it's not even something you're hosting.
It's what third party resources you're relying on. Got ads? That will be the biggest bottleneck here, since ad networks load hundreds of KBs worth of scripts and images that most people block or ignore anyway.
Same with third party social networks and media sites. That YouTube video or embedded tweet is probably using a lot more of your user's bandwidth than anything else.
Not sure what the solution would be there, especially if you're reliant on the ad money or need to use videos or third party media to illustrate your article.
Might not always be true but in tests I've done on my company's sites the http2 load is always faster with no CDN, even from far away locations.
The golden age of CDN's is over. Their primary advantage was being able to open up many parallel connections using multiple subdomains and the ability to cache across domains.
With http2 multiple connections have become a bad thing and https is mandatory so CDN caching is irrelevant.
On http2 and a tiny AWS instance I can get sub 200ms page loads from anywhere in the US if I host in the midwest. The gain from avoiding multiple HTTP connections, TCP slow starts, and TLS negotiations negates all the speed advantages of using a CDN. Cloudflare might be worthwhile if you get massive traffic but a small Nginx instance can handle hundreds of megabytes per second of traffic.
That being said, for less mission-critical projects, they do have their place.
CDNs involve a big set of tradeoff choices you have to make, they don't make sense for every circumstance. I don't think I'd ever throw in "Use CDNs as much as possible" into an optimization advice list.
CDNs are one of those cases where the cloud vastly outperforms whatever kind of server you have.
Counting unique declarations doesn't really tell me anything. CSS isn't simply a declarative language. CSS rules are ordered. Sometimes (and oftentimes within webapps) you need to repeat a declaration because you're using it to overwrite an earlier declaration but only when the second selector is valid. For example, it's very common to have lots of `display` declarations that turn on or off elements by overwriting earlier rules. Because of this, you're going to have lots of "repeat" declarations, but they're not repeated in their location within the order. With complex pages, you're going to wind up twisting yourself in knots trying to keep everything logically ordered if you also want to minimize declarations.
Additionally, from my naive understanding of browser engines, the performance cost of multiple rules applying to an element is greater than the cost of multiple declarations within a rule. Why minimize them?
But my largest concern is the mental overhead of trying to simplify rules in code. Co-locating declarations affecting a logical unit is extremely helpful. The tool we have to accomplish this is called a selector. Minimizing declarations increases selector count, which kind of defeats their purpose. Pre-processors can't solve this for you either, due to CSS rules being ordered. If all you're building is a static page then, sure, I can see minimizing declarations being some kind of goal. But CSS gets used for a lot more than static pages.
As other commenters have noted, if the author's concern is overly-large CSS files, run-length encoding alleviates a lot of that, at least if the declarations are in the same file (a reason to not use http2 as a silver bullet and use concatenation instead, if that's a concern).
EDITS: Added a couple sentences.
A maintainable CSS is way, way more important. Writing complex CSS is very easy, but debugging can be a nightmare.
Can you give a counter-example where repeating CSS improves maintainability ?
Many component-based designs also prefer repeating styles for each component because of maintainability but I guess they wouldn't be counted in the article as they use generated root names.
My point is, not repeating styles should not be the target, but it may of course be the side-effect.
One example of this is when some styles are "accidentally" the same for two elements. If you condense them into one rule, then you lose the independent control.
"Hey look, 97% of the users always turn up bass and treble together and turn down the middrange; we can condense the three-band equalizer panel down to one knob!"
Very nice to work with.
Shadow DOM supports style isolation [1], although I don't think I've never seen anyone using it outside of toy projects.
There's also a newly proposed containment [2] CSS property, but it's only supported on Chrome.
For simpler websites where you skip using any build tool, I don't think it's a problem. For larger applications that support build tools, css-modules is a good alternative [3].
[0] https://developer.mozilla.org/en-US/docs/Web/CSS/@namespace
[1] https://webkit.org/blog/4096/introducing-shadow-dom-api/
[2] https://developers.google.com/web/updates/2016/06/css-contai...
Perhaps that "dead" style is only used for that error div that isn't visible unless some rare condition exists.
Solutions like CSS Modules and Styled Components are getting _really_ really close. CSS Modules lets you do this at a component level, and is theoretically possible to do it at an individual class level (providing you use a 'safe' syntax).
The only issue I have come across is when you are inserting elements with CSS classes using JavaScript. A workaround for this is importing the CSS in the JS module you are using it in via webpack or PurifyCSS also has an option to manually exclude certain selectors.
Example from the dark ages: naive (or lazy) CAD drafters would often draw overlapping lines, which then caused the pen plotter to draw that many strokes on the mylar, which would then have too much ink, botching the output. Enough of a problem that 3rd party tools popped up to dedupe plot files.
---
Opera was onto something with server side rendering for their mini browser. They should sell that as a service.
In fact, someone needs to take it even further:
Render to some page description language (maybe PDF), and then automagically rehydrate into minimal, inferred HTML+CSS+images. Kinda like how tabula and others scrape PDFs to reconstitute tabular information.
One benefit is throwing away all the box model layout cruft. True WYSIWYG.
Another, even bigger, benefit is sanitizing content, like removing web bug tracking images.
---
I'm currently test driving the Mercury Reader extension for Chrome. Ignoring all styling also sounds like a terrific idea. I may prefer this strategy. https://postlight.com/
view-source:https://meiert.com/setup/default.css
If this is worthwhile doing, a source tool to transform it would make more sense IMO.
Repetition is simpler than the complexity of managing huge projects that are constantly changing.
No. The lack of abstraction tools is the definition of a lower level language.
You know it's a lower level language when, as a developer, you feel the need for one higher. I submit Less and Sass as evidence.
Honestly, this alone making it to standard css would have me taking a week off knowing how much time I'd save in the future:
.c {.b .a}
... where a and b and c are all classes.
Libs like styletron consolidate duplicated style declarations.