Z-index not working with position:fixed pseudo-elements - css

I've researched a lot on the topic and generally most problems of this matter are solved by specifying of changing the position attribute. However, the situation is different when dealing with pseudo-elements. The following CSS is the reduced test case.
#div {
background: #f5f;
height: 80vw;
width: 80vw;
max-height: 50px;
max-width: 50px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#div:before {
content: '';
background: #000;
height: 100vw;
width: 100vw;
max-height: 100px;
max-width: 100px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: -1;
}
HTML
<div id="div">hi!</div>
Fiddle

Pseudo elements belongs to the element itself. So the z-index will work in all pseudo "childrens", but not in the parent because is not in the same stack.
It's like when you want to change the z-index to put a div over another div but first is the parent of the second:
div {position:relative;}
.parent {z-index:10; background:red; padding: 5px;}
.children {z-index:5; background:blue;}
<div class="parent">
I need this more z-index than his children
<div class="children">
I need this less z-index than his parent
</div>
</div>
It doesn't work obviously. That's the same case.
To avoid this, you need to change your HTML and convert the pseudo element in a normal element with the propper stack.
EDIT
In your case, you can solve if you change the fixed positioning to the relative positioning:
http://jsfiddle.net/Kq2PY/166/
But this is a particular case because the parent is fixed positioning, and it works going out of the normal flow (fixed elements are attached to the document, not the parent element). So avoid to make this kind of things when you can make with another ways.

Related

Single page web without absolute position

is there any way to make single page website without position absolute? Because when I want to variable height of containers, absolute position is little bit awkward. I mean when I insert more content to one container, the other above it should move down. I've tried position static and relative, but it didn't work for me.
Now my css looks like:
<style>
#header {position: absolute; top: 0; left: 0; width: 100%; height: 20%;}
#main {position: absolute; top: 20%; left: 0; width: 100%; height: 80%;}
#about {position: absolute; top: 100%; left: 0; width: 100%; height: 100%;}
#contact {position: absolute; top: 200%; left: 0; width: 100%; height: 50%;}
</style>
<body>
<div id="header">
content....
</div>
<div id="main">
content...
</div>
<div id="about">
long content which is covered with next div, because its "top" atribute settings
</div>
<div id="contact">
div which covers previous one's end
</div>
But when some container needs to be longer, problem is here..
Thanks for any help!
That depends on the style of your website. Of course you can set up anchors and have a one-page scrolling website, but I don't think that answers your question.
My suggestion is to try using absolute positioned elements as containers, and have your actual template inside them.
It would help if you provided some actual code or a specific issue you're having, as it's currently too vague.
I'll provide an answer to what I think you might be asking, though it isn't clear. I hope this isn't too basic.
Ditch the position property altogether.
Just have a div (which is by default 100% width) as your header at the top of your html. The content should be in another div below that.
Divs by default have 100% width, and their height is dependent on the height of their content. They will grow to accommodate taller content. These behaviors are because they have the property display:block .
You've used % which, if I remember correctly, is relative to the parent element. vh (viewport height) is relative to the height of the screen (100vh is the full height of the screen).
I added the background-color just so it's easier to see.
<style>
#header {
background-color: #777;
height: 20vh;
}
#main {
background-color: #999;
height: 80vh;
}
#about {
background-color: #777;
height: 100vh;
}
#contact {
background-color: #999;
height: 50vh;
}
</style>

Controlling Intersection of CSS 3D Transformed Elements

