html5 or css 'smart text flow' to evenly distribute a sentence or paragraph over equally wide lines?

2k Views Asked by At

Suppose I have a dynamic HTML element (a span or div or whatever) with a sentence or paragraph of text inside, like this:

two lines

Now if I make the sentence slightly longer, it might need an extra line, like this:

three lines wrong

Note how the last word is on a separate line. So the first two lines are full occupied. In the sense that they take up the entire available with in this element. And the third line contains only one word and remains mostly empty.

I find this rather disturbing, and I wonder if there is a trick to distribute the free space more evenly amongst all lines. I mean like this: (note that this is the exact same sentence)

three lines right

It should re-flow automatically depending on font and browser view size, and width of the element, which may depend on screen resolution.

Is there some clever HTML5 or CSS3 way to achieve this?

Upon searching and looking in topics similar to this question, I did find the text-align: justify property which I am familiar with but isn't really what I'm looking for.
text-align: justify tends to extend all lines to the full with of the containing element by increasing the whitespace between words.

Instead, what I'm really looking for is something that redistributes the words so that all lines are narrower i.e. not take up all horizontal element space. In a way that results in all lines being equally wide (or approximating this as close as possible).

So I mean NOT like this: (which is what text-align:justify does)

text-align justify

Compare this to the previous example above.

2

There are 2 best solutions below

1
On BEST ANSWER

I know you asked for a CSS solution but I don't think there is one yet. Below is my JS solution for the meantime.

function createBetterLineBreaks(el) {
  var originalWidth = el.offsetWidth;
  var originalHeight = el.offsetHeight;
  for (let i = originalWidth - 1; i >= 0; i--) {
    el.style.width = `${i}px`;
    if (el.offsetHeight > originalHeight) {
      el.style.width = `${i + 1}px`;
      break;
    }
  }
}
// hover effects
document.querySelector('.box').addEventListener('mouseenter', function() {
  createBetterLineBreaks(document.querySelector('.box .text'));
});
document.querySelector('.box').addEventListener('mouseleave', function() {
  document.querySelector('.box .text').style.width = 'unset';
});
.box {
  width: 300px;
  font-size: 30px;
  border: 1px solid black;
  border-radius: 5px;
  padding: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
}
<div class="box"><span class="text">hover this box to distribute the text more evenly</span></div>

0
On

You're looking for the CSS Text Module 4 property text-wrap: balance. It has been proposed but unfortunately not yet implemented, so in the meantime, use this jQuery polyfill balance-text.

balanceText();
.box {
  width: 300px;
  font-size: 30px;
  border: 1px solid black;
  border-radius: 5px;
  padding: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.balance-text {
  text-wrap: balance;
}
<script src="//cdn.jsdelivr.net/npm/[email protected]/balancetext.min.js"></script>
<div class="box"><span class="text balance-text">The words in this sentence cause it to require three lines.</span></div>