Animated text is underlined for multiple lines (animation from left to right)

I'm going crazy about how to simulate the same effect that I show in the code below for one line of text (on hover) in a text with several lines.

.underline-on-hover
{
  position:relative;
  display:inline-block;
}

.underline-on-hover::after
{
  content: " ";
  background-color: red;
  width:0;
  position: absolute;
  left:0;
  bottom:0;
  height:5px;
  
  -webkit-transition: width 1s ease-in-out;
  -moz-transition: width 1s ease-in-out;
  -o-transition: width 1s ease-in-out;
  transition: width 1s ease-in-out;

}

.underline-on-hover:hover::after
{
  width:100%;
}
<p class="underline-on-hover">
I'm a single line text!
</p>
<br><br>
<p class="underline-on-hover" style="max-width:200px">
I'm a multiple line text... let me prove it: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
Run codeHide result

As you can see, I can model this “underline” animation from left to right for one line of text followed by, but I don’t know how to do this for text with several lines, my problem is that I cannot easily split it into lines because it will be dynamic text inserted into a dynamic container ...

Any idea on how to achieve it?

Many thanks!

+4
source share
2

, nth (CSS/JS) jQuery, , css.

+2

, . , js. ie11 ( ).
- .

Codepen

:

.container
  .text Lorem ipsum dolor sit amet consectetur adipisicing elit. Eligendi exercitationem quos, facere ipsum perspiciatis labore dolores, quibusdam, culpa numquam deleniti nihil ad. Tempore beatae nobis facere deserunt nam dicta earum.
br
br
div.test

SCSS:

.text {
  display: inline-block;
  line-height: 1.2;
}

.container {
  position: relative;
}

.line {
  position: absolute;
  width: 0;
  height: 2px;
  background: red;
  transition: width .5s;
}

.container:hover line {  
  left: 0;
  right: auto;
}

JS:

function multilineTextUnderline() {
  var text = document.querySelector('.text');
  var words = text.innerText.split(' ');
  var div = document.querySelector('.test');

  var initialText = text.innerText;
  var widths = [];
  var lineHeight = parseInt($(text).css('line-height'), 10);
  var firstWord = 0;
  text.innerText = words[0];
  var currentHeight = text.offsetHeight;

  $('.test span').remove();
  $('.test br').remove();

  function getWidths() {
    words.forEach(function(word, i) {
      text.innerText = words.slice(firstWord, i + 1).join(' ');
      if(currentHeight < text.offsetHeight) {
          text.innerText = words.slice(firstWord, i).join(' ');
          widths.push(text.offsetWidth);
          firstWord = i;

          var newSpan = document.createElement('span');
          newSpan.innerText = text.innerText;
          div.appendChild(newSpan);
          div.appendChild(document.createElement('br'));

          if(i === words.length - 1) {
            text.innerText = words[i];
            widths.push(text.offsetWidth);

            var newSpan = document.createElement('span');
            newSpan.innerText = text.innerText;
            div.appendChild(newSpan);
            div.appendChild(document.createElement('br'));
          }
      } else if(i === words.length - 1) {
          widths.push(text.offsetWidth);

          var newSpan = document.createElement('span');
          newSpan.innerText = words.slice(firstWord).join(' ');
          div.appendChild(newSpan);
          div.appendChild(document.createElement('br'));
      }
    });
  }

  getWidths();
  text.innerText = initialText;
  console.log('        widhts: ', widths);
  var controlWidths = [];

  [].forEach.call(document.querySelectorAll('.test span'), function(span) {
      controlWidths.push(span.offsetWidth);
  });
  console.log('control widths: ', controlWidths);

  //rendering underlines
  var container = document.querySelector('.container');
  var containerWidth = container.offsetWidth;
  var lines = [];
  $('.line').remove();

  widths.forEach(function(lineWidth, i) {
    var line = document.createElement('div');
    line.classList.add('line');
    line.style.top = lineHeight * (i + 1) - 2 + 'px';

    lines.push(line);
  });

  lines.forEach(function(line) {  
    container.appendChild(line);
  });

  container.addEventListener('mouseenter', function() {
    lines.forEach(function(line, i) {  
      line.style.width = widths[i] + 'px';
      line.style.left = 0;
      line.style.right = 'auto';
    });
  });
  container.addEventListener('mouseleave', function() {
    lines.forEach(function(line, i) {  
      line.style.width = 0;
      line.style.left = 'auto';
      line.style.right = containerWidth - widths[i] + 'px';
    });
  });
}

multilineTextUnderline();

window.addEventListener('resize', function() {

  multilineTextUnderline();
});
+1

Source: https://habr.com/ru/post/1664592/


All Articles