What is the relation between z-index and css Position:?
Is z-index only works if position:absolute or relative or fixed defined?
Does it never works with position static?
When z-index creates problem in IE? How to use carefully?
z-index defines the stacking order of relative, absolute and fixed position elements. That means that it will only work if your element has one of those position types.
.some-element {
position: relative;
z-index: 1;
}
.another-element {
position: absolute;
z-index: 2;
}
In the above, .another-element will stack above .some-element since it has a higher z-index.
The issue with older versions of IE is that z-index is only respected in the same stacking context. What this means is that in the following setup, z-index won't necessarily work correctly if the 2 images overlap:
HTML
<div id="elem1">
<img src="foo.jpg"/>
</div>
<div id="elem2">
<img src="bar.jpg"/>
</div>
CSS
#elem1 {
position: relative;
}
#elem1 img {
position: relative;
z-index: 1;
}
#elem2 {
position: relative;
}
#elem2 img {
position: relative;
z-index: 2;
}
The reason being that both images are in their own stacking context since #elem1 and #elem2 are position: relative.
Note the Applies to: section of the specification:
'z-index'
Value: auto | <integer> | inherit
Initial: auto
Applies to: positioned elements
—
And you can easily use the index to find the definition of positioned
Related
https://codepen.io/diana-larussa/pen/OJgjLqj
the code looks basically like that:
contact-section
svg-container
footer
I think the image is pretty self-explanatory... I also tried to solve it by using :before but it just doesn't work... Please help.
You can remove the svg container from the document flow (so that it can't be pushed by the form) and position it at the top relative to a parent element.
First enclose both elements in a common parent:
<div class="main-wrapper">
<div class="main-container"></div>
<div class="svg-container"></svg>
</div>
Set the svg container to be absolutely positioned (absolutely relative to its parent, that's why main-wrapper has position:relative).
.main-wrapper {
position: relative;
overflow: hidden;
}
.main-container {
/* ... */
position: relative; /* necessary for z-index */
z-index: 1; /* keep the content above svg-container */
}
.svg-container {
position: absolute;
top: 0;
left: 0;
right: 0;
}
I'm trying to override / ignore the stacking context for an element so it can be positioned on the z-axis relative to the page root.
However, according to the article What No One Told You About Z-Index:
If an element is contained in a stacking context at the bottom of the stacking order, there is no way to get it to appear in front of another element in a different stacking context that is higher in the stacking order, even with a z-index of a billion!
New stacking contexts can be formed on an element in one of three ways:
When an element is the root element of a document (the element)
When an element has a position value other than static and a z-index value other than auto
When an element has an opacity value less than 1
With the following example:
.red, .green, .blue { position: absolute; }
.red { background: red; }
.green { background: green; }
.blue { background: blue; }
<div><span class="red">Red</span></div>
<div><span class="green">Green</span></div>
<div><span class="blue">Blue</span></div>
If the first div is given opacity:.99;, (which creates a new stacking context on the first node) then even if .red has z-index:1, it will still be placed behind the other elements because it is just rendered as the highest element within that stack.
Working Demo in jsFiddle
Which looks like this:
Q: Is there a way for an element to ignore the stack context of any of it's parent elements and ask to be positioned relative to the original stack context of the page?
Q: Is there a way for an element to ignore the stack context of any of it's parent elements and ask to be positioned relative to the original stack context of the page?
No, it's not possible to transfer a positioned element between stacking contexts without repositioning the element in the DOM. You cannot even move an element to the root stacking context by using position: fixed or position: absolute (as you have observed, .red is being positioned relative to its parent, div:first-child because it creates a new stacking context).
That being said, given your HTML and CSS it should be trivial to just reassign the classes to the div elements instead, as shown in other answers and here so all your divs and spans participate in the root stacking context:
<div class="red"><span>Red</span></div>
<div class="green"><span>Green</span></div>
<div class="blue"><span>Blue</span></div>
But your situation probably isn't as simple as it seems.
We can do it using 3D transformation and we will be able to bring any element to the front even if it's trapped inside a stacking context:
.red,
.green,
.blue {
position: absolute;
width: 100px;
color: white;
line-height: 100px;
text-align: center;
}
body,
div:first-child {
transform-style: preserve-3d; /* this is important for the trick to work */
}
.red {
top: 20px;
left: 20px;
background: red;
/*z-index: 1; we no more need this */
transform:translateZ(1px); /* this will do the trick */
}
.green {
top: 60px;
left: 60px;
background: green;
}
.blue {
top: 100px;
left: 100px;
background: blue;
}
<div><span class="red">Red</span></div>
<div><span class="green">Green</span></div>
<div><span class="blue">Blue</span></div>
More details and examples here: Why can't an element with a z-index value cover its child?
As it stated in the The stacking context: "Using z-index, the rendering order of certain elements is influenced by their z-index value. This occurs because these elements have special properties which cause them to form a stacking context.
To partly overcome stacking content problem you can use css properties to display unwanted elements:
opacity: 0.1;
or
display: none;
Why in IE8, is the background color of a pesudo element flowing behind children of the parent? The text flows in front, but the background-color does not. Z-index did not seem to help any.
I haven't been able to determine if this is a bug in IE8 or not. It seems like this would have been a pretty common use-case, but I couldn't find many blog posts or SO questions related to it.
http://jsfiddle.net/VAg2E/
<div id="parent">
<img src="http://placehold.it/200x200">
</div>
#parent{ padding: 20px; }
#parent:before{
content: 'Behind the image';
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
background-color: red;
}
Edit : A related Stack Overflow Question about Stacking Order
This is definitely a bug in IE8; since your :before pseudo-element is positioned, it should create a new stacking context and always be drawn on top of the img unless you give it a negative z-index (even then, the entire element should be drawn behind it, not just its background).
This issue also seems specific to stacking between :before and :after pseudo-elements and replaced elements like img. It looks like IE8 is treating replaced content differently in terms of stacking, but whatever it is doing, it's definitely not conforming to the spec.
As you're probably aware, this is fixed in IE9.
Have your exact same issue, the only thing you can do is force the stacking order via CSS and z-index. The only catch is that z-index is placed on child element starting from parent element, so you wont be able to do a proper logic order as #parent-element {z-index: 2} and #child-element {z-index: 1}, the z-index for the #child-element will just be set to level 1 as a separate stack order inside the #parent-element.
You can still set z-index for the #child-element with a -1 value, it will just get back the whole #parent-element stacking order.
So to recap:
#parent-element { z-index: 99;} /* or any arbitrary number fitting */
#child-element {z-index: -1;}
Also remember to give both elements a position: relative/absolute to enable the stacking order fo z-index
IE8 only supports pseudos if <!DOCTYPE> is declared. Source
#parent { padding: 20px; z-index: 2; }
#parent:before {
content: 'Behind the image';
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
background-color: red;
z-index: -1;
}
I am wondering whether the :before and :after pseudo-elements can inherit the height from parent using the inherit value, without the actual element doing so?
No. The only way that pseudo-elements can inherit values from the parent of their generating element is when the generating element itself is also inheriting from its parent.
This is because inheritance occurs from a parent to a child, one level at a time. For inheritance to work across several levels of descendants, every descendant must inherit.
As an example, consider the following HTML:
<div class="parent">
<div class="child">
</div>
</div>
With the following CSS:
.parent {
width: 100px;
height: 100px;
}
.parent > .child:before, .parent > .child:after {
content: '';
position: absolute;
width: inherit;
height: inherit;
}
This will not work because even though the pseudo-elements have values of inherit, the element generating them, that is, .parent > .child, does not inherit from .parent. Instead, they inherit the default value of auto for both properties.
In order for this to work you will need to have .parent > .child inherit as well:
.parent {
width: 100px;
height: 100px;
}
.parent > .child {
width: inherit;
height: inherit;
}
.parent > .child:before, .parent > .child:after {
content: '';
position: absolute;
width: inherit;
height: inherit;
}
I know this question is fairly old, but I stumbled on it today. According to http://www.w3.org/TR/CSS21/generate.html, the accepted answer isn't accurate:
The :before and :after pseudo-elements inherit any inheritable properties from the element in the document tree to which they are attached.
I just tried inheriting width and it worked.
If you want to use your ::before pseudo-element to implement a background the trick is to make sure that you positioned your element absolute and his parent relative. Make also sure you set the width of the parent.
Example
&__item {
position: relative;
width: 100%;
height: 100%;
&::before {
content: "";
background-color: red;
background-size: 100%;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
}
Concerning these answers, I was just bumping into the aspect of transformation. It may resemble on inheritance; I hope it helps somebody.
Having this:
<div class="box">
<div class="frame"></div>
</div>
and this transformation for frame:
transform: rotate(10deg);
Then the frame:before and frame:after are also transformed. Yet they do not have the properties of frame, such as width and height, which is like explained above. Full example see here:
http://jsfiddle.net/chafpgwt/1/
On this fiddle, there are three nested squares, each rotated by 10 deg, but the transform definition is only set for the frame, not for frame:after neither frame:before.
It is a pitfall to think transformations also are not "inherited", as everything else is neither. The transformation has influence in another context.
This question already has answers here:
How to get a child element to show behind (lower z-index) than its parent? [duplicate]
(7 answers)
Why can't an element with a z-index value cover its child?
(5 answers)
Closed 3 years ago.
I am trying to style a element with the :after pseudo element CSS selector
#element {
position: relative;
z-index: 1;
}
#element::after {
position:relative;
z-index: 0;
content: " ";
position: absolute;
width: 100px;
height: 100px;
}
It seems like the ::after element can not be lower then the element itself.
Is there a way to have the pseudo element lower then the element itself?
Pseudo-elements are treated as descendants of their associated element. To position a pseudo-element below its parent, you have to create a new stacking context to change the default stacking order.
Positioning the pseudo-element (absolute) and assigning a z-index value other than “auto” creates the new stacking context.
#element {
position: relative; /* optional */
width: 100px;
height: 100px;
background-color: blue;
}
#element::after {
content: "";
width: 150px;
height: 150px;
background-color: red;
/* create a new stacking context */
position: absolute;
z-index: -1; /* to be below the parent element */
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Position a pseudo-element below its parent</title>
</head>
<body>
<div id="element">
</div>
</body>
</html>
I know this is an old thread, but I feel the need to post the proper answer. The actual answer to this question is that you need to create a new stacking context on the parent of the element with the pseudo element (and you actually have to give it a z-index, not just a position).
Like this:
#parent {
position: relative;
z-index: 1;
}
#pseudo-parent {
position: absolute;
/* no z-index allowed */
}
#pseudo-parent:after {
position: absolute;
top:0;
z-index: -1;
}
#parent { position: relative; z-index: 1; }
#pseudo-parent { position: absolute; } /* no z-index required */
#pseudo-parent:after { position: absolute; z-index: -1; }
/* Example styling to illustrate */
#pseudo-parent { background: #d1d1d1; }
#pseudo-parent:after { margin-left: -3px; content: "M" }
<div id="parent">
<div id="pseudo-parent">
</div>
</div>
Try it out
el {
transform-style: preserve-3d;
}
el:after {
transform: translateZ(-1px);
}
There are two issues are at play here:
The CSS 2.1 specification states that "The :beforeand :after pseudo-elements elements interact with other boxes, such as run-in boxes, as if they were real elements inserted just inside their associated element." Given the way z-indexes are implemented in most browsers, it's pretty difficult (read, I don't know of a way) to move content lower than the z-index of their parent element in the DOM that works in all browsers.
Number 1 above does not necessarily mean it's impossible, but the second impediment to it is actually worse: Ultimately it's a matter of browser support. Firefox didn't support positioning of generated content at all until FF3.6. Who knows about browsers like IE. So even if you can find a hack to make it work in one browser, it's very likely it will only work in that browser.
The only thing I can think of that's going to work across browsers is to use javascript to insert the element rather than CSS. I know that's not a great solution, but the :before and :after pseudo-selectors just really don't look like they're gonna cut it here.
Speaking with regard to the spec (http://www.w3.org/TR/CSS2/zindex.html), since a.someSelector is positioned it creates a new stacking context that its children can't break out of. Leave a.someSelector unpositioned and then child a.someSelector:after may be positioned in the same context as a.someSelector.
I know this question is ancient and has an accepted answer, but I found a better solution to the problem. I am posting it here so I don't create a duplicate question, and the solution is still available to others.
Switch the order of the elements. Use the :before pseudo-element for the content that should be underneath, and adjust margins to compensate. The margin cleanup can be messy, but the desired z-index will be preserved.
I've tested this with IE8 and FF3.6 successfully.
Set the z-index of the :before or :after pseudo element to -1 and give it a position that honors the z-index property (absolute, relative, or fixed). This works because the pseudo element's z-index is relative to its parent element, rather than <html>, which is the default for other elements. Which makes sense because they are child elements of <html>.
The problem I was having (that lead me to this question and the accepted answer above) was that I was trying to use a :after pseudo element to get fancy with a background to an element with z-index of 15, and even when set with a z-index of 14, it was still being rendered on top of its parent. This is because, in that stacking context, it's parent has a z-index of 0.
Hopefully that helps clarify a little what's going on.
I fixed it very simple:
.parent {
position: relative;
z-index: 1;
}
.child {
position: absolute;
z-index: -1;
}
What this does is stack the parent at z-index: 1, which gives the child room to 'end up' at z-index: 0 since other dom elements 'exist' on z-index: 0. If we don't give the parent an z-index of 1 the child will end up below the other dom elements and thus will not be visible.
This also works for pseudo elements like :after
I don't know if someone will have the same issue with this. The selected answer is partially correct.
What you need to have is:
parent{
z-index: 1;
}
child{
position:relative;
backgr