:before element overlapping my button text on hover - html

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 />
Do Stuff

You need to add additional <span> element which would stay above the ::before pseudoelement:
span {
position: relative;
z-index: 1;
}
fiddle

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.

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;
}
<span>Do Stuff</span>

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 />
<span>Do Stuff</span>

Related

CSS: Skewed button using pseudo position: absolute

I have a button with only a single tag (<a>). I want to skew the background of the button and keep the text as is, so I'm using this code, which is working as expected in my Codepen example:
<a class="et_pb_button et_pb_pricing_table_button" href="#">$200 / Month</a>
.et_pb_pricing_table_button {
margin: 10px;
cursor: pointer;
background-color: transparent;
border: none;
height: 50px;
padding: 10px 60px;
position: relative;
color: #000000;
font-weight: bold;
text-decoration: none;
}
.et_pb_pricing_table_button:after {
z-index: -1;
content: '';
display: block;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
transform: skewX(-15deg);
border-radius: 0px;
background-color: #ffd100;
}
.et_pb_pricing_table_button:hover:after{
background-color: skyblue;
}
However, when I apply that code to my page, it is not rendering as expected (not visible). I can't find anything that is stopping this from working (the parent elements are position: relative). I also tried increasing the z-index of the pseudo selectors, but that didn't help either. What am I missing?

CSS Animation only works when applied to grand-parent and not parent? [duplicate]

