CSS Stacking Order

CSS Stacking Order (Without z-index)

When elements on a webpage overlap, the browser needs to decide which element appears on top. If the z-index property is not specified on any element, the browser follows a strict set of rules to determine the stacking context.

Elements are stacked in the following order (from bottom to top):

  1. The Root Element: The background and borders of the root element (usually <html>).
  2. Non-Positioned Elements: Descendant elements that are not positioned (i.e., they have position: static), rendered in the exact order they appear in the HTML code.
  3. Positioned Elements: Descendant elements that are positioned (i.e., relative, absolute, fixed, or sticky), also rendered in the order they appear in the HTML code.

Important Note: When the CSS order property alters the rendering of items within flex containers, it similarly affects the order for their stacking context.

Explore modern layout architectures in our CSS Flexbox guide.

Example: Stacking Without z-index

In the example below, DIV #1 through DIV #4 are positioned elements. DIV #5 is static (non-positioned).

Because positioned elements are always painted after (and therefore on top of) non-positioned elements, DIV #5 is drawn completely below the other four elements, even though it is the very last element written in the HTML markup!

Default Stacking Context Example:

<!DOCTYPE html>
<html>
<head>
    <style>
        .stacking-container {
            position: relative; /* Acts as a container for absolute items */
            height: 400px;
            border: 2px solid navy;
            background-color: #f4f4f9;
        }
        .stacking-container strong {
            font-family: sans-serif;
        }
        .stacking-container div {
            padding: 10px;
            border: 2px dashed;
            text-align: center;
        }
        .static {
            position: static;
            height: 80px;
            background-color: #ffffcc;
            border-color: #999966;
        }
        .absolute {
            position: absolute;
            width: 150px;
            height: 350px;
            background-color: #ffdddd;
            border-color: #990000;
            opacity: 0.8; /* Makes overlapping visible */
        }
        .relative {
            position: relative;
            height: 80px;
            background-color: #ccffcc;
            border-color: #669966;
            opacity: 0.8;
        }
        #abs1 { top: 10px; left: 10px; }
        #rel1 { top: 30px; margin: 0px 50px; }
        #rel2 { top: 15px; left: 20px; margin: 0px 50px; }
        #abs2 { top: 10px; right: 10px; }
        #sta1 { margin: 0px 50px; }
    </style>
</head>
<body>
    <div class="stacking-container">
        <div id="abs1" class="absolute">
            <strong>DIV #1</strong><br />position: absolute;
        </div>
        <div id="rel1" class="relative">
            <strong>DIV #2</strong><br />position: relative;
        </div>
        <div id="rel2" class="relative">
            <strong>DIV #3</strong><br />position: relative;
        </div>
        <div id="abs2" class="absolute">
            <strong>DIV #4</strong><br />position: absolute;
        </div>
        <!-- Even though DIV #5 is last in the HTML, it renders at the bottom! -->
        <div id="sta1" class="static">
            <strong>DIV #5</strong><br />position: static;
        </div>
    </div>
</body>
</html>

Summary

Understanding the default stacking context is crucial before you start applying manual z-index values. If two elements overlap and neither has a z-index:


Exercise

?

If an unpositioned (static) element is written AFTER an absolutely positioned element in the HTML code, which one will appear on top visually?