CSS: Absolutely positioned pseudo element loses z-index? - css

Why would an absolutely positioned pseudo element be losing its z-index when using transition?
The fiddle:
http://jsfiddle.net/RyanWalters/jNgLL/
What's happening?
When you click on the li, it slides to the left without changing any z-index values. However, the :after content is popping up on top of the li.
What should happen?
I was hoping it would stay hidden behind the li.
The CSS (simplified a little bit, see fiddle for full example):
li {
position: relative;
transition: transform 0.2s;
}
li.active {
transform: translateX(-100px);
}
li:after {
position: absolute;
top: 0;
right: 0;
z-index: -1;
content: "Yada yada";
}
Why is the :after content not staying behind the li?

I found this on w3.org, which I think explains it: http://www.w3.org/TR/css3-transforms/#effects
Any value other than ‘none’ for the transform results in the creation of both a stacking context and a containing block. The object acts as a containing block for fixed positioned descendants.
As I understand it, your li:after pseudo-element is inside the stacking context of the li.active element, and therefore cannot appear behind it.

#BernzSed's answer is correct. Here's a solution, though:
Wrap the content inside the <li> using a <div> (or any other element) with position: relative, then the z-index: -1 on the psuedo element will force it to be behind the child element.
Here's the essential code:
HTML:
<ul>
<li><div>This is the first item</div></li>
</ul>
CSS:
li,
li div {
position: relative;
}
li:after {
position: absolute;
z-index: -1;
}
Example: http://jsfiddle.net/shshaw/jNgLL/3/
Also interesting to note: If you use a :before psuedo element, you don't need the z-index: -1 because it's already falling under the position: relative child element in the stacking order.

Related

Possible z-index issue

It seems that my dropdown menu its z-index is doing something strange:
https://uma.be/evenement/uma-day-2020-best-media-campaigns/
When you hover the menu-item "Commissions", the dropdown menu goes underneath the image.
I've already checked the z-index of the image itself and the z-index of .mega-sub-menu. Both seems okay to me. The class .mega-sub-menu has an z-index of 999 and the image hasn't got one.
I've added position: relative; z-index: 1; to the image, but that didn't fix the issue.
Is it possible that the Lazy loader does something with the image so that it goes over the sub navigation?
This is because your image and the menu are not in the same stacking context. To ensure that they are in the same stacking context, you will need to find out the parent element of both elements that are siblings to each other.
In this case, that will be:
#wrapper-navbar as the parent element for the dropdown menu
#tribe-events-pg-template as the parent element for the contents of the page (which includes the image)
All you need to do is:
Set the z-index of #wrapper-navbar to 2
Relatively position #tribe-events-pg-template and set its z-index to 1
Updated CSS:
#wrapper-navbar {
position: relative;
z-index: 2;
}
#tribe-events-pg-template {
position: relative;
z-index: 1;
}
After fix is applied:
Problem is your #navbar's z-index property. Increase it or remove it and that should fix your problem
>
#wrapper-navbar {
position: relative;
/* z-index: 1; */
}
Edit the following (added the z-index and position):
#tribe-events-pg-template, .tribe-events-pg-template {
z-index: 0;
position: relative;
margin: 0 auto;
max-width: 1200px;}

How is 'relative' positioning placing the tooltip at the correct position?

Here's an example of a CSS tooltip. The author positions the toolip relatively.
.tooltip{
display: inline;
position: relative;
}
However, the tutorial says,
Relative. This type of positioning is probably the most confusing and
misused. What it really means is "relative to itself". If you set
position: relative; on an element but no other positioning attributes
(top, left, bottom or right), it will no effect on it's positioning at
all, it will be exactly as it would be if you left it as position:
static; But if you DO give it some other positioning attribute, say,
top: 10px;, it will shift it's position 10 pixels DOWN from where it
would NORMALLY be. I'm sure you can imagine, the ability to shift an
element around based on it's regular position is pretty useful. I find
myself using this to line up form elements many times that have a
tendency to not want to line up how I want them to.
There are two
other things that happen when you set position: relative; on an
element that you should be aware of. One is that it introduces the
ability to use z-index on that element, which doesn't really work with
statically positioned elements. Even if you don't set a z-index value,
this element will now appear on top of any other statically positioned
element. You can't fight it by setting a higher z-index value on a
statically positioned element. The other thing that happens is it
limits the scope of absolutely positioned child elements. Any element
that is a child of the relatively positioned element can be absolutely
positioned within that block. This brings up some powerful
opportunities which I talk about here.
What I understand is that, without modifiers like top, left etc. relative is equivalent to static and goes with the flow of the page. Then how's the tooltip being displayed at the correct position, i.e. above the hyperlink? Shouldn't it appear at the end of the page instead?
The CSS you provided for tooltip is not complete. I think you saw it in w3schools. But note that there are two elements for it: a parent element with .tooltip class and a child element (actual tooltip text) inside it with .tooltiptext class.
the parent element has position: relative without any top, left ... positions which acts as you said as a static element in its original (normal) place. But the child tooltiptext inside it has a position: absolute which is why it is seperated from normal text flow and put over them.
Here is a sample:
.tooltip {
/* this is just to add meaning for position:absolute of .tooltiptext */
position: relative;
color: navy;
}
.tooltip .tooltiptext {
/* Position the tooltip */
position: absolute;
z-index: 1;
top: 100%;
left: 10%;
/* style the tooltip */
min-width: 50px;
background-color: #ff9;
color: black;
font-size: 10pt;
border-radius: 3px;
padding: 3px 10px 6px;
white-space: nowrap;
visibility: hidden;
}
.tooltip:hover .tooltiptext {
visibility: visible;
}
<span>Sample: </span>
<span class="tooltip">Hover over me
<span class="tooltiptext">Tooltip text</span>
</span>

