iTranslated by AI
How to Justify a Single Line of Text in CSS
Sometimes you want to justify a single line of text. For example, have you ever encountered a design like the one below?

The texts for "Udon," "Soba," and "Ramen" are justified.
In this article, we will explore ways to achieve such a design using CSS (or HTML and JavaScript).
Using text-align-last
If you are in an environment where the CSS text-align-last property is available, the solution is simple.
The key part is as follows. By setting text-align-last: justify;, the text is now justified.
dt {
text-align-last: justify;
}
The above seems like the best solution (and in fact, it is likely the best if you are targeting the latest versions of modern browsers). However, there is a concern that it is not supported in Safari prior to version 16.0.
So, what should we do to support older browsers? In this article, we will consider several implementation methods.
Inputting spaces
The simplest way is likely to insert spaces.
With a monospaced font, inserting spaces can sometimes solve the issue (though it may not work depending on the number of characters).
However, as you can see from the example above, while it works fine for "Udon" and "Soba," the balance becomes poor between "Udon" and "Ramen" due to the difference in the number of characters.
Using letter-spacing
Let's try adjusting the character spacing using letter-spacing.
In the implementation example below, the character spacing is adjusted with a monospaced font, but if you are using a non-monospaced font, adjustment might be difficult (as you may need to adjust it visually).
Since letter-spacing also creates a space after the last character, we use a negative margin to offset it.
dt[data-num="3"] {
/* Offset margin */
margin-right: -0.5em;
letter-spacing: 0.5em;
}
With this method, the value of letter-spacing depends on the number of characters, which may increase management costs. Also, depending on the font, adjusting the character spacing could become very difficult.
If you are using a monospaced font, you can manage it using CSS variables and calc as follows:
dt {
/*
--result = (maximum character count - target character count) / (number of character gaps)
In this case, the maximum character count is 4 for "ラーメン" (Ramen)
*/
--result: calc((var(--max-num) - var(--num)) / (var(--num) - 1));
margin-right: calc(var(--result) * -1em);
letter-spacing: calc(var(--result) * 1em);
}
Wrapping each character in span tags
The methods of using spaces or letter-spacing have issues with management costs and limited use cases, lacking versatility. Therefore, in practice, the method of wrapping each character in a span might be more commonly adopted.
In the implementation example above, JavaScript is used to wrap the text in span tags, but there is no particular problem with writing the span tags directly in the HTML.
Using text-align
While I have described several implementations so far, this method was the inspiration for writing this article.
justify
The inline contents are justified. Text should be spaced to line up its left and right edges to the left and right edges of the line box, except for the last line.
As stated in the MDN documentation, text-align: justify is not applied to the last line (meaning it cannot be applied to a single line). It is a perfectly valid argument that if text-align: justify could be applied to a single line, then text-align-last wouldn't be necessary in the first place.
So what do we do? We apply text-align: justify by forcing the text into two lines instead of one.
The key part is as follows. We use a pseudo-element to make dt consist of two lines. Additionally, we specify the height using grid-auto-rows. At this time, do not forget to account for the line-height calculation.
:root {
--line-height: 2;
}
dl {
display: grid;
grid-template-columns: auto 1fr;
/* Specify the height. Don't forget to consider line-height */
grid-auto-rows: calc(1em * var(--line-height));
line-height: var(--line-height);
}
dt {
text-align: justify;
}
/* To create two lines, use a pseudo-element (::after) with inline-block and 100% width */
dt::after {
content: "";
display: inline-block;
width: 100%;
}
Although it is a bit of a workaround, we were able to apply text-align: justify even to a single line of text.
When dd spans multiple lines
In the code above, I did not account for situations where the dd text spans multiple lines. Below is a code example that supports multiple lines for the dd.
If you specify the height using grid-auto-rows, the height becomes fixed, which prevents it from supporting multiple lines. Therefore, I removed grid-auto-rows and instead placed a span inside the dt, applying the height specification to that span.
The specific changes were as follows:
<dt><span>Udon</span></dt>
dt > span {
display: inline-block;
width: 100%;
height: calc(1em * var(--line-height));
vertical-align: bottom;
overflow: hidden;
}
This allows the height of the neighboring dd to be flexible while keeping the dt text justified.
Conclusion
text-align-last is very convenient. Since it has decent support across browsers, one approach could be to use text-align-last while allowing Safari versions prior to 16.0 to display as left-aligned (or right-aligned).
Also, the methods introduced in this article are not necessarily the best — even though I'm the one writing this — but keeping them in the back of your mind as a potential option might prove useful someday.
If you know of any other methods, please let me know in the comments!
Discussion