Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Browser Font Rendering Inconsistencies (stephaniestimac.com)
88 points by jermier on July 8, 2020 | hide | past | favorite | 48 comments


Summary: if you're specifying a bold font style (700) but not supplying a bold version of the font (only 400 and 600), Safari creates a "faux bold" on its own, while other browsers fall back to the next-closest weight (600).

Neither behavior seems more obviously correct, since you're asking for something that doesn't exist.

Moral of the story: whenever you're using webfonts that come in a variety of weights, make sure you're loading font files in the weights you're intending to use! Otherwise behavior may vary.

(And in contrast to multiple comments here, this has nothing to do with macOS using different/darker types of antialiasing than other operating systems. That is not what this article is about.)


The problem arises when you're invoking a style (like `h1` or `h2`) that by default requests a bold weight, but the `font-face` declaration only supplies a WOFF declared "font-weight: regular". In that case, the browser will try to synthesize a bold style by "smearing" the regular.

One fix for this is to set heading tags to "font-weight: normal".

Another fix is to supply two `font-face` declarations for the same WOFF file, covering both regular and bold, so that when the browser asks for the bold version, it just gets the same thing.

(Strictly speaking, I would classify this as user error, not a browser flaw, though it's an easy mistake to make)


> "Strictly speaking, I would classify this as user error, not a browser flaw, though it's an easy mistake to make"

I agree, but browsers should use console warnings to report when they resort to font synthesis or weight substitution. That would go a long way to help web developers understand this problem.

Similarly, console warnings to report character substitution when a needed character is not present in the font-family list would be useful.

In general, I want more transparency from text rendering engines when they encounter something that may not be what a professional designer or typesetter would want. The opacity of today's engines breeds ignorance among their users (web developers).


People hit this so much, it's maddening.

In this case, they're using Google Fonts, which already does the latter: https://fonts.googleapis.com/css?family=Poppins:400,600

Testing this on my own, I'm not seeing a difference between safari/chrome/firefox on macos. If there's only 400 and 600 weights present, they use the 600 for bold elements. If there's a 700, they use that. You only see faux bolding when there's nothing provided in the 600–900 range.

I think the difference here might be moreso about browser font handling on windows? Though I'm still not sure how they got to the bold result at the top of the screenshot…I wouldn't expect safari to apply a faux bold when the 600 weight is there, and that sure looks like the proper 700 which apparently wasn't being called.

Sidenote: I didn't know about the font-synthesis property until this. Looks like it is intended to prevent any sort of faux bolding or faux italicizing from happening. That's cool.


Perhaps it would have been better then if the web standards never allowed for defining usage of the nearest available weight. It seems to certainly have created enough confusion in the microcosm of just this thread.


Thanks for sharing this explanation! This may fix a frustrating font problem we're encountering with mobile Safari. We're also running into other font issues, such as serving Chinese fonts. Are you open to consulting? Your profile doesn't list contact information. Is it okay to send an email with more details?


Why would it be a bug if two browsers don’t render a h1 element the same, if you don’t specify how you want it to look?


That definitely makes it sound more like undefined behavior than a bug.


Implementation defined :P


Maybe related — there was a Chrome bug regression that was recently fixed that rendered the thickness of font-sizes above a certain threshold incorrectly, large bold text wouldn't be bolded - https://bugs.chromium.org/p/chromium/issues/detail?id=105765...


Damn it folks, stop trying to make your designs pixel perfect!

There will always be font rendering inconsistencies. It's how the web works.

> The cross-platform problem is a harder one to solve as you can't control how the operating system handles font rendering.

Bingo.

So stop trying! Embrace flexible designs and differences in rendering


I think the problem described in the article is a bit beyond 'pixel perfect', though. the font weight is DRAMATICALLY different. Text being way too thin or too thick can have an impact on readability.


A similar problem occurs with the valuable Japanese font "Yu Gothic", which is available on both Windows and Mac by default (both availability is rare).

(Not surprisingly no English info available) https://neos21.hatenablog.com/entry/2019/01/05/000629


Ensuring the browser uses the desired font weight is a hell of a lot different from pixel perfection


These rendering differences also impact vertical alignment with specific fonts, which will absolutely drive you mad if you're trying to troubleshoot.

Take a look at Github's redesign in Firefox. Button and icon alignment are generally off by 1-2px everywhere because of it. Guessing they're just living with it because Firefox is down in the single-digit percentages of browsershare these days.


If you're using Firefox on Linux, check out https://nolanlawson.com/2020/05/02/customizing-fonts-in-fire...


It's important to keep in mind that the bitmap output of various font rasterizers isn't universally the same. If you're designing websites expecting text nodes to have the exact same dimensions, you're making a critical mistake.


Yes different fonts have different dimensions, but I'm talking about the same font across different browsers. The issue is that Firefox and Webkit render the baseline of some fonts with a 1-2px difference.

It's impossible to vertically align Helvetica consistently in Firefox and Chrome without some browser-specific adjustments, but Arial works fine.


I am, too. The same font rendered by Core Text, FreeType, and Direct2D/DirectWrite will not have the exact same dimensions every time despite coming from the same exact file.

Say I render a font with no anti-aliasing on an embedded device, because it's marginally more expensive to do so. If I did anti-alias it, you have to account for possibly growing the bitmap size to do so. If I did, am I no longer compliant with web standards? No, because the web standards don't specify dimension requirements for text nodes from source fonts.

Further, there are multiple different types of ways to anti-alias. Should the web standards dictate how?


Sorry, I misread.

The annoying aspect to me isn't the change in dimensions, but the inaccurate baselines. If we could reliably align text based on its baseline it wouldn't be an issue. "align-items: baseline" would be brilliant if it actually worked cross-browser.

It's pretty telling that Github doesn't even bother to solve the issue in their redesign, they've seemed to write off Firefox text alignment idiosyncrasies.


It would have been great had I known details like this much earlier in my career, but when people talked then about "pixel perfect" designs, I don't think most people understood then what sacrifices you have to make to do so! Box size calculations should be the same, I think, surely. But text specifically has no such requirements for equal precision.

In truth, that type of work would require you to know the output sizes across every supported browser.


Is there something happening in the font world I don't know about? I just spent the past day struggling with fixing my fonts on Arch Linux. I finally just deleted all xorg packages that give bitmap fonts becuase I couldn't get any of them to load right in Firefox. This was after a font package totally broke my installation a week ago.


Tangential but I made getsnapfont.com to test how fonts look like on various OS/browsers.

Unfortunately most designers I've worked with don't acknowledge these inconsistencies when designing. For them, their 2x retina mac represents the vast majority of users.


draw_down was downvoted for this, but I agree. If you're going to write an article on this, you _should_ know, or at least try to.

This would have been more educational if perhaps instead of the author guessing at what behavior should occur, they read the standards[1][2][3] and told us what should occur. There are even definitions in the specifications for how to lookup the nearest available weight.[1][4]

It seems like the author doesn't understand what liberties you have as an implementor. For instance:

> In the computed tab, Edge, Chrome and Firefox are all showing font-weight: bold to be computed to a font-weight of 700, whereas Safari's computed font-weight doesn't have a numerical value, it just remains computed as "bold." But this still doesn't explain much.

Well, OK, but the _author_ didn't explain much. This little tidbit isn't meaningful, it's just an observation without an explanation as to why. But a cursory read shows the specifications clearly state that bold is the same as 700.

> Wait.

> I add ,700 to the end of this string: Poppins:400,600. My heading re-renders and now matches Safari.

Well, yeah.

From Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification, "15.6 Font boldness: the 'font-weight' property"

"If the desired weight is less than 400, weights below the desired weight are checked in descending order followed by weights above the desired weight in ascending order until a match is found. If the desired weight is greater than 500, weights above desired weight are checked in ascending order followed by weights below the desired weight in descending order until a match is found. If the desired weight is 400, 500 is checked first and then the rule for desired weights less than 400 is used. If the desired weight is 500, 400 is checked first and then the rule for desired weights less than 400 is used."[1]

From CSS Fonts Module Level 4, "5.2. Matching font styles"

"If the desired weight is inclusively between 400 and 500, weights greater than or equal to the target weight are checked in ascending order until 500 is hit and checked, followed by weights less than the target weight in descending order, followed by weights greater than 500, until a match is found.

If the desired weight is less than 400, weights less than or equal to the desired weight are checked in descending order followed by weights above the desired weight in ascending order until a match is found.

If the desired weight is greater than 500, weights greater than or equal to the desired weight are checked in ascending order followed by weights below the desired weight in descending order until a match is found."[4]

> So what do I do to render headings consistently across browsers and platforms?

Read the specifications. If you're arguing that Core Text doesn't draw like FreeType or Direct2D/DirectWrite, well, sure, but the specifications don't force you to output particular bitmaps.

[1]: https://www.w3.org/TR/CSS2/fonts.html#propdef-font-weight [2]: https://drafts.csswg.org/css-fonts-3/#font-weight-prop [3]: https://drafts.csswg.org/css-fonts-4/#font-weight-prop [4]: https://drafts.csswg.org/css-fonts-4/#font-matching-algorith...


It's a webkit thing.

Try

-webkit-font-smoothing: antialiased

and you'll get the version with less weight, while 'subpixel-antialiased' is the heavier one. This weight difference is more noticeable in white text against dark backgrounds.

Photoshop offers several options on how to render text that show different "weight" in a similar way... they're called "Crisp", "Strong", "Smooth", etc. In particular there's a "Mac LCD" one which I think matches this "issue" seen in Safari.


As far as I know, -webkit-font-smoothing doesn't change weight, it changes rasterization. What you describe in Photoshop also isn't weight, it's rasterization.[1]

See my post below. This is developer error from not understanding the font-weight implementation. The real answer is browser implementors use an algorithm to determine the nearest available weight. Succeeded standards, depending on how up-to-date the browser is in compliance, use slightly differing algorithms.

As a designer, you must specify exact weights, and understand what the keyword values translate to in the CSS standards. All other behavior is fallback.

[1]: https://www.thegraphicmac.com/improve-text-appearance-with-p...


Yes, it changes rasterization. It’s because MacOS has a legacy of dilating the pixel outlines when subpixel antialiasing is enabled.

When subpixel antialiasing first appeared on OS X, the FIR filter affected the gamma curve, making the font seem too light or thin. Correcting gamma the right way was expensive at the time, so they changed the rasterizer to dilate the outlines, increasing the contrast of the text.

At that same time, the *nix APIs like Xft just cranked up the coefficients of the filter so that the sum was ~40% higher than it was supposed to be, which also worked. I think that was a better method than sabotaging the outline shape.


That's fascinating, I wasn't aware of such details!


As far as I know, -webkit-font-smoothing doesn't change weight, it changes rasterization. What you describe in Photoshop also isn't weight, it's rasterization.[1]

It is true that these settings control the rasterization, but it is also true and a well-known problem that different rasterizations (and in particular, the default rasterizations on different platforms) can result in different apparent font weights.

As you noted in your longer top-level comment, this doesn't actually seem to be the problem the original author encountered here, though.


Yeah, and as DiabloD3 mentioned as well, I think it's a very good reminder.


It's not, actually.

In other cases, this might be that. But in this particular case, it's not. If you look closely, it's not about the heaviness at the edges -- they're literally different outlines. Safari in this case is actually creating a "faux bold". It has nothing to do with the heaviness of antialiasing, like Photoshop's options.


No. Let the browser, macOS and the GPU do the rendering. As the below commenter said, the issue is dev error.


In which a novice web struggles aimlessly before giving up?

Compelling stuff.


Do websites need to look exactly the same in every browser? http://dowebsitesneedtolookexactlythesameineverybrowser.com/


Could this be related to macOS font smoothing? System Preferences > General > uncheck "Use font smoothing when available"


Yes, if you remove "use font smoothing" the font weight gets lighter and closer to other OSes rendering. Big Sur gets rid of this option, but I don't know if the underlying option is still on or not.


This is a well known Mac thing, and its one of the top 5 reasons why I moved away from OSX and refuse to support Apple users.

Safari enforces the OSX "thick antialiasing", causing really thick fonts. This also causes really thick fonts, unreasonably so, in normal non-web apps.

The reverse, unfortunately, is true: a lot of web developers worship at the altar of Apple, and have screwed up perfectly good websites by making their fonts too thin: on every other OS, with every other browser thin fonts break.

If you are a web developer, for the love of all that is holy, test your website on a normal Windows machine, with a normal 100% DPI conventional monitor, in both Chrome and Firefox. If it misrenders, this is on you, and you will look positively incompetent to the 95% of users visiting your website.

Apple users are a vocal minority, they do not represent the silent majority who will easily click away from your website because its unreadable.

The fix on OSX, if you're still willing to use that, is `defaults -currentHost write -globalDomain AppleFontSmoothing -int 1`, and if you have a non-Retina display, combined with `defaults write -g CGFontRenderingFontSmoothingDisabled -bool NO` to turn sub-pixel font rendering back on.

Defaults are 2 and YES, respectively. AppleFontSmoothing accepts values 0 through 3. 0 is off, 1 is light, 2 is medium, 3 is french roast columbian bold.


It's true that Mac has different font rendering, but this is not that.

This article is about "faux bold", which is intentionally faking a bolder text. This goes way beyond any antialiasing preferences.

You're describing Mac-style antialiasing, which has nothing to do with this article.

(Also your description of thin fonts isn't even correct. Thin fonts, if rendered mathematically correctly e.g. converted to curves in Photoshop, are too thin to be legibile at small sizes period. Mac compensates by giving heaviler antialiasing, while Windows compensates with hinting that forces strokes to be a full pixel wide. They look different, but there's no widespread problem of fonts being too thin on Windows.)


This is a well known Mac thing, and its one of the top 5 reasons why I moved away from OSX and refuse to support Apple users

Seriously? You changed operating environments because of font weights? That seems a little over-the-top.


Only on Safari, even.

Yet this comment over all brings up a good point (re: downvotes).


You don't support Apple users on your website? You don't bother to fix breaking issues for any Apple device? I'm genuinely curious to know what industry you work in since that seems like a huge segment of visitors.


Any websites that I work on, which I don't often anymore, use standards. If its broken in Safari, then Safari needs to support the agreed upon W3C standards. I don't personally do weird cutting edge stuff, its stuff generally that's been supported in Firefox and Chrome stable for years. Safari must implement these, or be discontinued.

However, generally, Mac users have always been below 10% of PC users, most of them opt not to use Safari (over half use Chrome, half of whats left use Firefox, roughly; changes over time); in the mobile space, "100%" use Safari due to the anti-trust stance they have against their largest competitors (even if you install Chrome or Firefox or anything else, it is required to be an unoptimized Safari instance underneath, with zero access to any sort of GPU or Javascript optimization) but only a small fraction of handsets sold have been iPhones.

Apple says stuff like, almost 2 billion iPhones have been sold since the introduction of it in 2007, but there are 2 billion active Android devices out there currently.

Analysis like https://www.statista.com/statistics/266219/global-smartphone... (use https://cdn.statcdn.com/Statistic/265000/266219-blank-754.pn... to get around paywall, blue is Android, black is iOS) basically put a nail in Apple's coffin.

Like I've said on here before, if you have a lot of Apple users, you should support them. If you are a huge company, you can afford to deal with the monetary and cognitive overhead of dealing with a developer-hostile company.

But for average devs in smaller or medium sized businesses? I don't see the point to give Apple users priority over the majority. Treat them just as you would any other OS or any other browser, no special support just for them. They won't pay you more, in fact, Apple makes sure they pay you less via the 30% grab on out-of-app service signups they're shaking down big companies over.

The front page of HN is certainly familiar with Apple shakedown stories, at this point it's really hard to argue in favor of supporting Apple anymore than the bare minimum for as little gain as you get.


The thing is, I think this font-weight behavior is perfectly standard. The author isn't familiar with the standard at all, however.


it is required to be an unoptimized Safari instance underneath, with zero access to any sort of GPU or Javascript optimization) but only a small fraction of handsets sold have been iPhones.

