1

I'm trying to place the :before,:after box-shadow behind the button. But the transition is starting in front of the a tag. For my works CMS, I'll need all the properties to be on the a tag.

<a href="#" class="btn">Join Today</a>


.btn{
  position: relative;
  z-index: 1;
  display: inline-block;
  text-align: center;
  background-color: #8ec656;
  border-radius: 30px;
  font-family: 'Roboto Condensed', sans-serif;
  font-size: 20px;
  color: #fff;
  border: 3px #d2d2d2 solid;
  padding: 15px 40px;
  line-height: 1;
  transition: box-shadow .4s;
}
.btn:hover{
  background: #6b9640;
  box-shadow: inset 0px -22px 13px 0px #84b652, inset 0px 2px 5px 0px #84b652;
}
.btn:before,
.btn:after{
  content: "";
  position: absolute;
  z-index: -1;
  bottom: 9px;
  left: 10px;
  width: 88%;
  top: 73%;
  transition: box-shadow .4s;
}
.btn:hover:before,
.btn:hover:after{
  box-shadow: 0 15px 10px #777;
}

https://jsfiddle.net/3aj5muyu/

3 Answers3

0

That's because .btn establishes a stacking context, so its background will always be at the back of its contents. The back-to-front order is

  1. the background and borders of the element forming the stacking context.
  2. the child stacking contexts with negative stack levels (most negative first).
  3. the in-flow, non-inline-level, non-positioned descendants.
  4. the non-positioned floats.
  5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
  6. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
  7. the child stacking contexts with positive stack levels (least positive first).

To fix it, .btn shouldn't establish a stacking context. Move the following properties to a wrapper:

position: relative;
z-index: 1;

.btn-wrapper {
  position: relative;
  z-index: 1;
  display: inline-block;
}
.btn{
  display: inline-block;
  text-align: center;
  background-color: #8ec656;
  border-radius: 30px;
  font-family: 'Roboto Condensed', sans-serif;
  font-size: 20px;
  color: #fff;
  border: 3px #d2d2d2 solid;
  padding: 15px 40px;
  line-height: 1;
  transition: box-shadow .4s;
  text-decoration: none;
}
.btn:hover{
  background: #6b9640;
  box-shadow: inset 0px -22px 13px 0px #84b652, inset 0px 2px 5px 0px #84b652;
}
.btn:before,
.btn:after{
  content: "";
  position: absolute;
  z-index: -1;
  bottom: 9px;
  left: 10px;
  width: 88%;
  top: 73%;
  transition: box-shadow .4s;
}
.btn:hover:before,
.btn:hover:after{
  box-shadow: 0 15px 10px #777;
}
<div class="btn-wrapper">
  <a href="#" class="btn">Join Today</a>
</div>
Oriol
  • 274,082
  • 63
  • 437
  • 513
0

Take a look at this working example:

.btn {
  position: relative;
  /* z-index: 1; */
  display: inline-block;
  
  background-color: #8ec656;
  border-radius: 30px;
  border: 3px #d2d2d2 solid;
  padding: 15px 40px;
  transition: box-shadow .4s;
  text-decoration: none;
}

.btn > span {
  text-align: center;
  font-family: 'Roboto Condensed', sans-serif;
  font-size: 20px;
  color: #fff;
  line-height: 1;
}

.btn:hover{
  background: #6b9640;
  box-shadow: inset 0px -22px 13px 0px #84b652, inset 0px 2px 5px 0px #84b652;
}
.btn:before,
.btn:after{
  display: inline-block;
  content: "";
  position: absolute;
  z-index: -1;
  bottom: 9px;
  left: 10px;
  width: 88%;
  top: 73%;
  transition: box-shadow .4s;
}
.btn:hover:before,
.btn:hover:after{
  box-shadow: 0 15px 10px #777;
}
<a href="#" class="btn"><span>Join Today</span></a>

https://jsfiddle.net/7argwcje/

That's because before and after elements are effectively children of the .btn element and siblings of the plain text (Join today). So you have no way to force the text to be on front.

These are the changes:

.btn {
  position: relative;
  /* z-index: 1; */
  display: inline-block;
  background-color: #8ec656;
  border-radius: 30px;
  border: 3px #d2d2d2 solid;
  padding: 15px 40px;
  transition: box-shadow .4s;
  text-decoration: none;
}

.btn > span {
  text-align: center;
  font-family: 'Roboto Condensed', sans-serif;
  font-size: 20px;
  color: #fff;
  line-height: 1;
}

Basically transferred some properties from .btn to a wrapper span element.

Notice that the z-indexes are no longer necessary.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Wazaraki
  • 494
  • 2
  • 7
0
.btn:before,
.btn:after{
  transition: .6s;
  content: "";
  box-shadow: 0 28px 17px -3px #777;
  width: 84%;
  height: 11px;
  top: 48%;
  left: 15px;
  position: absolute;
  opacity: 0;
}
.btn:hover:before,
.btn:hover:after{
  opacity: 1;
}

This is what I had to settle with. Thank you for your responses!