The other day, when I was exploring the progress bar in Hotwire, I noticed that the
<div> implementing the progress bar was injected into the DOM (Document Object Model) after the
<head> tag and before the
I assume that the Hotwire framework is making this choice because it swaps out the entire
<body> tag when a new page is loaded. As such, any elements contained within the
<body> tag will be implicitly removed. Which means, if the progress bar is outside the Body tag, the progress bar can be persisted even as the Body tag is being replaced.
That's a cool use-case; but, when I saw this, my immediate thoughts went to stacking context. Stacking context is the key to understanding
z-index layering. If you've ever seen a developer using a CSS property like:
z-index: 999999999 ;
... it's because they don't understand how
z-index works; and, they're just throwing numbers at the wall to see what sticks. It's a futile attempt to break free from a "stacking context" that is locking-down layering within a branch of the DOM.
The main rendered branch of the DOM is the
<body> element. Which means, if we can create a "stacking context" on the Body tag itself, anything outside of the Body, will be in a different stacking context and can freely stack above or below the Body layer.
To demonstrate this, I've created a page with two
<div> elements using
z-index: 2. They are both defined in between the Head and Body tags; however, one of them is dynamically injecting itself after the
As you can see, the "box" element is our control layer and has a high
z-index. Each of my other elements use a
2. Normally, this would place both elements below the box from a stacking perspective. However, when we run this page, we get the following output:
<head>. And, because it is rendered outside of the
<body> tag, it is stacked above the "box" despite having a much lower
I don't know that much about accessibility. But, I have to assume that content rendered outside of the
<body> has all kinds of accessibility issues. As such, it's probably a bad idea to use this technique to render consumable "content". However, for something like a progress bar that is nothing more than a visual indicator (ala the Hotwire framework), this seems like a rather clever approach.
Want to use code from this post? Check out the license.
I also wanted to try playing around with this technique to create a persisted IFrame-based video play in Hotwire:
Essentially, I inject the Hotwire Turbo Frame before the
<body>tag. This way, I can mount an IFrame inside of it, and Turbo Drive won't have to move it around, and won't control the state as I move from page to page.
I didn't know that elements can be rendered outside of the body tag, that's interesting. Thank you for your walkthrough of this topic, as well as the examples you provide.
My pleasure! Glad you found it interesting. I think this will be a good one to have in the back pocket.
Post A Comment — ❤️ I'd Love To Hear From You! ❤️
Post a Comment →