What causes a new stacking context to be formed when using position: relative without z-index?

After reading this informative piece:

When two elements share the same stack level, their layering is determined by their order in the source code. Elements stacked successively are placed on top of those that came before them.

And referencing this article:

A stacking context comes into existence anywhere within a document due to certain conditions being met, such as: ... 2. An element with either a "relative" or "absolute" position values coupled with a non-"auto" z-index value.

Now let's observe the following code snippet:

.c1 {
  position: relative;
  top: 50px;
}


.c2 {
   background: green;
   width: 200px;
   height: 200px;
 }
<div class="c1">
  Why am I visible?
</div> 

<div class="c2">&nbsp;</div>

Based on the aforementioned statements, it's expected that div.c1 does not establish a new stacking context because it lacks a specific z-index value. Therefore, both div.c1 and div.c2 belong to the <html> stacking context and should be rendered accordingly. So why does div.c2 appear below div.c1?

Answer №1

There's a common misconception that the CSS properties top, left, bottom, and right dictate the stacking order of elements, but in reality, it's not the case. By removing the top property and adding a negative value to margin-bottom, you can still achieve the desired layout.

.c1 {
  position: relative;
  margin-bottom: -50px;
}


.c2 {
   background: green;
   width: 200px;
   height: 200px;
 }
<div class="c1">
  Why am I still visible?
</div>

<div class="c2">&nbsp;</div>

Understanding the concepts of stack level and stacking contexts sheds light on why the relatively positioned element appears on top. The stack level is influenced by the z-index property, where elements with z-index: auto default to stack level 0. As per the spec, elements with lower stack levels are painted first within each stacking context. Check out this section for more details.

  1. the background and borders of the element forming the stacking context.
  2. the child stacking contexts with negative stack levels (most negative first).
  3. the in-flow, non-inline-level, non-positioned descendants. the non-positioned floats.
  4. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
  5. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
  6. the child stacking contexts with positive stack levels (least positive first).

To illustrate this further, let's compare a relatively positioned element that creates a stacking context versus one that doesn't.

const blueBox = document.querySelector('#blue-box');
const button = document.querySelector('button');
const opacity1 = document.querySelector('#opacity-1');
const opacityNot1 = document.querySelector('#opacity-not-1');

let opacity = 1;

button.addEventListener('click', () => {
  if(opacity == 1){
    opacity = .9;
    opacity1.hidden = true;
    opacityNot1.hidden = false;
  }
  else {
    opacity = 1;
    opacity1.hidden = false;
    opacityNot1.hidden = true;
  }
  blueBox.style.opacity = opacity;
})
#blue-box {
  width: 100px;
  height: 100px;
  position: relative;
  background: blue;
}

#yellow-box {
  width: 50px;
  height: 50px;
  position: relative;
  top: 75px;
  z-index: 1;
  background: yellow;
}

#red-box {
  width: 100px;
  height: 100px;
  position: relative;
  background: red;
}
<div id="blue-box" style="opacity: 1">
  <div id="yellow-box"></div>
</div>

<div id="red-box"></div>

<button>Toggle opacity for blue box</button>
<p id="opacity-1">Blue box has <code>opacity: 1;</code> (so does NOT create a new stacking context)</p>
<p id="opacity-not-1" hidden>Blue box has <code>opacity: .9;</code> (so it creates a new stacking context)</p>

In this scenario, all three boxes are relatively positioned, but the yellow box stands out as it creates a stacking context with a higher stack level. Toggling the opacity of the blue box changes its behavior accordingly.

What happens when the blue box does not create a stacking context? The painting order follows the specified sequence, placing the yellow box above the blue and red boxes due to its elevated stack level.

Conversely, enabling the blue box to create a new stacking context shifts the dynamics. Now, the blue box and its associated stacking context are painted together, leading to the red box being displayed on top of the yellow box.


In summary, elements with position: relative do not inherently establish a new stacking context but rely on their positioning and stack level to determine display order relative to other elements.

Answer №2

When using the property position: relative, elements are first rendered in their normal flow before any offsets are applied. The offset is then calculated relative to the element's own position. In this specific scenario without the 10px offset provided to "c1", the correct order of rendering would be to display "c1" first and then place "c2" below it (not overlapping). Since both "c1" and "c2" are block elements, they should not overlap by default. However, due to the offset given to "c1", it was displaced 10px downwards causing it to overlap with "c2".

Answer №3

When you apply relative positioning to an element, it allows you to use the z-index property on that element. This is a feature that doesn't function well with statically positioned elements. Consequently, even if you do not specify a z-index value, this particular element will now be displayed on top of any other statically positioned element.

Moreover, if you declare position: relative; for an element without any other positioning attributes such as top, left, bottom, or right, it will have no impact on its positioning whatsoever. The element will remain in the same position as it would if its position was set to static. However, if you do add another positioning attribute like in your case, setting top: 50px;, the element will move 50 pixels downwards from its original position.

This explains why .c1 appears "stacked" above .c2.

Answer №4

In this scenario, c1 establishes the stacking context because it has position:relative applied to it. If you then apply position:absolute to c2, both divs will be at the same level and layered based on their source order.

.c1 {
  position:relative;
  background:blue;
  top: 50px;
}


.c2 {
  position:absolute;
   background: green;
   width: 100px;
   height: 100px;
 }