This question already has answers here:
How to make a hover effect for pseudo elements?
(4 answers)
Closed 2 years ago.
So, I am trying to create a simple underline animation on hover, everything works fine but there's a small weird behavior that I don't get.
This code snippet doesn't work as expected. On hover it has no effect.
.underline {
font-weight: bold;
font-size: 2rem;
position: relative;
}
.underline::before {
pointer-events: none;
position: absolute;
content: "";
width: 0%;
height: 6px;
background-color: black;
left: 50%;
bottom: 0;
transition: all .4s ease-in-out;
}
.underline:hover {
cursor: pointer;
}
.underline:hover .underline::before {
height: 6px;
width: 100%;
left: 0;
}
body {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
<div class="underline">Know More</div>
But a small tweak i.e. wrapping .slider into a container .wrapper solves the problem. I don't get why.
.underline {
font-family: cursive;
font-weight: bold;
font-size: 3rem;
position: relative;
}
.underline::before {
pointer-events: none;
position: absolute;
content: "";
width: 0%;
height: 6px;
background-color: black;
left: 50%;
bottom: 0;
transition: all .4s ease-in-out;
}
.underline:hover {
cursor: pointer;
}
.wrapper:hover .underline::before {
height: 6px;
width: 100%;
left: 0;
}
body {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
<div class="wrapper">
<div class="underline">Know More</div>
</div>
So, .wrapper:hover .underline::before css selector works but .underline:hover .underline::before doesn't WHY?
.underline:hover .underline::before looks for an element with class underline inside an element with class underline. It's a descendant selector. That doesn't match your document structure.
I'm not entirely sure what your goal is, but I'd bet that .underline:hover::before would do fine. See How to make a hover effect for pseudo elements?.

Pseudo element moves from below to above parent on CSS transform

I have button with a pseudo element I placed underneath to create a clicking effect. I wrote this code:
button {
appearance: none;
--webkit-appearance: none;
background-color: #0070c9;
border-radius: .3em;
border: none;
color: white;
display: inline-block;
font: inherit;
font-size: 1.5em;
padding: 5px 10px;
position: relative;
text-transform: uppercase;
}
button::after {
background-color: #005496;
border-radius: .3em;
bottom: -.2em;
content: '';
height: 100%;
left: 0;
position: absolute;
width: 100%;
z-index: -1;
}
button:active, button:focus {
outline: none;
}
button:active {
transform: translateY(0.1em);
}
button:active::after {
bottom: -.1em;
}
<button>Button</button>
When the button is clicked, the pseudo element becomes the background of the button; I want the light background to remain over the pseudo element while the transform occurs and after. Is there a reason that the pseudo element moves under the text but above the background of the button?
Note: I am not using any vendor-prefixed CSS in my original code, I just added --webkit-appearance: none; to this page; I will use a post-processor to handle this later.
Edit
The button looks like the left when not in active state, and the the right image in active state.
I do not want the button to become dark when it is in active state. I want the background to remain the same.
I want the button to look like this when it is clicked:
I have added a ::before pseudo element as well and then shifted the z-index of the :before and :after pseudo elements when the button is active. I have also added a span around the buttons text and added a positition of relative and a z-index of 3 to bring it to the front of the pseudo elements.
button {
appearance: none;
background:none;
--webkit-appearance: none;
border-radius: .3em;
border: none;
color: white;
display: inline-block;
font: inherit;
font-size: 1.5em;
padding: 5px 10px;
position: relative;
text-transform: uppercase;
}
button span {
position:relative;
z-index:3;
}
button::before, button::after {
border-radius: .3em;
content: '';
height: 100%;
left: 0;
position: absolute;
width: 100%;
}
button::before {
background-color: #0070c9;
top: 0;
z-index: 2;
}
button::after {
background-color: #005496;
bottom: -.2em;
z-index: 1;
}
button:active, button:focus {
outline: none;
}
button:active span {
bottom: -.2em;
}
button:active::before {
z-index:2;
background:none;
}
button:active::after{
z-index:1;
background-color: #0070c9;
}
<button><span>Button</span></button>

Overlap ::after and ::before with text in CSS

Goal: Make nice effect of hovering buttons in pure CSS, which will use ::after and ::before pseudo-elements. Look at this jsFiddle example to see, what I want to reach.
Code: Button will have some styling, also an background-color, which is turned off in this example.
.button {
display: inline-block;
position: relative;
height: 35px;
line-height: 35px;
padding: 0 15px;
/*background-color: white;*/
text-decoration: none;
color: black;
}
Problem: I want to use background-color and when I enable it, then I can't see pseudo-elements. It is like that, because these pseudo-elements have z-index: -1;, which put them behind the background. When I change z-index to 0 or 1, then text is not visible.
What I can't do: I can't add new elements inside buttons (like spans), because this is one already running website and client decided to change the behavior of buttons, so here I am. There are tons of buttons in this website, so this is the reason, why I want to find solution with pseudo-elements, because trying to find every single button and change them would be inappropriate.
If i understood you well, this is what you are looking for:
.button {
display: inline-block;
position: relative;
height: 35px;
line-height: 35px;
padding: 0 15px;
/*background-color: white;*/
text-decoration: none;
color: black;
border:1px solid;
}
a.button:before {
content: " ";
display: block;
z-index: -1;
position: absolute;
height: 0%;
top: 0;
right: 0;
left: 0;
background: #ddd;
transition: height 0.2s ease;
}
a.button:hover:before {
height:100%;
}
TEST
Consider an alternative method of doing the background colour transition thing.
As seen in this edited demo:
/* remove all references to .button::before */
.button {
background-image: linear-gradient(to bottom,
transparent, transparent 100%,
red 100%, red);
transition: background-image 0.5s ease 0s;
}
/* the "gradient" above has the practical result of being fully transparent,
but it has been carefully crafted so that the transition gives the desired result */
.button:hover {
background-image: linear-gradient(to bottom,
transparent, transparent 0%,
red 0%, red);
}
You can transition gadients, and in this case it is done stop-by-stop. The first and last stops don't change, but the middle two transition from 100% to 0%, essentially meaning that the cut-off point between transparent and red slides from the bottom to the top of the button, giving the effect you want.
You can now replace transparent with your desired background colour.
* You may need to remove the z-index:-1 from the ::after element to get the border effect back.
You can do something like,
HTML
CSS
body {
background: #FF7272;
}
.button {
display: inline-block;
position: relative;
height: 35px;
line-height: 35px;
padding: 0 15px;
text-decoration: none;
color: black;
z-index: 0;
background-color: white;
width: 50px;
}
.button::before, .button::after {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: 0;
}
.button::after {
content: "TEST";
height: 50%;
width: 72px;
text-align: center;
z-index: 2;
line-height: 0.2;
border-left: 4px solid red;
border-right: 4px solid red;
border-bottom: 4px solid red;
}
.button::before {
height: 0%;
background-color: red;
transition: all 0.5s ease 0s;
z-index: 1;
}
.button:hover::before {
height: 100%;
}
Example: https://jsfiddle.net/LL0f7rwp/6/
Some values are hard coded, but hope you can get an idea out of it :)
It's because z-index: -1 and background-color: white will push your :before and :after elements beneath.
Remove z-index: -1 from :after and :before and add to hover .button:hover::before
Make the background-color: transparent while hovering. Updated fiddle.
body {
background: #FF7272;
}
.button {
display: inline-block;
position: relative;
height: 35px;
line-height: 35px;
padding: 0 15px;
background-color: white;
text-decoration: none;
color: black;
}
.button::before,
.button::after {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: 0;
}
.button::after {
height: 50%;
border: 4px solid red;
border-top: 0;
}
.button::before {
height: 0%;
background-color: red;
transition: all 0.5s ease 0s;
}
.button:hover::before {
height: 100%;
z-index: -1;
}
.button:hover {
background-color: transparent;
}
TEST

CSS hide top part of text

I prefer CSS only solution; I can change HTML structure; Always only single line of text
TL;DR;
How to hide top part of text instead of bottom:
div {
overflow: hidden;
height: 11px;
}
<div>HOME</div>
Full example
I want to hide top of the text line so I can simulate transition effect:
div {
height: 20px;
width: 100px;
text-align: center;
}
div span {
display: block;
overflow: hidden;
transition: all 500ms ease-in-out;
height: 20px;
}
div .default {
color: black;
background-color: #f0f0f0;
}
div .hover {
height: 0;
color: white;
background-color: black;
}
div:hover .hover {
height: 25px;
}
div:hover .default {
height: 0px;
}
<div>
<span class="default">HOME</span>
<span class="hover">HOME</span>
</div>
As you can see in example .hover is currently sliding from bottom because text is hidden from bottom to top when height is reduced.
I want to hide text from top to bottom, so that it will look like same text is inverting it's color.
Are you against if I use pseudo elements to do it ? I play with bottom height to make it appears from top to bottom with the text in content property.
div .default {
display: block;
overflow: hidden;
height: 20px;
position: relative;
color: black;
background-color: #f0f0f0;
}
div .default:after { content: "Home"; position: absolute; left: 0; bottom: 100%; right: 0; background: #000; color: #fff; text-transform: uppercase; transition: all 500ms ease-in-out;}
div .default:hover:after { bottom: 0; }
HTML
<div>
<span class="default">HOME</span>
</div>
Like this
Other solution keeping the structure and avoid text in content property
<div>
<span class="default">HOME</span>
<span class="black">HOME</span>
</div>
CSS
div .black { position: absolute; left: 0; bottom: 100%; right: 0; background: #000; color: #fff; text-transform: uppercase; transition: all 500ms ease-in-out;}
div .default:hover ~ .black { bottom: 0; }
Fiddle with 2nd solution
I have solved that by using absolute positioned element over origin item:
div {
height: 20px;
width: 100px;
text-align: center;
position: relative;
}
div span {
display: block;
overflow: hidden;
transition: all 500ms ease-in-out;
height: 20px;
}
div .default {
color: black;
background-color: #f0f0f0;
/* ADDED */
position: absolute;
left: 0;
z-index: 10;
top: 0;
width: 100%;
height: 100%;
}
div .hover {
height: 20px;
color: white;
background-color: black;
}
div:hover .default {
height: 0px;
}
<div>
<span class="default">HOME</span>
<span class="hover">HOME</span>
</div>
Given your first example, this one hides top part of the text. Just play around with the line-height on your animation
Just add on your div span style:
line-height: 5px; /* play with the value till desired look is reached*/
https://jsfiddle.net/w0ydLg9h/