---
layout: post
title: "blocking=render: Why would you do that?!"
date: 2024-08-14 12:45:11
categories: Web Development
main: "https://csswizardry.com/wp-content/uploads/2024/08/blocking-status.png"
meta: "Why on earth would you make something render-blocking?!"
faq:
- question: "Why would be need a blocking=render attribute?"
answer: "Generally, we don’t! The primary use case thus far is to grant scripts the ability to be render- but not parser-blocking, which is not currently possible. This would be particularly helpful for A/B testing libraries who currently rely on anti-flicker snippets to achieve the results they want."
---
WebKit have recently announced their [intent to
implement](https://github.com/WebKit/WebKit/pull/32022) the `blocking=render`
attribute for `` This will block parsing (and therefore also
rendering) of subsequent content. The browser may not parse or construct any
DOM until `app.js` is fully fetched and parsed, at which point it now has two
tasks ahead of it: build the DOM and render it. **Scripts are parser
blocking.**
All other file types are, by default, non-blocking.
The pedant in me wants to point out that even inline `
```
This snippet works by applying the class `async-hide` to the `` element
(`document.documentElement`). This aggressively sets `opacity: 0;` so that the
page is rendered, only invisibly. The class is then removed either when the A/B
tool’s work is done, or a `4000`ms timeout is reached—whichever is first.
One immediate failing with this is that an invisible page is still interactive,
and users could still click on or interact with elements inadvertently. The page
_is_ rendered, but invisibly. `blocking=render` ensures that the page is not
rendered at all, and therefore can’t be interacted with.
Another problem is that we’re going through more paint cycles than we need to:
paint the page invisibly, modify it, paint it again visibly… It would be nicer
to hold off painting anything at all until we have all of the relevant
information about what to paint. `blocking=render` gives us this ability.
A further issue is the big-reveal phenomenon: with an anti-flicker snippet, the
page is totally invisible until it’s totally visible. Behind the `opacity: 0;`,
there may well have been a progressive render of the page—which is a familiar
and good user experience—but a user didn’t benefit from it. Anti-flicker
snippets eschew this behaviour and take an all-or-nothing approach: nothing,
nothing, nothing, _everything_.
A regular, progressive render (top) versus an anti-flicker
big-reveal (bottom). Which do you think is the better experience?
`blocking=render` leaves the browser to its usual rendering process, so we can
still get a progressive render of the page, only now we do it in a way more
akin to loading a CSS file.
Finally, and this is counter to my own preferences and beliefs as a performance
engineer, we still risk leaking the experiment to the user when using an
anti-flicker snippet. Knowingly hiding a page for up to four seconds feels like
insanity to me, but at least we do have a timeout. The problem with anti-flicker
snippets is that if that four-second timeout is reached, we’ll still display the
page even if experiments haven’t completed—the `4000`ms is a magic number that
we use to hopefully win a race condition.
By using `blocking=render`, that timeout now becomes [governed by the browser’s
own heuristics](https://github.com/whatwg/html/issues/7131#footnote2), which is
almost definitely going to be longer than four seconds. While that does terrify
me, it does guarantee we don’t paint anything _too_ soon. No more race
conditions, but a potentially longer render-blocked period.
As I said at the top of the article, most of us won’t need `blocking=render`,
and those of us who do will know that we do.
## tl;dr
One handy takeaway is that, at present, `blocking=render` would cause any of the
following:
* ``
* ``
* ``
* ``
…to behave like this:
* ``
- - -
[^1]: [x.com/kurtextrem/status/1823698340388782591](https://x.com/kurtextrem/status/1823698340388782591)