<div class="c1">
  Am I visible?
</div> 

<div class="c2">&nbsp;</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Centering content within a <th> tag

Hey there, I'm currently facing an issue with aligning a div inside another one. To illustrate the problem, I've set up a small fiddle which you can check out here: https://jsfiddle.net/jpq7xzoz/ The challenge arises when using the jQuery table ...

Is it possible to create a single code that can be used for various buttons that perform the same function?

Whenever I click the right button, the left button appears and when I reach the last page, the right button disappears. However, this behavior is affecting both sections. Is there a way to write separate code for each section? I managed to make it work by ...

The left column is stationary vertically, but can be scrolled horizontally

On a webpage, there are three columns: left, middle, and right. Only the left column is set to position:fixed, while the others are normal. When vertically scrolling, the left column should remain fixed while the other two scroll. However, when the brows ...

Angular material input featuring an additional component

Trying to integrate an additional text element next to an input using angular-material. The goal is to replicate the functionality of bootstrap's .input-group-addon: The closest approach achieved so far can be seen in this example: <md-content la ...

Set the div element to be horizontally aligned

Is there a way to make this display horizontally instead of vertically, from left to right rather than top to bottom? I attempted using display:flex but only the extra-text class is affected and not the outer div. https://i.stack.imgur.com/2DNoC.png .m ...

Tips for binding data to numerous dynamic controls

Implementing reactive forms in my Angular project allowed me to create a simple form for adding employee work hours and breaks. The challenge I encountered was the inability to bind data from break controls. In the .ts file export class AddAppointmentForm ...

What is the best way to use PHP to call an ACF variable and substitute a nested HTML element?

Utilizing the repeater field in Wordpress' advanced custom fields, I have made the content on my site dynamic. View an image of the static markup here The following is how I structured the content using plain HTML: <div class="container" ...

utilize javascript to style iframe from an external domain without access to its DOM structure

I have two websites, example.com and example1.com. I'm trying to display the content of example1.com within an iframe on example.com. For instance: Add this code to example.com: <iframe src='http://example1.com'> Then add the follow ...

What is the best way to select an element that is currently visible but hidden underneath another element?

I have developed a circular graphic using primarily HTML and CSS, with some JavaScript and JQuery functionalities incorporated for text curving and planned interactions in the future. However, I've encountered an issue where clicking on the upper rig ...

How can images be resized according to screen resolution without relying on javascript?

Looking to use a large banner image on my website with dimensions of 976X450. How can I make sure that the image stretches to fit higher resolution monitors without using multiple images for different resolutions? ...

CSS might not always work properly on all web browsers, but it functions perfectly on Eclipse

When developing JSF pages with stylesheets, everything seems to be working fine in the Eclipse preview function. However, when I test the pages on IE8, the styles do not seem to have any effect. I am utilizing composite views to define a general layout fo ...

How to target the following element with CSS that has a specified class name

Would it be possible to achieve this using CSS alone, or would I need to resort to jQuery? This is how my code currently looks: <tr>...</tr> <tr>...</tr> <tr>...</tr> <tr class="some-class">...</tr> // My g ...

Ensuring that the image perfectly fills the entire screen on an iPhone X using React Native

Looking for a solution to make my image fit the entire screen on the iPhone X simulator. I've tried adjusting the imageContainer width to "100%" and the container that encompasses everything, but haven't had any luck. Would appreciate any suggest ...

Centering loaders within elements of an unordered list

I am working on a navbar that uses Bootstrap 3 and AngularJS. Within this navbar, I have an unordered list with li elements. Below is a snippet of my navbar: https://i.stack.imgur.com/o75Lp.png This is the code for my navbar: <div class="navbar-head ...

Dynamic Sizing of Elements + Adaptive Text Overlay

There were 2 obstacles I encountered when trying to create an image-based drop-down menu : No matter how much effort I put in, I couldn't figure out how to make a flexed element inside a container maintain the same height as the adjacent element. [ ...

Creating a horizontal layout for list items that are responsive using CSS

My website has a "Featured" section with 3 equally sized elements displayed horizontally. I want to make the webpage responsive by using percentage widths, but when I resize the window to less than the list width, the items stack on top of each other. Che ...

Utilizing static HTML, CSS, and JavaScript for secure backend administrative control

Seeking a solution for my static html, CSS, and JS website which includes some Jquery elements. I want to implement a user-friendly backend system that allows non-developer admins to log in, easily edit sections or change images with their own preferences. ...

When you initiate a prevent default, both the Angular and Bootstrap UI tabs will become active simultaneously

I am facing a CSS issue while utilizing Angular UI-Tab. The problem arises when I have two tabs and need to stop tab switching based on a specific condition. To achieve this, I implemented prevent default. However, the CSS displays both tabs as active bec ...

The mouseenter event in jQuery is failing to trigger

I'm encountering an issue with the mouseenter event on a div section of my webpage. I am attempting to alter the background color of this div when the mouse enters, but it seems to be disregarded. This is the basic HTML code: <div id="services" c ...

How can I remove a specific JSON object from localStorage based on the data associated with the element that is currently being clicked on?

Unique Scenario A user interacts with an element, triggering a change in the background image and storing data related to that element in localStorage: this process functions correctly. Next, the toggle variable is set to 0, the background image change ...