Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

webkit-line-clamp: text-align: right; breaks text-overflow: ellipsis;

Tags:

css

My target is:

  1. limit the number of text lines
  2. text should be aligned right
  3. text overflow: 3 dots

The problem begins when I add text-align: right; to the style: 3 dots behave differently than without the text-align style property: in general, 3 dots are outside the text container (grey color).

enter image description here

Compare "good" vs "bad" styles; The only difference: "good" doesn't contain text-align: right; style property. Try to play with font-size in those styles and you will see that for the "good" style 3 dots are always inside the text container (grey background) while for the "bad" style 3 dots' position is unexpected (could be inside the container, or partly inside, or fully outside)

So, is there any chance to have a 3 dots behavior like for the "good" style, but at the same time have text aligned right? Take into account the line number limit.

* {
  box-sizing: border-box;
}

body {
  height: 100vh;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #78b9f3;
  margin:0;
  font-family: "Arial";
}

.wrapper {
  display: flex;
  justify-content: center;
}

.card {
  background: #fff;
  box-shadow: 0 4px 24px 3px rgb(0 0 0 / 10%);
  padding: 20px;
  margin: 20px;
  width: 200px;
  height: auto;
  border-radius: 6px;
}

p {
  font-size: 1em;
  line-height: 1.3em;
  margin:0;
}

h2 {
  font-size: 1.5em;
  margin: 0 0 0.5em 0;
}

.good {
  font-size: 20px;
  background-color: grey;
   text-overflow: ellipsis;
   display: -webkit-box;
   -webkit-line-clamp: 2;
           line-clamp: 2; 
   -webkit-box-orient: vertical;
}

.bad {
  font-size: 20px;
  text-align: right;
  background-color: grey;
   text-overflow: ellipsis;
   display: -webkit-box;
   -webkit-line-clamp: 2;
           line-clamp: 2; 
   -webkit-box-orient: vertical;
}
<section class="wrapper">
  <div class="card">
    <h2>Good</h2>
    <p class="good">Hello, I'm a very long text for at least three lines!</p>
  </div>
  <div class="card">
    <h2>Bad</h2>
    <p class="bad">Hello, I'm a very long text for at least three lines!</p>
  </div>


</section>
like image 760
Stetho Avatar asked Dec 09 '25 20:12

Stetho


2 Answers

I just found a trick way to fix the above issue:

  1. Add padding-right for the div/p: 20px --> The number is harding code for show only three dots
  2. Using text-align: right

Hope this way help you temporarily fix the issue.

See example below:

* {
  box-sizing: border-box;
}

body {
  height: 100vh;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #78b9f3;
  margin:0;
  font-family: "Arial";
}

.wrapper {
  display: flex;
  justify-content: center;
}

.card {
  background: #fff;
  box-shadow: 0 4px 24px 3px rgb(0 0 0 / 10%);
  padding: 20px;
  margin: 20px;
  width: 200px;
  height: auto;
  border-radius: 6px;
}

p {
  font-size: 1em;
  line-height: 1.3em;
  margin:0;
}

h2 {
  font-size: 1.5em;
  margin: 0 0 0.5em 0;
}

.good {
  font-size: 20px;
  background-color: grey;
   text-overflow: ellipsis;
   display: -webkit-box;
   -webkit-line-clamp: 2;
           line-clamp: 2; 
   -webkit-box-orient: vertical;
   
   text-align: right;
   padding-right: 20px; //added code
  
}

.bad {
  font-size: 20px;
  text-align: right;
  background-color: grey;
   text-overflow: ellipsis;
   display: -webkit-box;
   -webkit-line-clamp: 2;
           line-clamp: 2; 
   -webkit-box-orient: vertical;
}
<section class="wrapper">
  <div class="card">
    <h2>Good</h2>
    <p class="good">Hello, I'm a very long text for at least three lines!</p>
  </div>
  <div class="card">
    <h2>Bad</h2>
    <p class="bad">Hello, I'm a very long text for at least three lines!</p>
  </div>