Have been experimenting with CSS 3D transforms and am confused why I'm not getting the expected results in browsers other than Safari.
Basically I have 2 sibling elements that are on top of one another (on the same z-index). If I put a transform: rotateX(xdeg) on one and leave the other untouched I would expect to see one half of the transformed element hidden behind the untouched element and the other side to be sticking out.
HTML:
<div class="container">
<div class="outer"></div>
<div class="inner"></div>
</div>
CSS:
.container{
position: relative;
margin: 100px;
-webkit-perspective: 30em;
perspective: 30em;
}
.outer{
-webkit-transform: rotateX(45deg);
transform: rotateX(45deg);
position: absolute;
top: 0;
left:0;
width: 100px;
height: 100px;
box-sizing: border-box;
-moz-box-sizing: border-box;
border:5px black solid;
}
.inner{
position: absolute;
top: 5px;
left: 5px;
background: orange;
width: 90px;
height: 90px;
transform: rotate
}
http://jsfiddle.net/jaredkhan/4VRTb/3/
The fiddle uses the same code.
The bottom of the transformed element is not displayed in front of the element that is untouched despite theoretically being closer in 3D space. This does however, work as I would expect in Safari. Am I missing something? I've tried explicitly putting them both on the same z-index and even nesting the inner one, nothing seems to be working. It's likely I'm just being dumb but please help.
Thanks
Children are rendered one by one onto the plane of the parent element. You need to set transform-style: preserve-3d on the parent to prevent this (fiddle):
.container{
...
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
More info on MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/transform-style
(I'm not sure whether this even existed back in 2014 when you asked the question, but it works now in 2019.)

Z-index on a element with fixed position

I have a left panel with fixed position(it's always on the left side, nomatter how much you scroll) and also few elements in that left panel. On a certain event a mask appears(it goes over everything because position:fixed; z-index: 102).
My goal is when X event fires and the mask come up, to show up the holder element over the mask.
Here is a fiddle showing my problem: JSFIDDLE
Here is my HTML:
<div class="leftpanel">
<div class="just-random-elem" style="height: 30px;">just an element to move the holder abit down</div>
<div class="holder">asdasdas</div>
</div>
<div class="mask"></div>
<div style="height: 9999px;">Just to make sure both mask and leftpanel are with fixed positions.</div>
 and here's the CSS:
.mask {
opacity: 0.85;
position: fixed;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
z-index: 101;
background-color: #000;
}
.leftpanel {
width: 250px;
height: 100%;
position: fixed;
top: 0px;
left: 0px;
background-color: red;
padding: 15px;
}
.holder {
width: 230px;
height: 90px;
background-color: #fff;
z-index: 99999; <<<<<<<<<< This is NOT working!
}
Your .holder element is no positioned, so z-index simply has no effect on it. You need to add a position value different from the default static – relative will do.
http://jsfiddle.net/DJA5F/4 works that way in every browser I tested – except Chrome. Can’t spontaneously say if Chrome is handling stacking contexts correct here and the others are not – or if it’s the other way around.
Works in Chrome as well if you put #mask into .leftpanel: http://jsfiddle.net/DJA5F/5 – might not be the nicest workaround, but since it’s postioned fixed, it does not actually matter, since the orientation for fixed is the viewport.

percentages and CSS margins

I have create a jsFiddle to demonstrate my problem:
http://jsfiddle.net/MXt8d/1/
.outer {
display: inline-block;
vertical-align: top;
overflow: visible;
position: relative;
width: 100%;
height: 100%;
background: red;
}
.inner {
overflow: hidden;
height: 50%;
width: 100%;
margin-top: 25%;
margin-bottom: 25%;
background: blue;
opacity: 0.7;
color: white;
}
<div class="outer">
<div class="inner"></div>
</div>
The thing is that when i need to horizontally center a div inside another.
I specify the height of the inner div in % (eg. 50%) and then the margin-top and margin-bottom to the remaining (eg. (100 - 50) / 2 = 25 %).
But as you see in the jsFiddle it's not working as intended.
Calculating the margins from the Parent works, but it's not possible for me, because I dont have access to the div's parent, as the elements-style object is bound to the object via knockout.js and it's not so simple as shown in the jsFiddle.
Hope anyone could help me :-)
bj99
Update:
Just found out why this is actually happening, so I'll post here for peaple with similar problems:
From http://www.w3.org/TR/CSS2/box.html#propdef-margin-top :
'margin-top', 'margin-bottom'
Percentages: refer to width of containing block
And not as I tought to the height :-/
To #inner element:
1) Add position:absolute
2) Remove margin-top and margin-bottom properties
3) Add top:25%
That's it!
It is a solution to your problem.I hope I helped you
.inner {
overflow: hidden;
height: 50%;
width: 100%;
top:0;
bottom:0;
left:0;
right:0;
position: absolute;
margin: auto;
background: blue;
opacity: 0.7;
color: white;
}
There are various solutions to your problem:
1) add position:absolute and top:25% on the inner element - Example
2) use display:table on the outer and display:table-cell on the inner element, this also allows vertical centering. - Example
Each of the solutions has some caveats, I personally try to avoid absolute positionings wherever I can, but this is also up to personal preferences.

child div not expanding to parent div

So I have three div's
One parent and two child.
The parent is as follows:
#parent {
overflow:auto;
margin: 0 auto;
margin-top:37px;
min-height: 100%;
width:875px;
}
the two child divs are as follows
#child1 {
overflow:auto;
min-height:150px;
border-bottom:1px solid #bbb;
background-color:#eee;
opacity:0.4;
}
#child2 {
height:100%;
background-color:white;
}
The parent div extends 100% as I can see the borders of it till the end of the page but the child2 is not extending down to the end of the page like the parent div.
height doesn't behave the way you seem to be anticipating. When you specify height: 100% that percentage is calculated by looking up the DOM for the first parent of said element with a height specified that has absolute or relative positioning.
You can cheat when it comes to the body tag, so if you had something like this:
<body>
<div style="height: 100%">
</div>
</body>
Some browsers/versions will behave the way you expect by taking up the total height of the page. But it won't work when you go any deeper than that.
Here is the approach I use to strech a div to the bottom of the page, it involves absolute positioning (nice thing about this one is that it is pretty cross-browser compliant and doesn't require javascript to pull it off):
<div id="parent">
<div id="childNorm"></div>
<div id="childStrech"></div>
</div>
#parent
{
position: absolute;
width: 1000px;
bottom: 0;
top: 0;
margin: auto;
background-color: black;
}
#childNorm
{
position: absolute;
width: 1000px;
top: 0;
height: 50px;
background-color: blue;
color: white;
}
#childStrech
{
position: absolute;
width: 1000px;
top: 50px;
bottom: 0;
background-color: red;
color: white;
}
Here is a Jsfiddle for demo: http://jsfiddle.net/t7ZpX/
The trick:
When you specify absolute positioning and then put in bottom: 0; that causes the element to stretch to the bottom of the page; You just have to worry about positioning the elements as a trade off.
Yes, this is one of the annoying things in css. min-height is not considered a "height" for purposes of calculating height. See http://jsfiddle.net/3raLu/3/. You need to have height: 100% on the parent div to make the child full height. Or, if you can have it be absolutely positioned, then this works: http://jsfiddle.net/3raLu/6/.

Resources