KodeFor.Me
KodeFor.Me

Reputation: 13511

:before element overlapping my button text on hover

I have a button with a background color, and text color set. What I like to do, is when the user hover the mouse on the button, the background to animate from bottom to top and change the color of the text to the color of the background.

For terms of simplicity of the code, I didn't put the transient I like to apply on the CSS properties. I know it's much easyer to change the button background code, but I plan to use transient for changing the :before height on hover.

So I have the following code, but when I hover the mouse on the button, the :before overlapping my button text.

I have also try to play with the z-index but no luck. Do you think is there any solution to this problem ?

body {
  background: #111;
}
.btn {
  color: #FFF;
  background: #333;
  border: none;
  font-size: 18px;
  font-weight: bold;
  padding: 18px 60px;
  position: relative;
}
.btn:before {
  display: block;
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 0;
  background: #FFF;
}
.btn:hover {
  color: #333;
}
.btn:hover:before {
  height: 100%;
}
<br />
<a href="#" class="btn">Do Stuff</a>

Upvotes: 0

Views: 4119

Answers (4)

Raevenk
Raevenk

Reputation: 246

The effect you desire can also be achieved without adding the additional span. By utilising the before and after pseudo elements for background colours and positioning them correctly.

To position the pseudo elements behind the text, set a positive z-index on the element and a negative z-index on the pseudo-element.

.btn {z-index: 1}
.btn:before {z-index: -1;}

Reference this article by Nicolas Gallagher which explains in more detail, see section 'Pseudo background-position' http://nicolasgallagher.com/an-introduction-to-css-pseudo-element-hacks/.

Also see fiddle with it in action: https://jsfiddle.net/j9whmcmz/2/

This technique does not work if you apply a background color to the .btn itself.

Choose your poison I guess, both solutions do the trick.

Upvotes: 4

juallom
juallom

Reputation: 116

Try this:

body {
  background: #333;
}
.btn {
  color: #FFF;
  background: #333;
  display: inline-block;
  position: relative;
  overflow: hidden;
  -webkit-transition: color 0.3s ease-in-out;
  transition: color 0.3s ease-in-out;
}
.btn span {
  display: inline-block;
  padding: 18px 60px;
  border: none;
  font-size: 18px;
  font-weight: bold;
  z-index: 10;
  position: relative;
}
.btn:after {
  display: block;
  content: '';
  position: absolute;
  top: 100%;
  left: 0;
  width: 100%;
  max-height: 0;
  background: #FFF;
  height: 100%;
  z-index: 9;
  -webkit-transition: all 0.3s ease-in-out;
  transition: all 0.3s ease-in-out;
}
.btn:hover {
  color: #333;
}
.btn:hover:after {
  max-height: 100%;
  top: 0;
}
<a href="#" class="btn"><span>Do Stuff</span></a>

Upvotes: 2

JoannaFalkowska
JoannaFalkowska

Reputation: 3677

You need to add additional <span> element which would stay above the ::before pseudoelement:

span {
  position: relative;
  z-index: 1;
}

fiddle

Upvotes: 4

SergeS
SergeS

Reputation: 11779

Solution if pretty obvious - content of the button should be also absolute positioned. Then browser order them properly behind each other.

EDIT: Maybe my formatting and styling is not the best for the case, but it was quick update of your code to get the idea

body {
  background: #111;
}
.btn {
  color: #FFF;
  background: #333;
  border: none;
  font-size: 18px;
  font-weight: bold;
  padding: 18px 60px;
  position: relative;
}
.btn span {
  display: block;
  content: '';
  position: absolute;
  top: 18px;
  left: 0px;
  width: 100%;
  text-align: center;
}
.btn:before {
  display: block;
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 0;
  background: #FFF;
}
.btn:hover {
  color: #333;
}
.btn:hover:before {
  height: 100%;
}
<br />
<a href="#" class="btn"><span>Do Stuff</span></a>

Upvotes: 1

Related Questions