How I Destroyed my Blog's Performance with CSS Background-Blend-Modes

7 Jan 2017
Just because a browser has a feature doesn't mean you should use it
Reddit comment: This website is so poorly written it spins up the fans of my gaming laptop

My previous article became mildly popular on Reddit yesterday. But I was intrigued by that comment. "My website is not poorly built!", I thought to myself, "Silly redditors." I only have google analytics and CSS that I've written by hand. It should be very very fast.

But I was wrong.

I tried scrolling down. In firefox, the performance of scrolling down was crazy bad:

firefox performance monitor capture

That's right, each paint was taking about 800ms when scrolling, not the 16.6ms that is required for smooth scrolling. What was happening? There was almost no javascript, no webgl, no canvas, no nothing! Just handwritten css and html. And it looks even funkier from the user point of view:

"Cinematic", "Console-Quality" scrolling

Remove 5 lines - Get 60fps???

Then I tried removing the background-blend-mode css properties. I had to change around which background was used so that the most important texture came through:

--- a/source/sass/_blog.scss
+++ b/source/sass/_blog.scss
@@ -38,9 +38,7 @@
 @include padded-centered('BlogContent');
 .BlogMore {
-  background: url(/static/images/cork-wallet.png),
-              radial-gradient($slate-sh, $slate-nt);
-  background-blend-mode: hue;
+  background: radial-gradient($slate-sh, $slate-nt);
 .BlogContent {
   position: relative;
@@ -69,8 +67,7 @@
   margin-top: -$overlay;
   margin-bottom: -4rem;

-  background: url(/static/images/cork-wallet.png), white;
-  background-blend-mode: hue;
+  background: url(/static/images/cork-wallet.png);

Now firefox is firefast:

firefox dev tools performance - but fast

What the hell? How does this small change take us from 1fps to 58fps?

Am I going crazy?

Was this a bug with my site - some dangerous cocktail of css that lead to bad performance? In 2013, you could end up with specific and odd combinations of box-shadow and border-radius with huge render times. Had I tripped on one of these?

Well, I tried to find the smallest reproducing case for the performance issue. It used different backgrounds and different patterns. Lo and behold, I found one with only 10 lines of CSS:

(Yes, I even removed the font-family:​ sans-serif line to get the count down 😄. Sorry to your eyes!)

What this probably means is that I am hitting a really bad code path. It isn't some bad combination of weird html, running videos and complex css. No, it is just that background-blend-modes are super slow in firefox.

But what about chrome?

Who knows! When I stress tested chrome, it also has visibly noticeable white, un-rendered squares while scrolling. But they have designed their profiler well to not show average fps (I think):

Chrome Devtools timeline
Incomparably good performance!

Still, as an uneducated (l)user, that FPS graph looks very bumpy. Even chrome doesn't stand up to the background-blending challenge.

Lesson Learnt

This taught me 1 thing - just because a browser has a features, doesn't mean you should use it! I suppose for the next while, background-blend-mode can join the waiting room of immature css features - like flexbox, border-radius or :​before/:​after once were. It's a loss for all of us - background blends can make it easy to create beautiful pages that combine textures and gradients in a stunning way.