1

I have some short and long text in html with max-width and overflow styles. i want to check if an element is overflowing then start back and forth animation to users can see all contents.

Please see this demo:

.animated {
  position: relative;
  white-space: nowrap;
  max-width: 150px;
  overflow: hidden;
  background: #0c0c0c;
}

.text-animated{
  color: #fff;
  animation: backAndForth 5s linear infinite;
}

@keyframes backAndForth {
    0% { transform: translateX(0); }
    10% { transform: translateX(0); }
    45% { transform: translateX(calc(100% - 340px)); }
    55% { transform: translateX(calc(100% - 340px)); }
    90% { transform: translateX(0); }
    100% { transform: translateX(0); }
}
<div class="animated">
  <h3 class="text-animated">
    Some Short Text
  </h3>
</div>
<span>Must be fixed</span>

<br><br><br>

<div class="animated">
  <h3 class="text-animated">
    Some Long And Bigger Text To Animate
  </h3>
</div>
<span>Must be Animated to view all text</span>

Can anybody help me?

Thanks

Hadi Rajabi
  • 67
  • 1
  • 12

3 Answers3

2

Although a max width is set it is not being taken up on the smaller text - notice the widths of both examples are the same.

This snippet gives both the div and the h3 a position so that the widths are taken up and the div is set to have width fit-content (it will still obey the max-width).

The animation needs to take into account both the width of the container and the width of the text. It therefore uses left positioning and transition. For the shorter text they balance out so there is no movement. For the longer text the amount of movement is just the extra length of the text compared to the container.

.animated {
  position: relative;
  white-space: nowrap;
  max-width: 200px;
  overflow: hidden;
  background: #0c0c0c;
  display: inline-block;
  width: fit-content;
  position: relative;
}

.text-animated {
  color: #fff;
  animation: backAndForth 5s linear infinite;
  display: inline-block;
  position: relative;
}

@keyframes backAndForth {
  0% {
    transform: translateX(0);
    left(0);
  }
  10% {
    transform: translateX(0);
    left: 0;
  }
  45% {
    transform: translateX(calc(-100%));
    left: 100%;
  }
  55% {
    transform: translateX(calc(-100%));
    left: 100%;
  }
  90% {
    transform: translateX(0);
    left: 0;
  }
  100% {
    transform: translateX(0);
    left: 0;
  }
}
<div class="animated">
  <h3 class="text-animated">
    Some Short Text
  </h3>
</div>
<span>Must be fixed</span>

<br><br><br>

<div class="animated">
  <h3 class="text-animated">
    Some Long And Bigger Text To Animate
  </h3>
</div>
<span>Must be Animated to view all text</span>

UPDATE: a couple of additional requirements have been added (in the comments below).

The max-width needs to change from a fixed px width to be relative to container size. The snippet below demonstrates this by putting the divs in a container whose width depends on viewport size.

The text direction has changed from left to right to right to left. The settings for left and transform/translate therefore have to swap signs compared to tehe original code above:

.container {
  width: 40vw;
  position: relative;
}

.animated {
  position: relative;
  white-space: nowrap;
  /* max-width: 200px; */
  max-width: calc(100% - 5rem);
  overflow: hidden;
  background: #0c0c0c;
  display: inline-block;
  width: fit-content;
  position: relative;
  white-space: no-wrap;
  direction: rtl;
}

.text-animated {
  color: #fff;
  animation: backAndForth 5s linear infinite;
  display: inline-block;
  position: relative;
  direction: rtl;
}

@keyframes backAndForth {
  0% {
    transform: translateX(0);
    left(0);
  }
  10% {
    transform: translateX(0);
    left: 0;
  }
  45% {
    transform: translateX(calc(100%));
    left: -100%;
  }
  55% {
    transform: translateX(calc(100%));
    left: -100%;
  }
  90% {
    transform: translateX(0);
    left: 0;
  }
  100% {
    transform: translateX(0);
    left: 0;
  }
}
<div class="container">
  <div class="animated">
    <h3 class="text-animated">
      Some Short Text
    </h3>
  </div>

  <br><br><br>

  <div class="animated">
    <h3 class="text-animated">
      Some Long And Bigger Text To Animate
    </h3>
  </div>
