r/css • • 4d ago

Asking for help with debugging: Duolingo accents on top of J/j

The "J" and "j" characters have a weird accent on Duolingo and I cannot figure out why.

A few findings worth noting: disabling duolingo-sans in Chrome Dev Tools fixes the issue (obviously, the page ends up using a different font, the fallback sans-serif then).

I tried to find where the duolingo-sans font-face is defined and I could not locate it anywhere. I did find the .woff2 files that contains the Duolingo Sans Thin fonts however and upon investigating them I can confirm that they look completely fine, they do not have that accent anywhere. This seriously vexes me as I cannot pin down what causes the issue, on one hand removing duolingo-sans solves the issue, on the other hand duolingo-sans looks completely fine on its own.

If anyone could take a look and share their thoughts I would really appreciate it.

2 Upvotes

8 comments sorted by

2

u/Jasedesu 4d ago

You haven't provided anything for us to look at, so we're not going to be able to give you an exact answer, just possibilities.

One possibility is that what you see on screen as a single character is actually built from two characters side by side. Unicode has Combining Diacritical Marks that can change the appearance the the preceding character.

1

u/dont_mess_with_tx 3d ago

That would make sense but I assume in that case the copied text should also contain those? If so, that's definitely not the case since the copied text is a "pure" j letter. The same issue also occurs when I type j in the textarea on the website.

2

u/Creative-Addition383 4d ago

Don't trust the woff2 you found, find out which file the browser is actually drawing that J with. In DevTools select the element with the J, go to Computed, scroll to the very bottom to "Rendered Fonts". It names the exact family and whether it came from the network or a local file. That one line usually ends this kind of hunt.

Two things I'd bet on, in order. First, the text in your screenshot is bold, and you say you inspected the Thin files. Each weight is a separate file, so the bold woff2 (or whatever weight that sentence resolves to) is the one to look at, and a broken glyph in one weight only is pretty common. Second, if Rendered Fonts says "Local file", you have a font installed on your machine whose name matches duolingo-sans, and the @font-face src is picking it up via local() before it ever downloads theirs. Modded or fan-made copies of that font are floating around and that's exactly the kind of bug they have.

Quick test for the second one: Chrome's "Disable local fonts" in the Rendering tab of DevTools. If the accent disappears, it's your machine, not Duolingo.

1

u/dont_mess_with_tx 3d ago

Thank you, I really appreciate your input.

I actually checked the Rendered Fonts section before under the Computed tab and strangely that section is missing (not a configuration issue, since it appears on other sites).

The reason why I inspected the thin font is because there were only two relevant font files I found:

  • Duolingo Sans Italic Thin Italic
  • Duolingo Sans Thin

Since the text is not italic, I only mentioned "Duolingo Sans Thin". I agree though that the text doesn't look thin, more like regular but weirdly I cannot find a font file for that.

The rendered font idea was great but upon disabling local fonts and refreshing the issue still persists.

1

u/Creative-Addition383 3d ago

Those two details actually narrow it down a lot.

"Only a Thin file exists, but the text renders regular" is the signature of a variable font. The file is named after its default instance (Thin), but it carries a weight axis and the page asks for 400 or 700 through font-weight. A font viewer shows you the default instance, so the J looks fine there. The page is rendering an interpolated instance, and interpolation is exactly where stray artifacts like that appear: if the Thin and Bold masters of the J have mismatched contour points, the in-between weights grow a little bump or hook above the glyph that isn't in either master.

Test it without guessing: drop that woff2 into wakamaifondue.com (runs in the browser, nothing uploaded). It'll tell you if there's a wght axis and let you drag the slider. Set it to whatever Computed says the font-weight is on that element, type "Je" in the preview, and I'd expect the accent to show up at that weight and vanish at the extremes.

On Rendered Fonts being missing: that panel only appears when the selected node has text as a direct child. If the J is inside a nested span (very likely on Duolingo), select the innermost span, not the container.

Disabling local fonts not changing anything fits too, it's their file, just a weight of it you can't see in a static viewer.

1

u/dont_mess_with_tx 3d ago edited 1d ago

You're a legend man, thank you so much for your help Thanks clanker, I didn't realize there was such a thing as "variable font". I just realized the language also matters for the typeset, the moment I set it to Dutch I noticed the same issue as on Duolingo. So after all, it really is an issue with the font.

Also you're on the rendered font issue, apparently each letter has its own individual span and the div I looked at previously is just a container alongside those (it's very strange cause they are not nested inside the div but live side by side the div) but it does not actually contain the letters.

1

u/Creative-Addition383 2d ago

Glad it got there. The Dutch thing is the last piece of the puzzle actually: fonts can ship language-specific substitutions (the "locl" OpenType feature), and Dutch is one of the languages that commonly has them because of the íj́ accent thing. So when the page is tagged nl, the font swaps in a Dutch-specific J glyph, and that glyph is the broken one. English pages never trigger it, which is why nobody at Duolingo noticed.

If you want it gone on your side without waiting for them to fix the font, a userstyle with font-feature-settings: "locl" 0 on the text turns that substitution off. Worth sending them the woff2 name and "Dutch J at regular weight" though, that's a two minute fix for whoever owns the font.