Reputation: 17
I want to animate a border-bottom on hover over an existing border bottom like so: Gif showing border-bottom transition
I have tried doing this using pseudo states ::before
and ::after
and this only animates a border bottom out of nothing. And I've also tried to include a border-bottom on the original element but this does not work since the transition happens on the ::after
element and the two don't overlap like in the gif example: https://jsfiddle.net/nicyuvi/6xem7zgp/3/
h1 {
color: #666;
display: inline-block;
margin: 0;
text-transform: uppercase;
border-bottom: 3px solid lightgray;
}
h1:after {
display: block;
content: '';
border-bottom: solid 3px #019fb6;
transform: scaleX(0);
transition: transform 250ms ease-in-out;
}
h1:hover:after {
transform: scaleX(1);
}
h1.fromLeft:after {
transform-origin: 0% 50%;
}
<h1 class="fromLeft">Expand from left</h1>
Any answers using html/css/vanilla javascript?
Upvotes: 0
Views: 1478
Reputation: 273688
A simple background animation can do it:
h1 {
color: #666;
display: inline-block;
margin: 0;
text-transform: uppercase;
background:
linear-gradient(#019fb6 0 0),
linear-gradient(lightgray 0 0);
background-size:0% 3px,100% 3px; /* we make the top one 0% width */
background-position:bottom left;
background-repeat:no-repeat;
transition:0.5s;
}
h1:hover {
background-size:100% 3px; /* 100% width on hover */
}
<h1 class="fromLeft">Expand from left</h1>
Considering your code, a negative margin is all what you are missing:
h1 {
color: #666;
display: inline-block;
margin: 0;
text-transform: uppercase;
border-bottom: 3px solid lightgray;
}
h1:after {
display: block;
content: '';
border-bottom: solid 3px #019fb6;
margin-bottom:-3px; /* here */
transform: scaleX(0);
transition: transform 250ms ease-in-out;
}
h1:hover:after {
transform: scaleX(1);
}
h1.fromLeft:after {
transform-origin: 0% 50%;
}
<h1 class="fromLeft">Expand from left</h1>
Upvotes: 2
Reputation: 2095
You need to create to elements stacked on top of each other, then add pointer-events: none
to the upper one, which will make it "transparent" to pointer-events, so you can still acces the input
below it. Using the ~
selector we can now edit the width of the upper element, while hovering the input
, since its placed "phyisically" after the input
.
/* optional */
input[type=text] {
background-color: #ECEFF1;
border: 0;
}
/**/
*,
::after,
::before {
box-sizing: border-box;
}
.wrapper {
display: inline-block;
position: relative;
}
input[type=text],
.onHover {
height: 2rem;
border-bottom-style: solid;
border-bottom-width: 1px;
}
input[type=text] {
border-bottom-color: #B0BEC5;
}
input[type=text]:hover ~ .onHover {
width: 100%;
}
.onHover {
position: absolute;
top: 0;
left: 0;
width: 0;
border-bottom-color: #000;
pointer-events: none;
transition: width 400ms ease-in;
}
<div class="wrapper">
<input type="text">
<div class="onHover"></div>
</div>
Upvotes: 1