</div>
A Haworth
  • 30,908
  • 4
  • 11
  • 14
  • Thanks, your code is correct, but my language direction is rtl, and in the main project I use `max-width: calc (100% -5rem)` because I want long texts to overflow in **responsive mode**. Please see https://jsfiddle.net/yasproject/ozbqw38d/18. the short text have vibrate animation! – Hadi Rajabi Jun 21 '22 at 22:29
  • Are you saying that this answers the question as posed but there are extra things now which need to be taken into consideration? It should be easy to incorporate these new requirements. Have you tried? I don't understand the vibrate comment - I don't see any vibration (I'm on Edge/Chrome Windows 10). What system are you on? – A Haworth Jun 22 '22 at 04:54
  • I've added in the two new requirements in another snippet. I still don't see any vibration. Can you let me know what system you see vibration on? – A Haworth Jun 22 '22 at 05:23
  • Sorry, I'm using Firefox and there is still a problem even with your code. Please see this gif https://i.imgur.com/ZxROgWK.gif – Hadi Rajabi Jun 22 '22 at 07:36
  • I've tried it on FF on WIndows10 and don't see any 'vibration'. What system are you on? This seems to be a rather different problem from that posed in the original question. If we can't solve it here shortly I suggest you post the code in my second snippet in a new question and specifically ask the question about your version of FF/OS. As I don't see the problem I am unlikely to solve it! – A Haworth Jun 22 '22 at 07:52
  • Thanks My Friend, I'm also using FF on Win 10. In the main project and in desktop mode https://i.imgur.com/WAsvtAQ.gif and mobile mode https://i.imgur.com/dI1NSPb.gif, all texts are vibrating and no animate! – Hadi Rajabi Jun 22 '22 at 07:57
  • Do you get the same effect when you just run the second snippet here - without any changes at all, just pressing the run snippet button? We need for now to concentrate on that simple task rather than bring in other factors like a different typeface, images and other CSS. – A Haworth Jun 22 '22 at 08:09
1

scrollWidth is the width of elements with also not showable content.

and offsetWidth is the only showable content width.


so if the scrollWidth is different than offsetWidth, this means that is overflowing!

if (childEl.scrollWidth > childEl.offsetWidth) {
      childEl.classList.add("text-animated");
}

enter image description here

/* choose your parent element (that can be also a <body> if you want all elements) */
let parent = document.querySelectorAll(".animated");

parent.forEach((el) => {
  /* get all h3 from parent (if you want all elements use "*" selector)*/
  let childs = el.querySelectorAll("h3");

  childs.forEach(childEl => {
    /* if overflow then add class */
    if (childEl.scrollWidth > childEl.offsetWidth) {
      childEl.classList.add("text-animated");
    }
  });
});
.animated {
  position: relative;
  white-space: nowrap;
  max-width: 150px;
  overflow: hidden;
  background: #0c0c0c;
}

.text-animated {
  color: #fff;
  animation: backAndForth 5s linear infinite;
}

@keyframes backAndForth {
  0% {
    transform: translateX(0);
  }
  10% {
    transform: translateX(0);
  }
  45% {
    transform: translateX(calc(100% - 340px));
  }
  55% {
    transform: translateX(calc(100% - 340px));
  }
  90% {
    transform: translateX(0);
  }
  100% {
    transform: translateX(0);
  }
}
<!-- 1 -->
<div class="animated">
  <h3>
    Some Short Text
  </h3>
</div>
<span>Must be fixed</span>

<br><br><br>

<!-- 2 -->
<div class="animated">
  <h3>
    Some Long And Bigger Text To Animate
  </h3>
</div>
<span>Must be Animated to view all text</span>
Laaouatni Anas
  • 4,199
  • 2
  • 7
  • 26
  • Thanks my friend, there is a bug that I used fixed 340px in css and if the text is too long it will not be seen completely – Hadi Rajabi Jun 21 '22 at 21:28
0

HTML text-overflow ellipsis detection says you can detect if element has overflown content:

function isEllipsisActive(e) {
     return (e.offsetWidth < e.scrollWidth);
}
IT goldman
  • 14,885
  • 2
  • 14
  • 28