</section>
like image 158
Quyen Vo Avatar answered Dec 12 '25 06:12

Quyen Vo


TL;DR: there is no 100% predictable css fix

Just take a look at the compatibility table on mdn – apart from firefox, browser support is rather spotty (to put it mildly).

However, you could fix this rendering issue with some javaScript.
... or you could also mimic text-overflow an line-clamp properties with some old school overflow and line height properties.

Example 1: css only hack

This hack is based on defining some line-height related classes.
Css variables help to facilitate the calculations:

:root {
  --overflowLineHeight: 1.25em;
  --overflowColor1: rgba(255, 255, 255, 1);
  --overflowColor2: rgba(255, 255, 255, 0);
}


.maxLines2 {
  max-height: calc(var(--overflowLineHeight) * 2);
}

The actual overflow indicator (ellipsis) element is just an absolutely positioned pseudo element with a background gradient (placed in a relatively positioned parent element).

* {
  box-sizing: border-box;
}

body {
  height: 100vh;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #78b9f3;
  margin: 0;
  font-family: "Arial";
}

.wrapper {
  display: flex;
  justify-content: center;
  padding:1em;
}

.card {
  background: #fff;
  box-shadow: 0 4px 24px 3px rgb(0 0 0 / 10%);
  padding: 1em;
  margin: 1em;
  width: 33%;
  height: auto;
  border-radius: 6px;
  resize: both;
  overflow: hidden;
}

p {
  font-size: 1em;
  line-height: 1.3em;
  margin: 0;
}

h2 {
  font-size: 1.5em;
  margin: 0 0 0.5em 0;
}

:root {
  --overflowLineHeight: 1.25em;
  --overflowColor1: rgba(255, 255, 255, 1);
  --overflowColor2: rgba(255, 255, 255, 0);
}

.overflow {
  font-size: 20px;
  line-height: var(--overflowLineHeight);
  text-align: right;
  overflow: hidden;
  position: relative;
}

.overflow:after {
  content: " …";
  position: absolute;
  bottom: 0;
  right: 0;
  display: block;
  z-index: 1;
  background-image: linear-gradient( 90deg, var(--overflowColor2), var(--overflowColor1) 50%);
  width: 2.5em;
}

.maxLines2 {
  max-height: calc(var(--overflowLineHeight) * 2);
}

.maxLines3 {
  max-height: calc(var(--overflowLineHeight) * 3);
}

.maxLines4 {
  max-height: calc(var(--overflowLineHeight) * 4);
}
<section class="wrapper">
  <div class="card">
    <h2>Fix: 2 lines</h2>
    <p class=" maxLines2 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>

  <div class="card">
    <h2>Fix: 3 lines</h2>
    <p class=" maxLines3 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>

  <div class="card">
    <h2>Fix: 4 lines</h2>
    <p class=" maxLines4 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>

</section>

Example 2: js hack for line-clamp

This hack is based on the fact word-break: break-all will render the ellipsis within the block boundaries.

Unfortunately, this will result in ugly word breaks.

To fix this issue,

  • we're splitting all words into an array of <span>elements.
  • then we check all span heights: if a span height is larger than the first instance - it contains a line break
  • spans with line breaks get a special class with a word-break: break-word property

let overflows = document.querySelectorAll(".overflow");
fixOverflow(overflows);