CSS: Anchor In List Item Doesn't Stay 100% Height

So, here's the skinny...
I have a page that has a list as display:table-cell. As the width of the browser resizes, the contents (anchors) of the lists may wrap to 2 lines. The problem is the anchors that don't wrap to 2 lines aren't staying 100% height.
CSS...
.home .pushes ul {display:table;}
.home .pushes ul li {display:table-cell; vertical-align:middle; width:25%; background-color:#e5a015; color:#ffffff;}
.home .pushes ul li a {display:block; padding:4em 0; padding:4rem 0;}
So, the height of <li> should be determined by the height and padding of <a>. But, since it's <display:table-cell>, the height is determined by the tallest <a>.
Ok, so just set a {height:100%;}. But, then, the anchor doesn't keep the padding. So, just set li {height:160px;} or something. But, then the anchor isn't vertically-centered. So, just set li {line-height:160px;}. But, then the anchor is huge when it wraps to 2 lines.
So, what is a guy to do?
I could do li {display:inline-block;}. But I want all the boxes to be the same height.
JJ
Edit...
HTML included for posterity...
<ul>
<li>bleh</li>
<li>bleh</li>
</ul>
JJ
Edit 2...
The anchor background color is what isn't growing the full height of its parent.
I didn't realize that I could upload an image. Thanks for the tip.
JJ
The best way of fixing this problem would be to use position: relative and position: absolute.
Example:
li {
position: relative;
}
li a {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
However, the above does not work because your li is using "display: table-cell;" and position: relative is not defined for table cells (See: Using Position Relative/Absolute within a TD?).
Therefore, your only choice is to use Javascript to get this done. There are many solutions but here is one:
Use the jQuery resize method (http://api.jquery.com/resize/) to keep track of when the window resizes. When the window resizes modify the anchor tag's padding so that it continues to cover the entire space.

CSS not selector with after content

Is it possible to use the :not() selector/pseudo thing with :after?
So for example if I have the following:
li:hover > ul
{
display: block;
}
li:after
{
content: " ";
width: 200px;
height: 200px;
background: #cccccc;
position: absolute;
top: -100px;
left: -100px;
}
What happens is that if a person HOVERS over the content that is created by the after it will also make the child menu display block. In other words hovering other the LI or the AFTER content is acknowledged as hovering the LI. How would I stop this, so it only does the display block when hovering the ACTUAL LI and NOT the content created using AFTER.
I thought about: li:hover:not(:after) > ul { display: none; } but hasn't worked...
Also tried: li:after:hover > ul but also didn't work.
Any ideas for this? It might seem trivial but it's causes some issues in my design so need to stop it doing it asap.
As you observe, :hover styles on an element will be triggered when hovering over its contents, including descendants and pseudo-elements. However, you can't prevent :hover styles on an element from applying to its :after pseudo-element, nor can you use :not() to select :after pseudo-elements (this is explicitly disallowed by the spec).
This is by design, so the only way around it is to not use :after, but use JavaScript to generate some other element that you can append to the li and cancel the :hover effect on.
Actualiy it is possible with the use of the attribute "pointer-events" and assign it to none in the pseudo-element :after or :before .
So it would be -> pointer-events: none; in the pseudo-element.

Is it possible to set the stacking order of pseudo-elements below their parent element? [duplicate]

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

Resources