Mr.Smithyyy Mr.Smithyyy - 1 month ago 11
CSS Question

CSS border animation on hover

So I've always animated with JavaScript but I wanted to try doing simpler animations with CSS. I have followed the guide on w3schools exactly but I can't seem to get any results.



nav ul li {
display: inline;
}

nav ul li a {
margin: 0em 2em;
text-decoration: none;
color: #000;
}

nav ul li a:hover {
animation: borderGrow 2s;
-webkit-animation: borderGrow 2s;
}

@keyframes borderGrow {
from { border-bottom: 0em solid #000; }
to { border-bottom: 1em solid #000; }
}

@-webkit-keyframes borderGrow {
from { border-bottom: 0em solid #000; }
to { border-bottom: 1em solid #000; }
}

<nav>
<ul>
<li><a href="#">Link One</li>
<li><a href="#">Link One</li>
<li><a href="#">Link One</li>
</ul>
</nav>




Answer Source

For some reason, the animation doesn't seem to work when the border property is not set on the original element itself (before the animation). Adding the border property to the original element does seem to solve it.

Based on MDN's list of animatable properties, it seems like while the border-color and border-width are animatable, the border-style is not and this could possibly be the reason why we are having to add it in the original element. However adding just border-style: solid by default produces a border in almost all browsers (if not all) and so it is better to specify the border-width: 0 also along with it.

Note:

  1. Behavior seems to be consistent in IE10, IE11 and Firefox. So it is more likely to be the expected behavior and not a bug.
  2. I will update the answer with further details if and when I manage to find a clear and specific source explaining the reason for the behavior.

nav ul li {
  display: inline;
}
nav ul li a {
  margin: 0em 2em;
  text-decoration: none;
  color: #000;
  border-bottom: 0em solid #000;
}
nav ul li a:hover {
  -webkit-animation: borderGrow 2s;
  animation: borderGrow 2s;
}
@-webkit-keyframes borderGrow {
  from {
    border-bottom: 0em solid #000;
  }
  to {
    border-bottom: 1em solid #000;
  }
}
@keyframes borderGrow {
  from {
    border-bottom: 0em solid #000;
  }
  to {
    border-bottom: 1em solid #000;
  }
}
<nav>
  <ul>
    <li><a href="#">Link One</a>
    </li>
    <li><a href="#">Link One</a>
    </li>
    <li><a href="#">Link One</a>
    </li>
  </ul>
</nav>


Alternately this same effect can be achieved by just using transition instead of animation also. And for transition the need to set a border on the element before hover seems to be completely optional. Below is a sample snippet.

nav ul li {
  display: inline;
}
nav ul li a {
  margin: 0em 2em;
  text-decoration: none;
  color: #000;
  border-bottom: 0em solid #000; /*optional for transition */
  -webkit-transition: border-bottom 1s;
  transition: border-bottom 1s;
}
nav ul li a:hover {
  border-bottom: 1em solid #000;
}
<nav>
  <ul>
    <li><a href="#">Link One</a>
    </li>
    <li><a href="#">Link One</a>
    </li>
    <li><a href="#">Link One</a>
    </li>
  </ul>
</nav>