How to set z-index?


I want to create a hover effect for my button as displayed in the below link:

The idea is to have a transition effect while hovering over the button so as to get a white overlay over it. Here’s my code:

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

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;

.btn-container {
  background: orange;
  width: 100%;
  height: 500px;

.btn {
  display: inline-block;
  margin: 20px;

.btn button {
  background: transparent;
  padding: 20px;
  border: none;
  color: #fff;
  font-family: Arial, sans-serif;
  font-size: 1.2em;
  cursor: pointer;

.btn1 {
  border: 1px solid #fff;
  position: relative;
  transition: color 0.3s ease-in-out;

.btn1 button:hover {
  color: orange;

.btn1 button:after {
  content: '';
  height: 100%;
  width: 0%;
  position: absolute;
  transition: width 0.3s ease-in-out;
  top: 0px;
  left: 0px;
  background-color: #fff;
  z-index: -1;

.btn1 button:hover:after {
  width: 100%;
  <div class="btn-container">
    <div class="btn btn1">
      <button>Hover Me</button>

The only problem is when z-index is set to ‘-1’ the transition effect disappears. I’m confused as to what’s wrong here.

It looks like it’s working. On hover a white background transitions from left to right and the text become green. If I remove z-index: -1 then the background covers the text.

Is this not the effect your looking for?

1 Like

Perhaps you are only looking at the first link (green button) and that works absolutely fine. But that is only for reference. What I really need is the second button to work the same. I hope you won’t mind having a look over the second link.

Oops. Sorry about that. Yes, when I load in the CSS for the 2nd example I can only get it to work when I add a z-index of 1 to .btn1 and .btn1 button:before has the z-index of -1 setting it farthest back.

Using either pseudo clas of :before or :after works the same.

1 Like

Glad you looked.

The Z-index in the first button needs to be set in one obvious place whereas in the second one it needs to be specified for its parent element as well. Could you explain what’s really going on and why does the second button behave differently?

Thanks for the help.

I’m not entirely sure.

The interesting thing is if I move your orange BG color to the body. Remove orange BG color from your .btn-container DIV, then I can remove the extra z-index: 1 from .btn1. It works like the 1st example works.

The differences I see is that they put the background color on body. You put the BG color on your button container. Also you have one extra DIV wrapping another DIV which wraps the button. They just have one DIV which wraps around their button.

Somehow your extra DIV is requiring an extra z-index.

Sorry wish I could explain why it works but I’m not sure.

here it is with both buttons. Slightly differnt HTML but only one z-index on the pseudo-class :after

1 Like

Okay, I know why example 1 only used one z-index. It’s because an element with z-index: -1 can never go behind the body tag. here’s a test:

Your example, used 2 DIVs and the BG color was set on your outer DIV. The z-index: -1 was placed on the pseudo-element, so when I placed a z-index of 1 on the inner DIV, that placed it above the other DIV.

In other words, 2 DIV can be flexible and go in front of or behind each other based on the z-index.

You can’t do that with the body. The Body DIV will always be the lowest element. Z-index: -1 can’t even hide behind it.

1 Like

Now I see. I was actually getting desperate and didn’t see what was really happening there with my two DIVs. But now it’s all clear. The pseudo element was getting placed behind the .btn-container and thus it wasn’t showing up.

Thanks a lot. It was quite helpful.