Tuesday, May 26, 2026Tech HubAboutContactAdvertiseNewsletter
Back to Home
Unstacking CSS Stacking Contexts

Unstacking CSS Stacking Contexts

In CSS, we can create “stacking contexts” where elements are visually placed one on top of the next in a three-dimensional sense that creates the perception of depth. Stacking contexts are incredibly useful, but they’re also widely misunderstood and often mistakenly created, leading to a slew of...

B
Blizine Admin
·1 min read·0 views

Unstacking CSS Stacking Contexts — Smashing Magazine

Skip to main content Start reading the article Jump to list of all articles Jump to all topics16 min readCSS, Coding, Techniques, ToolsShare on Twitter, LinkedInAbout The AuthorGabriel is a front-end developer and technical writer. He specializes in HTML, CSS, JavaScript, React, Vue, TailwindCSS, and BootStrap, with a track record of … More about Gabriel ↬Email NewsletterYour (smashing) email Weekly tips on front-end & UX.Trusted by 182,000+ folks. See User Testing Live Celebrating 10 million developers Deep Dive On Accessibility Testing with Manuel Matuzović Design Patterns For AI Interfaces, 30 lessons + UX training The Modern UX Practitioner with Paul Boag Custom Web Forms for Angular, React, & Vue. Your backend. How To Measure UX and Design Impact with Vitaly FriedmanIn CSS, we can create “stacking contexts” where elements are visually placed one on top of the next in a three-dimensional sense that creates the perception of depth. Stacking contexts are incredibly useful, but they’re also widely misunderstood and often mistakenly created, leading to a slew of layout issues that can be tricky to solve.Have you ever set z-index: 99999 on an element in your CSS, and it doesn’t come out on top of other elements? A value that large should easily place that element visually on top of anything else, assuming all the different elements are set at either a lower value or not set at all.A webpage is usually represented in a two-dimensional space; however, by applying specific CSS properties, an imaginary z-axis plane is introduced to convey depth. This plane is perpendicular to the screen, and from it, the user perceives the order of elements, one on top of the other. The idea behind the imaginary z-axis, the user’s perception of stacked elements, is that the CSS properties that create it combine to form what we call a stacking context.We’re going to talk about how elements are “stacked” on a webpage, what controls the stacking order, and practical approaches to “unstack” elements when needed.About Stacking ContextsImagine your webpage as a desk. As you add HTML elements, you’re laying pieces of paper, one after the other, on the desk. The last piece of paper placed is equivalent to the most recently added HTML element, and it sits on top of all the other papers placed before it. This is the normal document flow, even for nested elements. The desk itself represents the root stacking context, formed by the element, which contains all other folders.Now, specific CSS properties come into play.Properties like position (with z-index), opacity, transform, and contain) act like a folder. This folder takes an element and all of its children, extracts them from the main stack, and groups them into a separate sub-stack, creating what we call a stacking context. For positioned elements, this happens when we declare a z-index value other than auto. For properties like opacity, transform, and filter, the stacking context is created automatically when specific values are applied.When the browser decides what goes on top, it stacks the folders first, not the individual papers inside them. This is “The Golden Rule” of stacking contexts that many developers miss. (Large preview)Try to understand this: Once a piece of paper (i.e., a child element) is inside a folder (i.e., the parent’s stacking context), it can never exit that folder or be placed between papers in a different folder. Its z-index is now only relevant inside its own folder.In the illustration below, Paper B is now within the stacking context of Folder B, and can only be ordered with other papers in the folder.(Large preview)Imagine, if you will, that you have two folders on your desk:Folder A Folder B .folder-a { z-index: 1; } .folder-b { z-index: 2; } Let’s update the markup a bit. Inside Folder A is a special page, z-index: 9999. Inside Folder B is a plain page, z-index: 5. Special Page

Plain Page

