The border
property is a shorthand and changes more than one single property. By applying border: none
you are changing border-style
from solid
to none
, which cannot be transitioned (is not animatable).
In order to transition border-width
you need to keep border-style:solid
in both states and only change border-width
:
.button-orange {
border: 0 solid;
border-color: transparent transparent blue;
transition: background 0.4s, border-width 0.4s, height 0.4s;
background: orange;
}
.button-orange:hover {
border-bottom: 3px solid blue;
border-top: 3px solid rgba(0, 0, 0, 0);
background: green;
height: 94px;
}
<div class="button-orange">Button</div>
However, you'll notice transitioning border-width
is not really good looking, mostly because major browsers apply anti-aliasing to sub-pixel values of the border and the transition will not look smooth.
The most commonly used and eye-catchy effect for "border-like" effects is to have an additional element (usually a pseudo-element acting as a "live" border), animating from 0
to full element width, on X axis.
For example:
.button-orange {
transition: background-color 0.4s, height 0.4s;
background: orange;
position: relative;
height: 18px;
}
.button-orange:hover {
background-color: green;
height: 94px;
}
.button-orange:after {
content: '';
height: 3px;
width: 0;
bottom: -3px;
left: 50%;
background-color: blue;
position: absolute;
transition: width .4s cubic-bezier(.4,0,.2,1);
transform: translateX(-50%)
}
.button-orange:hover:after {
width: 100%;
}
<div class="button-orange">Button</div>
(looks better when not moving the pseudo while changing its width - in our case, could have been placed on top of the element instead of bottom).
Another possible option is to keep the same border-width and animate the border from a "solid" color to transparent
, keeping border-width
unchanged. It looks smoother and keeps the element from "jumping" because of the difference in border-width
.
For example:
.button-orange {
border: 3px solid transparent;
transition: background 0.4s, border-color 0.4s, height 0.4s;
background: orange;
height: 18px;
}
.button-orange:hover {
border-bottom-color: blue;
background: green;
height: 94px;
}
<div class="button-orange">Button</div>
Also note that in your initial example (as well as in my first snippet), the height
property is not, actually animating, because you're trying to animate from default, which is auto
, to a specific value and that, again, is not animatable. You need to set a value on the default state if you want to animate height
. It tricks you into believing it's working but, in fact, it's the border-width
that's animating, creating the illusion the element height is changing. In fact, the border is changing width
while having a style of none
.