It’s been possible to create gorgeous layouts on the web for decades, but often, refining the details to perfection can take a lot of effort. Arguably too much effort, and developers just don’t have the time.
Happily, the last few years of CSS have seen a lot of new tools, sometimes very simple tools, that when used in a smart fashion suddenly make polishing graphic design details incredibly easy. In this article, I’ll show you two such tools.
Line height units
#Gaining a new unit that represents the line height might seem like no big deal. Support shipped in every browser in 2023 without much fanfare. But wow, are they powerful.
Basically, 1lh
equals the height of one line of text for the current font at the current line height. “LH” stands for Line Height. The accompanying 1rlh
unit is the equivalent of one line height at the root, just like how rem
is the em
at the root. “RLH” stands for Root Line Height.
My favorite thing to do with the lh
unit is to set margins on content. Let’s set a new universal margin on paragraphs with the following paragraph rule.
p { margin-block: 1lh; }
You can see the results in the following screenshots. On the left, the margin in the block direction is set to 1em
, the default in UA stylesheets since the '90s. On the right it’s changed to 1lh
.
Many people with an eye for layout and spacing can immediately see the difference. You might agree that the version on the right just looks more polished. It looks refined. In comparison, the version on the left looks a bit clunky. It looks, well, like everything on the web has looked for decades. Slightly awkward.
Many other people will look at this comparison and think, “I don’t see it” or “What’s the big deal?” Let’s draw a line grid over the text to make the difference clearer. Hopefully, now it’s more obvious that the blank space between paragraphs is equivalent to a line of text when it’s defined in lh
units.
Line height units give us a direct way to tie any size in our layout to the vertical rhythm of the text. Margins are just one possibility — padding is another, as well as gaps, width, height, or any other measurement in the layout.
Line height units are supported in over 90% of the browsers people use today. For that last 10%, you can use progressive enhancement to ensure they get a good experience.
article {
padding: 1em; /* fallback for browsers lh without support */
padding: 1lh;
}
Using this technique causes browsers without support to render 1em
of padding, while the browsers with support render 1lh
of padding.
Margin trim
#Now let’s look at the second seemingly-unimportant-but-actually-powerful tool that’s come to CSS — margin-trim
.
Imagine multiple paragraphs inside an article element styled as such.
article {
padding: 2lh;
font-size: 1.2rem;
line-height: 1.3;
p {
margin-block: 1lh;
}
}
By using lh
for the margins between the paragraphs and the padding on the article box, we’re attempting to create a beautiful typographic layout. But what’s happening with all the extra space above and below the text?
Let’s turn on some guides to see better what’s happening. The padding on the article box is seen here in yellow, while the paragraph margins are marked in green.
Turns out, the margins on the first and last paragraphs (1lh
) are being added to the padding (2lh
) to create a space that measures 3lh
. This feels like too much space.
It will be better for the design if we get rid of the margin above the first paragraph and the margin below the last paragraph. The new margin-trim
property gives us an easy way to do so. It provides a mechanism to tell the box, in this case the article, to eliminate any margins that are butting up against that box.
For example:
article {
/* Added: */
margin-trim: block;
font-size: 1.2rem;
line-height: 1.3;
padding: 2lh;
p {
margin-block: 1lh;
}
}
Now, the browser automatically chops off any margins that touch the edge of the article box in the block direction — in this case, the top and bottom of the box.
While the margins are defined on the <p>
element, you declare margin-trim
on the <article>
element. Here’s the result. It looks pretty great.
Support for margin-trim shipped almost two years ago in Safari 16.4. So far, Safari is the only browser with support. But you can start using it today with progressive enhancement techniques.
What should you do for browsers without support? For our demo, you could write fallback code inside of feature queries, like this:
article {
margin-trim: block;
font-size: 1.2rem;
line-height: 1.3;
padding: 2lh;
p {
margin-block: 1lh;
}
}
@support not (margin-trim: block) {
article {
:first-child {
margin-block-start: 0;
}
:last-child {
margin-block-end: 0;
}
}
}
When using :first-child
and :last-child
, any element that’s the first or last direct child of the container will have its margins trimmed. But any content that either isn’t wrapped in an element or that is nested further deep will not.
For example, if the first element is a figure with a top margin, and the figure contains an image that also has a top margin, both of those margins will be trimmed by margin-trim
, while only the figure margin will be trimmed by :first-child
.
<article>
<figure style="margin-top: 1em">
<img style="margin-top: 1em" src="photo.jxl" alt="[alt]">
<figcaption>[caption]</figcaption>
</figure>
</article>
The margin-trim
property makes trimming such margins easier and more robust than older techniques.
You can, of course, also trim margins that bump up against a box in the inline direction. These are all valid options:
margin-trim: none
margin-trim: bloc
kmargin-trim: inline
margin-trim: block-start
margin-trim: block-end
margin-trim: inline-start
margin-trim: inline-end
If you want to trim in both directions at the same time, you can do so by combining long-hand values. For example:
margin-trim: block-start block-end inline-start inline-end
More recently, the CSSWG resolved to allow the shorter block and inline keywords in combination, allowing for syntax like this:
margin-trim: block inline
Safari still needs to update our implementation to support this last option. Follow this issue for updates.
Try it yourself
#You can try out combinations of options to see the effects of both lh
and margin-trim: block
by interacting with this demo.
Take your typography to the next level
#It really is a great time for typography on the web. Over a dozen small features that shipped in the last few years empower web designers and developers to polish typographic details to a far better result, especially with the kind of easy robustness that makes it practical to accomplish. It’s my hope you use them!
Let me know what you think on Bluesky or Mastodon. I’d love to hear your stories, plans, and questions.
Jen selected MEAction for an honorary donation of $50
MEAction or "Myalgic Encephalomyelitis Action Network" is a patient-led advocacy org for post-viral illness & disability like Long Covid.