Font optical sizing bug in Safari 16

Update: as of Safari 16.4, this bug has been fixed. I’ve updated the code snippet to reflect this. Thanks to the efforts of Myles and team for turning this around so quickly.

In my previous post I extolled the virtues of Literata’s font optical sizing, in particular how it worked automatically in the browser. By ‘it’ I mean how the corresponding style was chosen along the optical size axis of the variable font, based on type size.

Four type styles in a line, ranging from low contrast on the left to high contrast on the right.
Literata’s optical size axis from <7px to >72px. Image ©TypeTogether.

This behaviour is turned on by default, but if you wanted to turn off the automatic optical sizing, you can use this declaration, the effect being to style text as if it were set at 12px:

font-optical-sizing: none;

And you can turn it back on with:

font-optical-sizing: auto;

Automatic selection of optical size styles in a variable font has been supported in browsers since at least 2020. That is until the release of Safari 16 with macOS Ventura. A regression was inadvertently introduced meaning the browser acted as if font-optical-sizing was turned off. The bug was an unintened consequence of improvements being made to Core Text. Fortunately it’s being actively fixed.

So what to do in the meantime? The answer is to use the low level font-variation-settings property to manually set the optical size. I only want to do this for Safari 16.1, 16.2 and 16.3, so firstly I use a bit of clunky user agent sniffing to set a root-level class accordingly:

var root = document.getElementsByTagName('html')[0];
if (navigator.userAgent.indexOf('Safari') != -1 &&
    navigator.userAgent.indexOf('Chrome') == -1 &&
    ( (navigator.userAgent.indexOf('Version/16.1') != -1) ||
      (navigator.userAgent.indexOf('Version/16.2') != -1) ||
      (navigator.userAgent.indexOf('Version/16.3') != -1) )  {

Then I style my headings and body text according to the most appropriate style along the optical size axis:

.isSafari16 h1 { font-variation-settings: "opsz" 60; }
.isSafari16 h2 { font-variation-settings: "opsz" 35; }
.isSafari16 h3 { font-variation-settings: "opsz" 30; }
.isSafari16 body { font-variation-settings: "opsz" 25; }
.isSafari16 footer { font-variation-settings: "opsz" 12; }

This works well, but because the styles are being manually applied to selected elements, rather than automatically on a text size basis, some subtle differences are lost with the responsive text sizing I’m applying.

It’ll do for now, and hopefully the situation will be fixed for the release of Safari 17. Update: It was fixed by version 16.4!