CSS leading-trim – The Future of Digital Typesetting

Ethan Wang, who works at Microsoft:

In a standard text box, there’s almost always extra space above and below the actual text. Because of this, when you use a text box to measure and implement spacing, it ends up larger than you intended. The bigger the line height, the bigger the problem.

You can see the issue below: the 32px gap between all text ends up too be more than 32px because of this:

To solve this the new CSS property leading-trim from the CSS Inline Layout Module Level 3 specification can be used. As per spec:

The leading-trim properties allow controlling the spacing above and below the first and last lines of a block. It allows precise control over spacing; moreover, by relying on font metrics rather than hard-coded lengths, it allows content to be resized, rewrapped, and rendered in a variety of fonts while maintaining that spacing.

Vertical Centering of Text is explicitly mentioned in the specification of this new property. Use it as follows:

h1 { 
 text-edge: cap alphabetic;
 leading-trim: both;

As Wang notes:

The example above first uses text-edge (also a new property) to tell the browser the desired edge of the text is the cap height and the alphabetic baseline. Then it uses leading-trim to trim it from both sides.

These two simple lines of CSS create a clean text box that hugs your text. This helps you achieve much more accurate spacings and create a better visual hierarchy.

Cool! 🤩

Leading-Trim: The Future of Digital Typesetting →

The Case of the Top Secret iPod

David Shayer, who was an iPod Software Engineer – the 2nd one they hired for the iPod project when it started in 2001 – back in the day:

It was a gray day in late 2005. I was sitting at my desk, writing code for the next year’s iPod. Without knocking, the director of iPod Software — my boss’s boss — abruptly entered and closed the door behind him. He cut to the chase. “I have a special assignment for you. Your boss doesn’t know about it. You’ll help two engineers from the US Department of Energy build a special iPod. Report only to me.”

You can of course already guess the two engineers didn’t work for the US Department of Energy itself, but worked for a US Defense Contractor …

The Case of the Top Secret iPod →

Via Kottke

Feature Detecting CSS Flexbox Gap Support

In my post on Flexbox Gap I wanted to feature detect support for it using @supports. That however failed. As I then noted:

In the demo above I wanted to show a warning in browsers that don’t support flexbox gap. For that I tried using @supports, which has proven to be successful before.

.warning {
    display: block;

/* Hide warning in case browser supports flexbox gap */
@supports (display: flex) and (gap: 1em) { /* DOES NOT WORK AS INTENDED! */
    .warning {
        display: none;

But that’s not really working as intended. In Chromium < 85 – which does not support flexbox gap – the warning is hidden, this because both conditions are evaluated separately:

  • Does Chromium < 85 support display: flex? Yes
  • Does Chromium < 85 support gap: 1em? Yes (from CSS Grid)

This makes me wonder whether re-using property names remains a good idea or not. Perhaps an extension to css-conditional should be made so that it supports a combination of properties — e.g. @supports (display: flex; gap: 1em)?

I’ve filed an issue for the latter.


Recently Ahmad Shadeed has encountered the same issue. Digging further into the issue – and looking for a way to detect it now – he finally turned to Feature Detection using JavaScript, with this little snippet borrowed from Modernizr:

function checkFlexGap() {
    // create flex container with row-gap set
    var flex = document.createElement("div");
    flex.style.display = "flex";
    flex.style.flexDirection = "column";
    flex.style.rowGap = "1px";

    // create two, elements inside it

    // append to the DOM (needed to obtain scrollHeight)
    var isSupported = flex.scrollHeight === 1; // flex container should be 1px high from the row-gap

    return isSupported;

With said function in place, you can then add a CSS class onto the html element to indicate if the combination of both Flexbox and Gap is supported or not. With some clever selectors in place inside your CSS, you can then act upon that.

How to detect browser support for Flexbox Gap →

“On the origin of cascades“, a talk by @hdv on how CSS came to be

Hidde recently gave a talk at CSS Café on the origins of CSS:

It’s been 25 years since the first people proposed a language to style the web. Since the late nineties, CSS lived through years of platform evolution. The cascade, specificity and the enormous choice in values and units set the language up for success. But not everyone liked to use these features everywhere. Some began to adapt the language to meet their needs.

In this Darwin-themed talk, you’ll learn how CSS came to be, and how the language’s simplicity and flexibility still make it stand out today.

In addition to the video embedded at the top of this post you can also check out the slides or read a full transcript.

👨‍🎓 Looking for more lessons in CSS History? The Languages Which Almost Became CSS by Zach Bloom also touches the same subject.

Legacy to Laravel: How to Modernize an Aging PHP Application

The folks at Tighten:

In this post, I’ll present some strategies we use at Tighten to convert legacy apps to Laravel gradually over time, without needing to perform a full rewrite. Whether you’re upgrading from an old framework or moving to a framework for the first time, following these steps will let you start benefitting from all that Laravel has to offer right away.

What they basically do is set up a new Laravel project and have it catch the parts that they changed/added. Using a catchall rule, all other requests are routed to the legacy code. Clever.

Route::any('{path}', '[email protected]')->where('path', '.*');

From then on they start migrating to Eloquent models, introduce some helper functions, etc.

Legacy to Laravel: How to Modernize an Aging PHP Application →

A Lightweight Masonry Solution

With Masonry being specced in Grid Layout Module Level 2 – and already being implemented in Firefox – Ana Tudor looked into whipping up a lightweight fallback for browsers that don’t support it.

🤔 Masonry Layout?

Masonry is a grid layout based on columns, as popularized by Pinterest. Unlike other grid layouts, it doesn’t have fixed height rows. It works by placing elements in optimal position based on available vertical space, sort of like a mason fitting stones in a wall.

It became easy to implement thanks to the Masonry JavaScript Library.

After first laying out all images in columns, she then calculates the vertical gaps between all items. Each gap is adjusted – using a negative top margin – so that the items shift upwards, after which them end up at their wanted positions.

A Lightweight Masonry Solution →

Chrome is about to hide parts of the URL

In Chrome 86, we’re going to experiment with how URLs are shown in the address bar on desktop platforms. Our goal is to understand — through real-world usage — whether showing URLs this way helps users realize they’re visiting a malicious website, and protects them from phishing and social engineering attacks.

A shame they didn’t follow Jake’s proposal (as talked about in HTTP 203 and pictured below) though, as that pleases both a non-technical as a technical audience.

Screengrab of Jake’s Proposal

But then again I can imagine that there’s no good reason to show a bunch of seemingly random characters – which us developers can parse and interpret – to regular users like my mum. Most web-related support calls from her end up with me asking “are you on bla.com” with the rest of the URL not being entirely irrelevant, or me instructing her to “go to foo.com and search for X” instead of spelling out the whole URL.

Chrome is about to hide parts of the URL →

(And yes, there is an option to “Always show full URLs”)

Refactoring optional chaining into a large codebase: lessons learned

Lea Verou on how Optional Chaining affected her code, along with caveats and scenarios where it couldn’t be used.

Now that optional chaining is supported across the board, I decided to finally refactor Mavo to use it. This is a moment I have been waiting for a long time, as I think optional chaining is the single most substantial JS syntax improvement since arrow functions and template strings.

Refactoring optional chaining into a large codebase: lessons learned →