Results Website Design's company banner with logo showing increased sales.
Results Website Design's company banner with logo showing increased sales.

Expanding Underline from Center: Five Approaches

On several websites I noticed an interesting animation that was triggered when a menu item was hovered over.  An underline expanded from the center of the element being hovered until it extended the full width of the element.  Below I have demonstrated five different ways this effect can be accomplished.  Hover over the black text below to trigger the effect.  The rotate, scale, and keyframe methods all use pseudo-elements to draw the line.  The jQuery and "transition on width" methods draw the line with a child or sibling element that has a background color and is absolutely positioned.  The simplest method is probably the first listed.

CSS transform: rotate.


CSS transform: scale.


CSS transition on width & position.


CSS keyframe animation.


jQuery animation.


HTML
<div class="main-container">
    <h2 class="underline-title see-through">Expanding Underline from Center Point: 5 Approaches</h2>

    <p class="underlines-description">blah blah blah.</p>

    <h3 class="rotate">CSS transform: rotate.</h3>
    <br>
    <h3 class="scale">CSS transform: scale.</h3>
    <br>
    <h3 class="width-parent">CSS transition on width & position.<span class="width-child width-child-small"></span></h3>
    <br>
    <h3 class="keyframe keyframe-temp-color">CSS keyframe animation.</h3>
    <br>
    <div class="js-container">
        <h3 class="js-first">jQuery animation.</h3>
        <div class="js-second"></div>
    </div>
</div>
CSS
/*heading text with changing colors*/
.see-through {
    background: url(https://resultswebsitedesign.com/wp-content/uploads/2017/10/green2-1000x100.jpg) center top;
    /* if we can clip, do it */
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    /* fallback text color, which needs to work on the background for IE*/
    color: black;
    animation: hue 10s infinite;
    animation-delay: 3s;
}
/*color cycling animation in title text: credit animate.css website*/
@-webkit-keyframes hue {
    from {
        -webkit-filter: hue-rotate(0deg);
    }
    to {
        -webkit-filter: hue-rotate(-360deg);
    }
}
.rotate,
.scale,
.width-parent,
.keyframe,
.js-container {
    position: relative;
    display: inline-block;
}
.rotate::after,
.scale::after,
.keyframe::after {
    left: 0;
    top: 28px;
    position: absolute;
    content: "";
    height: 2px;
}
.rotate::after {
    width: 100%;
    background: black;
    transform: rotateY(270deg);
    transition: transform 1s ease-out;
}
.rotate:hover::after {
    transform: rotateY(180deg);
}
.scale::after {
    width: 100%;
    background: black;
    transform: scale(0);
    transition: transform 1s cubic-bezier(0.14, 0.77, 0.38, 0.97);
}
.scale:hover::after {
    transform: scale(1);
}
.keyframe::after {
    left: 50%;
    background: black;
    animation: shrink 1s;
}
/*temp bkgrnd color of .keyframe underline is transparent until the initial requisite animation completes.  This class is then removed*/
.keyframe-temp-color::after {
    background: transparent;
}
.keyframe:hover::after {
    animation: grow 1s;
}
@keyframes shrink {
    from {
        left: 0;
        width: 100%;
    }
    to {
        left: 50%;
        width: 0;
    }
}
@keyframes grow {
    from {
        left: 50%;
        width: 0;
    }
    to {
        left: 0;
        width: 100%;
    }
}
.width-child {
    position: absolute;
    height: 2px;
    background: black;
    left: 0;
    bottom: 2px;
    transition: all 1s;
}
.width-child-small {
    width: 0;
    left: 50%;
}
.width-child-big {
    width: 100%;
    left: 0;
}
.js-second {
    width: 0;
    height: 2px;
    position: absolute;
    background: black;
    right: 50%;
    bottom: 8px;
}
JavaScript
 jQuery(document).ready(function () {
     /*CSS transition on width of toggled class*/
     //toggle class with changed width
     jQuery(".width-parent").hover(
         //in
         function () {
             jQuery('.width-child').toggleClass('width-child-big width-child-small');

         },
         //out
         function () {
             jQuery('.width-child').toggleClass('width-child-big width-child-small');

         });
     /*CSS keyframe animation*/
     //remove class that hides .keyframe underline animation after the first requisite animation is complete.  This prevents the underline animation from being visible on page load, but allows it to happen thereafter on hover.
     setTimeout(function () {
         jQuery('.keyframe').removeClass('keyframe-temp-color');
     }, 1100);
 });
jQuery(window).on("load resize", function () {
     /*jQuery animation from center point*/
     //needs to run on load to get correct width measurement
     jQuery(".js-first").hover(
         //in 
         function () {
            var maxWidth = Math.round(jQuery('.js-first').width());
             jQuery('.js-second').animate({
                 width: maxWidth,
                 right: 0
             });
         },
         //out
         function () {
             jQuery('.js-second').animate({
                 width: 0,
                 right: '50%'
             });
         });
 });