3rd party browsers have had access to WKWebView for a while now, so they get almost all the goodies Safari has access to. You can read all about it at "New Chrome for iOS is finally as fast and stable as Safari"--https://arstechnica.com/gadgets/2016/01/new-chrome-for-ios-i....

The iPhone has a little more than 45% of the smartphone market in the United States, which is not nothin’: https://www.statista.com/statistics/236550/percentage-of-us-....

And there are over 1.5 billion active devices in the world--and growing: https://www.macrumors.com/2020/01/28/apple-1-5-billion-activ...

The number of devices running the most current version of Android is pretty small compared to the 80-90% of iOS devices that run the most current operating system. That matters for both web developers and native app developers.

For example, Android 9.0 Pie is only 32.43% of the installed base of Android users. Which means 60%+ are older versions that don't support the latest web features, etc: https://gs.statcounter.com/android-version-market-share/mobi...

On the other hand, iOS 13 is installed on 92% of all iPhones sold in the last 4 years: https://www.imore.com/ios-13-has-been-installed-92-iphones-r...

Anyone who’s website is used by US smartphone users by definition has a lot of iPhone customers.


You're describing anti-aliasing, not font-weight.


OSX font anti-aliasing adds about one weight to font rendering, its a known bug on Apple platforms. Apple is aware of it, considers it a feature, and won't fix.

Eventually the command line fixes won't work either.


You do raise an interesting point about anti-aliasing adding to weights creating an "equivalent weight" of sorts to the font.

Thanks for mentioning this, it's made me think differently about font rasterization.


Some people are passionate about fonts. I think I am the opposite, I override all custom styles with a single font family and a very limited range of sizes. I can just hear designers crying out, but long ago I started doing to that, the web looks so much better when that design decision is eliminated. Even good use of fonts unnecessary.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: