Z-Index issue with child elements [duplicate] - css

This question already has answers here:
How to make child element higher z-index than parent? [duplicate]
(6 answers)
Why can't an element with a z-index value cover its child?
(5 answers)
Closed 2 years ago.
I have sibling divs in a page, let's call them parents. And these parents have one child divs each. You can think of these child divs as custom tooltips. By default, child divs are hidden. When I hover one of the parents, it's child div becomes visible.
Because of painting order, when I hover first parent, it's child becomes visible below second parent which painted last on the page. All parents have the same z-index which is 1, as well as all child divs have the same z-index which is 2.
All child divs needs to be drawn on top. How can I override it to work like this?
You can find my problem as reproducible below:
.parent{
position: relative; height: 200px; width: 200px; z-index: 1; display: inline-block;
}
.parent:hover .child{
display: block;
}
.child{
position: absolute; height: 50px; width: 50px; z-index: 2; display: none;
}
<div class="parent" style="background-color: hotpink;">Parent 1<div class="child" style="background-color: yellow; margin-left: 180px; margin-top: 50px;">Child 1.1</div></div>
<div class="parent" style="background-color: green;">Parent 2<div class="child" style="background-color: greenyellow; margin-left: -30px;">Child 2.1</div></div>

The main reason why this behaviour is happening is because:
The child element in Parent1 is in lower stacking order than the Parent Element 2.
Even though it may appear in the first look that first child in first Parent has z-index of 2, but this is with respect to the ParentElement1 not ParentElement2.
Let me give a demo example:
.content {
position: relative;
z-index: 1;
background:orange;
height:400px;
width:400px;
}
.child {
position: absolute;
z-index: 100;
background:green;
height:200px;
width:200px;
bottom:0;
left:0;
}
.side-tab {
position: absolute;
z-index: 5;
background:teal;
height:300px;
width:300px;
top:10px;
}
<section class="content">
<div class="child"></div>
</section>
<div class="side-tab"></div>
Looking at the markup, we can see that the content and side tab elements are siblings. That is, they exist at the same level in the markup (this is different from z-index level). And the child div is a child element of the content element.
Because the child is inside the content element, its z-index of 100 only has an effect inside its parent, the content element.
But the z-index value of child element doesn't mean anything outside the parent, because the parent content element has its z-index set to 1.
So its children, including the child, can’t break out of that z-index level.
SOLUTION:
There are two solutions to this problem.
Remove positioning from the content, so it won’t limit the child's
z-index.
So in your example if your remove position:relative from the Parent this will solve the issue.
.parent{
position: static; height: 200px; width: 200px; display: inline-block; // Removed position:relative from here
}
Since the parent element is now unpositioned, it will no longer limit the child's z-index value.
Move the child outside of the parent, and into the main
stacking context of the page.
(But this would mess things up for you because then you will need to change your markup)
Hope this covers the positioning issue's that we face with z-index.

remove .parent's z-index: 1
.parent{
position: relative; height: 200px; width: 200px; display: inline-block;
}
.parent:hover .child{
display: block;
}
.child{
position: absolute; height: 50px; width: 50px; z-index: 2; display: none;
}
<div class="parent" style="background-color: hotpink;">Parent 1<div class="child" style="background-color: yellow; margin-left: 180px; margin-top: 50px;">Child 1.1</div></div>
<div class="parent" style="background-color: green;">Parent 2<div class="child" style="background-color: greenyellow; margin-left: -30px;">Child 2.1</div></div>

Related

expand parent to same height as child (position: absolute) without javascript [duplicate]

This question already has answers here:
Make absolute positioned div expand parent div height
(15 answers)
Closed last month.
How to expand the parent to have the same height as the child (the content) when the child has position: absolute ?
The height of the child is not static
Solution without javascript
.parent {
position: relative;
background: red;
}
.child {
position: absolute;
right: 10px;
width: 100px;
background: blue;
}
<div class="parent">
<div class="child">
test<br>test<br>test<br>test
</div>
</div>
<div>
some text below parent
</div>
(JsFiddle)
.parent {
position: relative;
background: red;
width: max-content;
}
on the parent

How can you horizontally center an absolutely positioned element relative to the viewport when it has a positioned parent?

Eg. how can you get the blue child in this example to be horizontally centered relative to the viewport (ie. in the center of the page), provided that the parent must stay the same.
Other qualifications:
I don't want it to be fixed.
Suppose that distance between the parent and the left viewport is unknown.
.parent {
margin-left: 100px;
margin-top: 100px;
background: red;
position: relative;
width: 50px;
height: 50px;
}
.child {
background: blue;
position: absolute;
bottom: 100%;
}
<div class="parent">
<div class="child">
child
</div>
</div>
I am trying to make this question a SSCCE. In reality, the use case is that I have a dropup (like dropdown, expect it appears above rather than below the triggering button). I want the dropup menu to be centered.
The menu needs to be absolutely positioned, otherwise it'd get in the way of the flow of other DOM elements. And I need to position the container so that I could set bottom: 100%; on the menu so that it appears right above the triggering button.
In in this case you can use position:fixed BUT to avoid it being fixed apply a null transform to the body:
body {
transform:translate(0,0);
min-height:150vh;
}
.parent {
margin-left: 100px;
margin-top: 100px;
background: red;
position: relative;
width: 50px;
height: 50px;
}
.child {
background: blue;
position: fixed;
left:50%;
transform:translate(-50%,-100%);
}
<div class="parent">
<div class="child">
child
</div>
</div>

Can a flex box container be positioned absolutely

Can one flex container(A) be positioned absolutely in front or behind of another flex container(B) and still maintain flex properties of its children?
My problem: When I assign a flex-container(B) to position:absolute, the children content inside lose the automatic flex properties. When I switch back to position:relative, flex works again. When container(B) is relative, I can't overlay on top of the other flex container(A) like I need.
Research: Found everything on absolute positioning of children in parent flex containers (W3C and CSS tricks, etc), but nothing specific enough to flex containers being moved absolutely over another flex container (which makes me wonder if it's even possible!). If so, I'll be rollin' in joy.
Ultimate Goal: Want to overlay one adjacent flex container over another with different z-indexes.
Thanks in advance.
As we don't know how your original code looks like, here is a general layout with one flex container being absolute positioned on top of another.
To make the position: absolute element align as its sibling, I wrapped them both and gave the second width: 100%
.wrap {
position: relative;
}
.a, .b {
display: flex;
height: 120px;
left: 0;
top: 0;
}
.a {
background: red;
}
.b {
position: absolute;
top: 50px;
height: 50px;
width: 100%;
background: blue;
}
.wrap > div > div {
flex: 1;
padding: 20px 50px;
margin: 5px;
background: green;
}
.wrap div div:first-child {
flex-basis: 50%;
}
<div class="wrap">
<div class="a">
<div></div>
<div></div>
<div></div>
</div>
<div class="b">
<div></div>
<div></div>
<div></div>
</div>
</div>

why is absolute element width limited by inline-block parent

I have the following setup:
div {
position: relative;
display: inline-block;
}
div div {
position: absolute;
top: 100%;
background: green;
}
a {
width: 25px;
float: left;
}
<div>
some
<div>
1
2
</div>
</div>
My question is why the div that contains a elements collapses on parent div width? I'd expect a elements to stay in one line but they wrapped. Is it expected behavior? How can I work around it?
I'd expect a elements to stay in one line but they wrapped. Is it expected behavior?
Yes. they're floated left, but the parent is absolute positioned so constrained from the document floats. Has no width set so the inner elements align to the available space (0) even being left-floated.
a elements are inline elements by default.
First of all you'll have to remove float from your anchors, set them rather to be inline-block. Still they're vertically positioned, to fix that set white-space: nowrap; to the parent.
div{
display: inline-block;
position: relative;
}
div div {
position: absolute;
top: 100%;
background: green;
white-space: nowrap; /* needed! for inner inline elements */
}
a {
width: 25px;
display:inline-block; /* needed just for the 25px width! (otherw. remove) */
}
<div>
some
<div>
1
2
</div>
</div>

Clear fix problems with overflow and pie-clearfix

I am trying to float some elements and apply clearfix so that the parent element can expand to the height and width of the children.
So, I simply set up the layout as per this fiddle: http://jsfiddle.net/fMjEx/
I then wanted to float the elements inside .bar. This is usually quite straight forward:
Float the elements.
Clear fix the parent using pie-clearfix or overflow: auto.
However, I ran into these problems:
If I use pie-clearfix, the element .picture which is next to .bar is also included in the clearing: http://jsfiddle.net/6C7WD/
If I use overflow: auto or overflow: hidden, the width of the .bar no longer spans the width of the document: http://jsfiddle.net/fv2gA/
Initially, one solution I had was to make .picture position: absolute. However, the problem with this approach is that the element is taken out of the flow.
In the layout, the height of .bar is variable depending on the content inside. I would like to give .bar and .picture a margin-bottom so that anything that comes after them is pushed downwards by that amount depending on whether .bar or .picture has a greater height.
This rules out using position: absolute on .picture as a solution.
Are there any solutions that satisfy the following?
Clear only floats within .bar.
Does not remove any elements from the flow.
This is the solution I ended up with:
Added a wrapper to the markup:
<div class="container">
<div class="group"> <-------------------------- This is the wrapper
<div class="picture"></div>
<div class="bar">
<div class="info"> some text goes here</div>
<div class="buttons">some other content goes here</div>
</div>
</div>
</div>
And the CSS:
.picture{
width: 100px;
height: 100px;
float: left;
background: green;
margin-left: 100px;
margin-top: 10px;
z-index: 2;
position: relative;
}
.bar{
background: blue;
margin-top: -80px;
overflow: auto;
width: 100%;
float: left;
z-index: 1;
position: relative;
}
.group{
margin-bottom: 10px;
}
.group:after {
clear: both;
content: "";
display: table;
}
.info, .button{
float: left;
margin-left: 200px;
}
.container{
overflow: auto;
}
Fiddle of the above: http://jsfiddle.net/c6Lng/

Resources