Home > Software design >  How to get the hover underline effect to start at the start of the word and stop at the end of the w
How to get the hover underline effect to start at the start of the word and stop at the end of the w

Time:12-08

I want the nav bar to be stack vertically and when I hover over the link I want the underline effect to go from the beginning of the word and end at the last letter but instead it start at the center and goes way past the end.

.col-1 ul li { 
  list-style: none;
  display: block; 
  margin: 0 20px;
  color: #e4c95e; 
  position: relative;
}

.col-1 ul li a {
  text-decoration: none;
  text-transform: uppercase;
}

.col-1 ul li::after {
  content: '';
  height: 3px; 
  width: 0; 
  background: #925e02;
  position: absolute;
  bottom: -10px;
  transition: 0.5s; 
}

.col-1 ul li:hover::after {
  width: 20%; 
} 
<div >
        <ul>
          <li><a href="#">Home</a></li>
          <li><a href="#">About Us</a></li>
          <li><a href="#">Meet The Squad</a></li>
          <li><a href="#">Services</a></li>
        </ul>
      </div>

CodePudding user response:

The underline is positioned absolutely but without any coordinates so its showing exactly where your :after is. I suggest giving it left:0. In addition, if you want it to span the width of your a rather than the width of the li you should change it to a:after (rather than li:after) and set your a as position:relative. EG:

.col-1 ul li { 
  list-style: none;
  display: block; 
  margin: 0 20px;
  color: #e4c95e; 
  position: relative;
}

.col-1 ul li a {
  text-decoration: none;
  text-transform: uppercase;
  position:relative;
}

.col-1 ul li a::after {
  content: '';
  height: 3px; 
  width: 0; 
  background: #925e02;
  position: absolute;
  left:0;
  bottom: -10px;
  transition: 0.5s; 
}

.col-1 ul li a:hover::after {
  width: 100%; 
}
<div >
        <ul>
          <li><a href="#">Home</a></li>
          <li><a href="#">About Us</a></li>
          <li><a href="#">Meet The Squad</a></li>
          <li><a href="#">Services</a></li>
        </ul>
      </div>

CodePudding user response:

One approach, with explanatory comments in the code:

.col-1 ul li {
  list-style: none;
  display: block;
  margin: 0 20px;
  color: #e4c95e;
}

/* because you want the transition/animation to
   be relative to the size of the text so the
   contents of the <a>, I'm applying the
   position: relative to the <a> element instead
   of the <li> parent (which has a larger size
   and is independent of the <a>: */
.col-1 ul li a {
  text-decoration: none;
  text-transform: uppercase;
  position: relative;
}

a::after {
  content: '';
  height: 3px;
  width: 100%;
  background: #925e02;
  position: absolute;
  /* positioning the element at the bottom-left of the <a> element: */
  bottom: 0;
  left: 0;
  /* setting the scale of the element to zero on the horizontal/X axis,
     and to 1 (unchanged) on the Y/vertical axis: */
  scale: 0 1;
  /* transitioning the scale property, over 0.5 seconds using the
     ease-in-out timing function: */
  transition: scale 0.5s ease-in-out;
  /* moving the transform-origin from the center (default) to the
  lower-left corner so the scaling transition starts there: */
  transform-origin: bottom left;
}

a:hover::after {
  /* here we set the new scale to be full-size on both axes: */
  scale: 1 1;
}
<div >
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">About Us</a></li>
    <li><a href="#">Meet The Squad</a></li>
    <li><a href="#">Services</a></li>
  </ul>
</div>

It's worth adding that I'm not entirely a fan of that implementation, because I prefer to hover anywhere on the list and have the link be active. To address that – quite personal – issue I offer the below:

:root {
  /* CSS custom properties to allow for theming/styling in one place: */
  --underlineColor: #925e02;
  --underlineHeight: 3px;
  --underlineSpace-before: 0px;
  --underlineSpace-after: 3px;
}

.col-1 ul li {
  list-style: none;
  display: block;
  margin: 0 20px;
  color: #e4c95e;
}

.col-1 ul li a {
  display: block;
  text-decoration: none;
  text-transform: uppercase;
  /* purely for the demo; this is not required: */
  background-color: antiquewhite;
}

/* here we're styling the <span> descendant of the <a> element, the <span>
   being the element that is sized according to the word it contains: */
a span {
  /* we use inline-block to allow for paddings and margins to be easily set: */
  display: inline-block;
  /* we're now positioning the underline relative to this element, rather than
     its parent <a>, so add position: relative here: */
  position: relative;
  /* here I'm adding padding to the bottom of the element, using the calc
     function to work out how much might be required; this is calculated
     by adding the space before the underline (--underlineSpace-before)
     to the height of the underline (--underlineHeight): */
  padding-bottom: calc(var(--underlineSpace-before)   var(--underlineHeight));
  /* the bottom-margin is set to the same value of the custom property
     --underlineSpace-after, and serves to allow some white-space between
     adjacent elements: */
  margin-bottom: var(--underlineSpace-after);
}

/* styling the pseudo-element of the <span> within the <a>: */
a span::after {
  content: '';
  /* we set the height of the underline to be equal to the property-value of
     the custom --underlineHeight property: */
  height: var(--underlineHeight);
  width: 100%;
  /* setting the background to the value of the --underlineColor custom-property: */
  background: var(--underlineColor);
  position: absolute;
  /* positioning the element at the bottom-left of the <a> element: */
  bottom: 0;
  left: 0;
  /* setting the scale of the element to zero on the horizontal/X axis,
     and to 1 (unchanged) on the Y/vertical axis: */
  scale: 0 1;
  /* transitioning the scale property, over 0.5 seconds using the
     ease-in-out timing function: */
  transition: scale 0.5s ease-in-out;
  /* moving the transform-origin from the center (default) to the
  lower-left corner so the scaling transition starts there: */
  transform-origin: bottom left;
}

/* styling the span::after pseudo-element in response to a hover event being
   triggerd on the parent <a> element: */
a:hover span::after {
  /* here we set the new scale to be full-size on both axes: */
  scale: 1 1;
}
<div >
  <ul>
    <li><a href="#"><span>Home</span></a></li>
    <li><a href="#"><span>About Us</span></a></li>
    <li><a href="#"><span>Meet The Squad</span></a></li>
    <li><a href="#"><span>Services</span></a></li>
  </ul>
</div>

  • Related