CSS Z-index changing unexpectedly

I have simplified this just to show what is going on. I have a box (originally a button), with a 3D effect. When it is hovered over, the box rises by 2 pixels and the 3D effect drops by 3 pixels (hiding it). However, for some reason the 3D effect behind the box moves in front. Can anyone explain why this is please? https://codepen.io/iBlackwolf/pen/ZEZWdQx
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Hmmmmmmm</title>
<style>
body {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}

#box {
position: relative;
width: 150px;
height: 150px;
border: none;
border-radius: 30px;
background-color: #f00;
font-size: 20px;
color: #fff;
cursor: pointer;
}

#box::before {
position: absolute;
content: '';
width: 146px;
height: 150px;
left: 2px;
top: -5px;
border: none;
border-radius: 30px;
background-color: #44f;
z-index: -1;
}

#box:hover {
transform: translateY(-2px);
}

#box:hover::before {
transform: translateY(3px);
}
</style>
</head>

<body>
<div id="box"></div>
</body>

</html>
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Hmmmmmmm</title>
<style>
body {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}

#box {
position: relative;
width: 150px;
height: 150px;
border: none;
border-radius: 30px;
background-color: #f00;
font-size: 20px;
color: #fff;
cursor: pointer;
}

#box::before {
position: absolute;
content: '';
width: 146px;
height: 150px;
left: 2px;
top: -5px;
border: none;
border-radius: 30px;
background-color: #44f;
z-index: -1;
}

#box:hover {
transform: translateY(-2px);
}

#box:hover::before {
transform: translateY(3px);
}
</style>
</head>

<body>
<div id="box"></div>
</body>

</html>
21 Replies
Abdul Rehaman Shaikh
Abdul Rehaman Shaikh•3mo ago
Did you try giving a z-index to #box
Blackwolf
Blackwolf•3mo ago
yes, messed about with alsorts of z-indexes and it just gets weirder
Tok124 (CSS Nerd)
Tok124 (CSS Nerd)•3mo ago
First of all. body already takes full width, so width:100vw; makes no sense. and vh should only be used as a fallback. better using svh and vh as fallback. https://www.youtube.com/watch?v=veEqYQlfNx8 Also, you want to do this? Is this the effect you looking for? https://codepen.io/tok124/pen/MWReaLz
Kevin Powell
YouTube
The problems with viewport units
Conquering Responsive Layouts (free course): https://courses.kevinpowell.co/conquering-responsive-layouts Join the Discord: https://kevinpowell.co/discord Viewport units often feel like this cheat code that makes things so much easier when you first discover them, but they actually are problematic for a number of reasons, from creating horizon...
Tim
CodePen
MWReaLz
...
Blackwolf
Blackwolf•3mo ago
that's better than mine, i do want the 3D effect to drop a little - the idea is to make it look like a button is pressed in and i don't want to move the foreground too much. the viewport is generic as it's just for developing components. i shall analyse your code later. thank you so much
Tok124 (CSS Nerd)
Tok124 (CSS Nerd)•3mo ago
Refresh the pen. I made it look a little better
Blackwolf
Blackwolf•3mo ago
excellent job, thank you again 🙂 i shall analyse the differences when i get some free time 🙂 ... i need to understand what i actually did wrong I see you made the box in a completely different way. I would like to understand why the z-index flips on my original when all I am doing is moving items up and down
Kevin Powell
Kevin Powell•3mo ago
The transform on hover is creating a new stacking context. I've made a little video where I explain it in more detail 🙂
Kevin Powell
Kevin Powell•3mo ago
Kevin Powell
Kevin Powell•3mo ago
If you don't mind, I might chop this up a little and turn it into a YT video
Abdul Rehaman Shaikh
Abdul Rehaman Shaikh•3mo ago
I just gave the #box a z-index of 1 and it came over red box
Blackwolf
Blackwolf•3mo ago
yea, it does crazy things
Abdul Rehaman Shaikh
Abdul Rehaman Shaikh•3mo ago
You did want blue over red, right?
Blackwolf
Blackwolf•3mo ago
no
Abdul Rehaman Shaikh
Abdul Rehaman Shaikh•3mo ago
Ahh… my bad! I assumed you wanted blue over red 😅
Blackwolf
Blackwolf•3mo ago
imagine the red as a button and the blue as it's 3D - when pressed, the red gets a little higher and the blue lower, so it looks like it's being pressed
Abdul Rehaman Shaikh
Abdul Rehaman Shaikh•3mo ago
Ahh… transform is your friend then
Blackwolf
Blackwolf•3mo ago
it's transform that appears to be breaking the z-index lol
Abdul Rehaman Shaikh
Abdul Rehaman Shaikh•3mo ago
I’ll duplicate and let you know 😅
Blackwolf
Blackwolf•3mo ago
ok, thanks
Abdul Rehaman Shaikh
Abdul Rehaman Shaikh•3mo ago
The main issue is that the box and it's pseudo class are not in the same stacking order. I mean you are moving the box and its before both using transform property. If you try wrapping the box in a container div and then on hover of that div you move the before, it will work as you expect it to work. https://codepen.io/i4mabdul/pen/BaEzRRg
Abdul Rehaman Shaikh
Abdul Rehaman Shaikh•3mo ago
transform have their own stacking order. Check out my codepen and see if that's the effect you wanted