function fixOverflow(overflows) {
  overflows.forEach(function(text, i) {
    //split textContent into array
    let words = text.innerHTML
      .split(" ")
      .map((w) => {
        return w.trim();
      })
      .filter(Boolean);

    //delete current textContent
    let wrapped = "";
    text.textContent = "";
    text.style.setProperty("word-break", "break-all");
    let bbText = text.getBoundingClientRect();
    let bottomText = bbText.y + bbText.height;

    //get line height by checking the first word's height
    let span0 = document.createElement("span");
    span0.textContent = words[0] + " ";
    span0.classList.add("wordWrp");
    text.appendChild(span0);
    let height0 = span0.getBoundingClientRect().height;

    //check max lines and init counter
    let style = window.getComputedStyle(text);
    let maxLines = parseFloat(style.webkitLineClamp);
    let breaks = 0;

    //wrap words in spans
    for (let i = 1; i < words.length; i++) {
      let word = words[i];
      let span = document.createElement("span");
      span.textContent = word + " ";
      span.classList.add("wordWrp");
      text.appendChild(span);
      let bbSpan = span.getBoundingClientRect();
      let heightSpan = bbSpan.height;
      let bottomSpan = bbSpan.y + bbSpan.height;
      if (heightSpan > height0 && breaks < maxLines - 1 && bottomSpan < bottomText) {
        span.classList.add("wordWrpLine");
        breaks++;
      }
    }
  });
}


//update on resize 
const resizeObserver = new ResizeObserver(() => {
  upDateOverflows();
});
overflows.forEach(function(text, i) {
  resizeObserver.observe(text);
});

function upDateOverflows() {
  overflows.forEach(function(text, i) {
    let wordWraps = text.querySelectorAll(".wordWrp");
    let bbText = text.getBoundingClientRect();
    let bottom = bbText.y + bbText.height;
    let height0 = wordWraps[0].getBoundingClientRect().height;

    //check max lines and init counter
    let style = window.getComputedStyle(text);
    let maxLines = parseFloat(style.webkitLineClamp);
    let breaks = 0;

    for (let i = 1; i < wordWraps.length; i++) {
      let wordWrap = wordWraps[i];
      wordWrap.classList.remove("wordWrpLine");

      let bb = wordWrap.getBoundingClientRect();
      let height = bb.height;
      let bottomSpan = bb.y + bb.height;

      if (height > height0 && breaks < maxLines - 1 && bottomSpan < bottom) {
        wordWrap.classList.add("wordWrpLine");
        breaks++;
      }
    }
  });
}
* {
  box-sizing: border-box;
}

body {
  height: 100vh;
  width: 100%;
  background: #78b9f3;
  margin: 0;
  font-family: "Arial";
}

.wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
}

.card {
  background: #fff;
  box-shadow: 0 4px 24px 3px rgb(0 0 0 / 10%);
  padding: 20px;
  margin: 20px;
  width: 250px;
  height: auto;
  border-radius: 6px;
  resize: both;
  overflow: hidden;
}

p {
  font-size: 1em;
  line-height: 1.3em;
  margin: 0;
}

h2 {
  font-size: 1.5em;
  margin: 0 0 0.5em 0;
}

.overflow {
  font-size: 20px;
  text-align: right;
  background-color: grey;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
}

.overflow:hover .wordWrp {
  outline: 1px solid red;
}

