Suppose I have a dynamic HTML element (a span
or div
or whatever) with a sentence or paragraph of text inside, like this:
Now if I make the sentence slightly longer, it might need an extra line, like this:
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)
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)
Compare this to the previous example above.
Use justify-content: space-between to evenly distributes child elements horizontally.
The HTML <p> align Attribute is used to specify the alignment of paragraph text content. Syntax: <p align="left | right | center | justify"> Attribute Values: left: It sets the text left-align.
If you want to limit the text length to one line, you can clip the line, display an ellipsis or a custom string. All these can be done with the CSS text-overflow property, which determines how the overflowed content must be signalled to the user.
The "space-evenly" value for the justify-content property distributes the space between items evenly. It is similar to space-around but provides equal instead of half-sized space on the edges. Can be used in both CSS flexbox & grid.
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>
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With