Ah yes, I suppose it wouldn’t be, as the sidebar is not a child of the div#text
We should probably try to think of a clever way to minimize the language CSS to make using the right font as easy as possible. I think it would be beneficial to lower the specificity of the rules, getting rid of #text and other context selectors wherever possible, and using something a lot like this as a starting point:
main {
/* Default font for contents of page (<main> excludes header and footer) */
font-family: 'Skolar Sutta Web'
}
/* Language Fonts */
[lang=my] {
font-family: 'Noto Sans Myanmar'
}
[lang=th] {
font-family: 'Lumen Thai'
}
…
[lang=en] {
/* En is default, so this rule is for en text embedded in another language */
font-family: 'Skolar Sutta Web'
}
Ideally, wherever possible, it should be possible to override the font for some text as easily as putting <span lang="en">
which means having very low specificity in the first place so overriding is easy.
Incidentally what’s the difference between [lang=my]
and :lang(my)
? If you use it on my/dn1 as a standalone selector [lang=my]
will select 1 element (the div#text) while :lang(my)
will select 566 elements (the div#text and every single one of it’s descendants). The pseudo-element selector certainly has it’s uses, in this specific context I think the attribute selector matches intention better - to set the font properties on one high level element and have those properties be inherited by descendants, rather than setting the property on every element.
Something else to consider would be using a class like .latin-script
as something more generic than [lang=en]
and more explicit than having latin as the implicit default. The .latin-script
class would be added selectively at the template level based on the language iso code, and a rule like this could be used:
.latin-script {
h1,h2,h3,h4,h5,h6 {
@include serif-small-caps;
}
}
Then if a language like th
is used, the latin script class is not added, and the simple [lang=th]
rule is applied everywhere with no need for complex overrides to revert the smallcaps rule. In other words, the rule is applied only where it is applicable, ideally only where it is definitely applicable.
A rethink of how fonts are applied, with dramatic simplification, would tie in well with using a font loader to avoid FOUT. Due to the horrible horrible limitations of browsers, font loaders need to do some pretty funky tricks to determine when a font has actually been loaded, and the long and the short of it is you end up having to implicitly specify in CSS what fonts to use.
The Web Font Loader sets classes on the <html>
element for when all fonts are loaded (or failed) and specific fonts loaded (or failed)
.wf-loading
.wf-active
.wf-inactive
.wf-<familyname>-<fvd>-loading
.wf-<familyname>-<fvd>-active
.wf-<familyname>-<fvd>-inactive
So you would then set some rules like this:
/* Hide page contents while fonts are loading */
.wf-loading main {
visibility: hidden;
}
/* Yay! Font goodness! */
.wf-active {
main {
font-family: 'Skolar Sutta Web';
}
[lang=my] {
font-family: 'Noto Sans Myanmar';
}
[lang=th] {
font-family: 'Lumen Thai';
}
…
}
.wf-inactive {
main {
/* let the browser choose fonts */
font-family: 'serif';
}
}
You could also set rules for specific fonts, like .wf-skolar_sutta_web-n4-loading
, which would mainly be useful for if some fonts might fail to download, because they are really big or something. wf-active only gets set once every font has finished loading which normally is what you want, but you might want some elements of the page to be able to render before every font is loaded (the header is an example).
Web Font Loader gives you a lot of control but you need to be quite explicit, you tell it exactly what fonts you want loaded for the page instead of relying on the built in logic of @font-face to decide what fonts to load.
The level of explicitness does mean it can lead to blow-out of rules so if we were to use Web Font Loader, we would also want to simplify the font style rules in general, which ties in well with my suggestions earlier in this post.
Note that it is possible to both use the Web Font Loader and have font-face fonts work even without it (i.e. on a device with javascript disabled), in this usage Web Font Loader isn’t responsible for loading the fonts and simply monitors the loading progress and you can use .wf-loading to avoid FOUT and .wf-inactive to provide explicit fallbacks if loading took too long. In this usage avoiding FOUT is easy, all you actually need is a rule like this:
.wf-loading #text {visibility: hidden}
However providing fallbacks is not any simpler in this usage as you’d still need a heap of rules for .wf-inactive.
If we were to go with a Web Font Loader, we would want to have a separate manifest file (probably JSON) mapping language codes to font families. If a language only uses default fonts (i.e. Skolar) it would not need an entry. If we wanted to use something like the .latin-script idea, then this file could also define things like that.