.special-page { z-index: 9999; } .plain-page { z-index: 5; } Which page is on top?It’s the .plain-page in Folder B. The browser ignores the child papers and stacks the two folders first. It sees Folder B (z-index: 2) and places it on top of Folder A (z-index: 1) because we know that two is greater than one. Meanwhile, the .special-page set to z-index: 9999 page is at the bottom of the stack even though its z-index is set to the highest possible value.Stacking contexts can also be nested (folders inside folders), creating a “family tree.” The same principle applies: a child can never escape its parents’ folder.Now that you get how stacking contexts behave like folders that group and reorder layers, it’s worth asking: why do certain properties — like transform and opacity — create new stacking contexts?Here’s the thing: these properties don’t create stacking contexts because of how they look; they do it because of how the browser works under the hood. When you apply transform, opacity, filter, or perspective, you’re telling the browser, “Hey, this element might move, rotate, or fade, so be ready!”(Large preview)When you use these properties, the browser creates a new stacking context to manage rendering more efficiently. This allows the browser to handle animations, transforms, and visual effects independently, reducing the need to recalculate how these elements interact with the rest of the page. Think of it as the browser saying, “I’ll handle this folder separately so I don’t have to reshuffle the entire desk every time something inside it changes.”But there’s a side effect. Once the browser lifts an element into its own layer, it must “flatten” everything within it, creating a new stacking context. It’s like taking a folder off the desk to handle it separately; everything inside that folder gets grouped, and the browser now treats it as a single unit when deciding what sits on top of what.So even though the transform and opacity properties might not appear to affect the way that elements stack visually, they do, and it’s for performance optimisation. Several other CSS properties can also create stacking contexts for similar reasons. MDN provides a complete list if you want to dig deeper. There are quite a few, which only illustrates how easy it is to inadvertently create a stacking context without knowing it.The “Unstacking” ProblemStacking issues can arise for many reasons, but some are more common than others. Modal components are a classic pattern because they require toggling the component to “open” on a top layer above all other elements, then removing it from the top layer when it is “closed.”I’m pretty confident that all of us have run into a situation where we open a modal and, for whatever reason, it doesn’t appear. It’s not that it didn’t open properly, but that it is out of view in a lower layer of the stacking context.This leaves you to wonder “how come?” since you set:.overlay { position: fixed; /* creates the stacking context */ z-index: 1; /* puts the element on a layer above everything else */ inset: 0; width: 100%; height: 100vh; overflow: hidden; background-color: #00000080; } This looks correct, but if the parent element containing the modal trigger is a child element within another parent element that’s also set to z-index: 1, that technically places the modal in a sublayer obscured by the main folder. Let’s look at that specific scenario and a couple of other common stacking-context pitfalls. I think you’ll see not only how easy it is to inadvertently create stacking contexts, but also how to mismanage them. Also, how you return to a managed state depends on the situation.Scenario 1: The Trapped ModalSee the Pen [Scenario 1: The Trapped Modal (Problem) [forked]](https://codepen.io/smashingmag/pen/pvbddjd) by Shoyombo Gabriel Ayomide.See the Pen Scenario 1: The Trapped Modal (Problem) [forked] by Shoyombo Gabriel Ayomide.If you click the “Open Modal” button in the header, you’ll notice that the overlay and modal appear behind the main content. This is because the modal is a child of the header container, which has a lower stacking context order (z-index: 1) than the main container (z-index of 2). Despite the modal overlay and the modal having z-index values of 9998 and 9999, respectively, the main container with a z-index: 2 still sits right above them.Scenario 2: The Submerged DropdownSee the Pen [Scenario 2: The Submerged Dropdown (Problem) [forked]](https://codepen.io/smashingmag/pen/zxBPPvm) by Shoyombo Gabriel Ayomide.See the Pen Scenario 2: The Submerged Dropdown (Problem) [forked] by Shoyombo Gabriel Ayomide.Here, we have a similar issue with the first scenario. When you hover over the “services” link, the dropdown shows, but behind the main container. I intentionally set the main container’s margin-top to 20px to make the dropdown visible enough for you to see it appear, but keep it just behind the main container. This is another popular issue front-end developers encounter, stemming from context stacking. While it is similar to the first scenario, there’s another approach to resolving it, which will be explored soon.Scenario 3: The Clipped TooltipNow, this is an interesting one. It’s not about which element has the higher z-index. It’s about overflow: hidden doing what it’s designed to do: preventing content from visually escaping its container, even when that content has z-index: 1000.See the Pen [Scenario 3: The Clipped Tooltip (Problem) [forked]](https://codepen.io/smashingmag/pen/GgqOOoo) by Shoyombo Gabriel Ayomide.See the Pen Scenario 3: The Clipped Tooltip (Problem) [forked] by Shoyombo Gabriel Ayomide.Who would have thought overflow: hidden could stop a z-index: 1000? Well, it did stop it, as you can see in the Codepen above.I think developers trust z-index so much that they expect it to pull them out of any obs

📰Originally published at smashingmagazine.com

Comments