.maxLines2 {
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

.maxLines3 {
  -webkit-line-clamp: 3;
  line-clamp: 3;
}

.maxLines4 {
  -webkit-line-clamp: 4;
  line-clamp: 4;
}

.wordWrpLine {
  word-break: break-word;
}

.wordWrpLine2 {
  background: red;
}
<h2>Resize cards</h2>
<section class="wrapper">
  <div class="card">
    <h2>Fix: 2 lines</h2>
    <p class=" maxLines2 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>

  <div class="card">
    <h2>Fix: 3 lines</h2>
    <p class=" maxLines3 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>
  
  <div class="card">
    <h2>Fix: 4 lines</h2>
    <p class=" maxLines4 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>
  
</section>

Example 3: js hack emulating line-clamp

Pretty similar to the previous js approach – by means of splitting the element's text into span elements.

This time we're completely replacing the css elllipsis placeholder by appending a custom <span> element.

The overflow "ellipsis" placeholder is placed according to some boundig box checks: the first span element leaving the overflow defined boundaries will be the position/index for prepending the ellipsis span.

let overflows = document.querySelectorAll(".overflow");
fixOverflow(overflows);

function fixOverflow(overflows) {
  overflows.forEach(function(text) {
    let spanWrps = text.querySelectorAll(".wordWrp");
    let words = '';
    let hasSpans = spanWrps.length ? true : false;
    let spanEllipse = text.querySelector(".spanEllipse");

    //create ellpse san if not already present
    if (!spanEllipse) {
      spanEllipse = document.createElement("span");
      spanEllipse.classList.add('spanEllipse');
      spanEllipse.textContent = ' …';
    }

    // get word/string array - unless it's aleady generated
    if (hasSpans) {
      words = [...spanWrps].map((word) => {
        return word.textContent
      });
    } else {
      //split textContent into array
      words = text.innerHTML
        .split(" ")
        .map((w) => {
          return w.trim();
        })
        .filter(Boolean);
    }


    let bbText = text.getBoundingClientRect();
    let bottomText = bbText.y + bbText.height;

    //delete current textContent
    if (!hasSpans) {
      text.textContent = "";
    }

    for (let i = 0; i < words.length; i++) {
      let word = words[i];

      //wrap words in spans if not already done
      let span = '';
      if (hasSpans) {
        span = spanWrps[i];
        span.classList.remove('wordWrpOverflow');
      } else {
        span = document.createElement("span");
        span.textContent = word + " ";
        text.appendChild(span);
        span.classList.add("wordWrp");
      }

      let bbSpan = span.getBoundingClientRect();
      let bottomSpan = bbSpan.y + bbSpan.height;
      if (bottomSpan > bottomText) {
        span.classList.add("wordWrpOverflow");
      } else {
        span.classList.remove("wordWrpOverflow");
      }
    }

    let firstOverFlow = text.querySelector('.wordWrpOverflow');
    if (firstOverFlow) {
      let bbE = spanEllipse.getBoundingClientRect();
      let bottomE = bbE.y + bbE.height;
      let bbPrev = firstOverFlow.previousElementSibling.getBoundingClientRect();
      let bottomPrev = bbPrev.y + bbPrev.height;

      //add ellipsis before first overflow element
      if (bottomE > bottomText && bottomPrev < bottomText) {
        firstOverFlow.parentNode.insertBefore(spanEllipse, firstOverFlow.previousElementSibling);
      } else {
        // ellipsis might be in overflow area - traverse backwards
        if (bottomPrev > bottomText) {
          firstOverFlow.parentNode.insertBefore(spanEllipse, firstOverFlow.previousElementSibling.previousElementSibling);
        } else {
          firstOverFlow.parentNode.insertBefore(spanEllipse, firstOverFlow);
        }
      }
    }
    // no ellipsis neede - remove it!
    else {
      spanEllipse.remove();
    }
  });
}

//update on resize 
const resizeObserver = new ResizeObserver(() => {
  fixOverflow(overflows)
});
overflows.forEach(function(text, i) {
  resizeObserver.observe(text);
});
* {
  box-sizing: border-box;
}

body {
  height: 100vh;
  width: 100%;
  background: #78b9f3;
  margin: 0;
  font-family: "Arial";
}

.card {
  background: #fff;
  padding: 20px;
  margin: 20px;
  height: auto;
  border-radius: 6px;
  resize: both;
  overflow: auto;
}

p {
  font-size: 1em;
  line-height: 1.3em;
  margin: 0;
}

h2 {
  font-size: 1.5em;
  margin: 0 0 0.5em 0;
}

:root {
  --lineHeight: 1.2em;
}

.overflow {
  font-size: 20px;
  line-height: var(--lineHeight);
  text-align: right;
  overflow: hidden;
}

.maxLines2 {
  max-height: calc(2 * var(--lineHeight));
}

.maxLines3 {
  max-height: calc(3 * var(--lineHeight));
}

.maxLines4 {
  max-height: calc(4 * var(--lineHeight));
}

.wordWrpOverflow {
  visibility: hidden;
}


/* force line break */

.spanEllipse+span {
  display: block
}

.txt-cnt * {
  text-align: center;
}

@media (min-width:720px) {
  .card {
    width: 33%;
  }
  .wrapper {
    display: flex;
    justify-content: center;
  }
}

@media (min-width:1024px) {
  .card {
    width: 250px;
  }
}
<section class="wrapper">


  <div class="card">
    <h2>Fix: 2 lines</h2>
    <p class=" maxLines2 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>


  <div class="card">
    <h2>Fix: 3 lines</h2>
    <p class=" maxLines3 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>

  <div class="card txt-cnt">
    <h2>Fix: 4 lines: <br />text-align:center</h2>
    <p class=" maxLines4 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>

</section>

Exclude browsers with proper text-overflow/line-clamp support

Currently only firefox and some iOS safari versions seem to render ellipsis correctly.
To avoid unnecessary js processing for these browser you could include a feature detection:

let firefoxOverflow = CSS.supports("text-overflow", "ellipsis ellipsis");
let safariWebkit = CSS.supports("-webkit-hyphens", "none");
let needsWorkaround = false;
if(!firefoxOverflow && !safariWebkit) {
  needsWorkaround = true;
  document.body.classList.add("needs-overflow-fix");
}

This will certainly not work for all firefox an safari versions.
At least it doesn't use any browser sniffing.

/**
 * check proper overflow support
 **/
let supportText = "";
let firefoxOverflow = CSS.supports("text-overflow", "ellipsis ellipsis");
let safariWebkit = CSS.supports("-webkit-hyphens", "none");
let needsWorkaround = false;
if (!firefoxOverflow && !safariWebkit) {
  needsWorkaround = true;
  document.body.classList.add("needs-overflow-fix");
}

// just for display
if (needsWorkaround) {
  supportText = "needs workaround - use js";
} else {
  supportText = "proper support – use css";
}
support.textContent = supportText;


/**
* apply workaround if necessary
**/
if (needsWorkaround) {
  let overflows = document.querySelectorAll(".overflow");
  fixOverflow(overflows);

  function fixOverflow(overflows) {
    overflows.forEach(function (text) {
      
      /*
      let style = window.getComputedStyle(text);
      let styleClamp = parseFloat(style.getPropertyValue("-webkit-line-clamp"));
      styleClamp = !styleClamp
        ? parseFloat(style.getPropertyValue("line-clamp"))
        : styleClamp;
      //console.log(style)
      console.log("clamp", styleClamp);

      if (styleClamp > 0) {
        //text.classList.add('maxLines'+styleClamp);
      }
      */

      let spanWrps = text.querySelectorAll(".wordWrp");
      let words = "";
      let hasSpans = spanWrps.length ? true : false;
      let spanEllipse = text.querySelector(".spanEllipse");

      //create ellpse san if not already present
      if (!spanEllipse) {
        spanEllipse = document.createElement("span");
        spanEllipse.classList.add("spanEllipse");
        spanEllipse.textContent = " …";
      }

      // get word/string array - unless it's aleady generated
      if (hasSpans) {
        words = [...spanWrps].map((word) => {
          return word.textContent;
        });
      } else {
        //split textContent into array
        words = text.innerHTML
          .split(" ")
          .map((w) => {
            return w.trim();
          })
          .filter(Boolean);
      }

      let bbText = text.getBoundingClientRect();
      let bottomText = bbText.y + bbText.height;

      //delete current textContent
      if (!hasSpans) {
        text.textContent = "";
      }

      for (let i = 0; i < words.length; i++) {
        let word = words[i];

        //wrap words in spans if not already done
        let span = "";
        if (hasSpans) {
          span = spanWrps[i];
          span.classList.remove("wordWrpOverflow");
        } else {
          span = document.createElement("span");
          span.textContent = word + " ";
          text.appendChild(span);
          span.classList.add("wordWrp");
        }

        let bbSpan = span.getBoundingClientRect();
        let bottomSpan = bbSpan.y + bbSpan.height;
        if (bottomSpan > bottomText) {
          span.classList.add("wordWrpOverflow");
        } else {
          span.classList.remove("wordWrpOverflow");
        }
      }

      let firstOverFlow = text.querySelector(".wordWrpOverflow");
      if (firstOverFlow) {
        let bbE = spanEllipse.getBoundingClientRect();
        let bottomE = bbE.y + bbE.height;
        let bbPrev = firstOverFlow.previousElementSibling.getBoundingClientRect();
        let bottomPrev = bbPrev.y + bbPrev.height;

        //add ellipsis before first overflow element
        if (bottomE > bottomText && bottomPrev < bottomText) {
          firstOverFlow.parentNode.insertBefore(
            spanEllipse,
            firstOverFlow.previousElementSibling
          );
        } else {
          // ellipsis might be in overflow area - traverse backwards
          if (bottomPrev > bottomText) {
            firstOverFlow.parentNode.insertBefore(
              spanEllipse,
              firstOverFlow.previousElementSibling.previousElementSibling
            );
          } else {
            firstOverFlow.parentNode.insertBefore(spanEllipse, firstOverFlow);
          }
        }
      }
      // no ellipsis neede - remove it!
      else {
        spanEllipse.remove();
      }
    });
  }

  //update on resize
  const resizeObserver = new ResizeObserver(() => {
    fixOverflow(overflows);
  });
  overflows.forEach(function (text, i) {
    resizeObserver.observe(text);
  });
}
* {
  box-sizing: border-box;
}

body {
  height: 100vh;
  width: 100%;
  background: #78b9f3;
  margin: 0;
  font-family: "Arial";
}

.needs-overflow-fix {
  background: orange;
}

.card {
  background: #fff;
  padding: 20px;
  margin: 20px;
  height: auto;
  border-radius: 6px;
  resize: both;
  overflow: auto;
}

p {
  font-size: 1em;
  line-height: 1.3em;
  margin: 0;
}

h2 {
  font-size: 1.5em;
  margin: 0 0 0.5em 0;
}

:root {
  --lineHeight: 1.2em;
}

.overflow {
  font-size: 20px;
  line-height: var(--lineHeight);
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
}

.needs-overflow-fix .overflow {
  text-overflow: unset;
  overflow: hidden;
  display: block;
  -webkit-line-clamp: unset !important;
  line-clamp: unset !important;
  -webkit-box-orient: unset !important;
}

.maxLines2 {
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

.maxLines3 {
  -webkit-line-clamp: 3;
  line-clamp: 3;
}

.maxLines4 {
  -webkit-line-clamp: 4;
  line-clamp: 4;
}

.needs-overflow-fix .maxLines2 {
  max-height: calc(2 * var(--lineHeight));
}
.needs-overflow-fix .maxLines3 {
  max-height: calc(3 * var(--lineHeight));
}
.needs-overflow-fix .maxLines4 {
  max-height: calc(4 * var(--lineHeight));
}

.wordWrpOverflow {
  visibility: hidden;
}

/* force line break */
.spanEllipse + span {
  display: block;
}

.txt-cnt * {
  text-align: center;
}

@media (min-width: 720px) {
  .card {
    width: 33%;
  }

  .wrapper {
    display: flex;
    justify-content: center;
  }
}
@media (min-width: 1024px) {
  .card {
    width: 250px;
  }
}
<p style="text-align:center"><strong id="support" >&nbsp;</strong></p>
<section class="wrapper">
  <div class="card">
    <h2>Fix: 2 lines</h2>
    <p class=" maxLines2 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>
  <div class="card">
    <h2>Fix: 3 lines</h2>
    <p class=" maxLines3 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>
  <div class="card txt-cnt">
    <h2>Fix: 4 lines: <br />text-align:center</h2>
    <p class="maxLines4 overflow">Hello, I'm a very long text1 for at least three lines! Hello, I'm a very long text2 for at least three lines! Hello, I'm a very long text2 for at least three lines!</p>
  </div>

</section>

If the background color changes from blue to orange – js fix is applied.

like image 44
herrstrietzel Avatar answered Dec 12 '25 04:12

herrstrietzel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!