Let’s take the code below:
$basicFont: 'dancing-script';
$chineseFont: 'Noto Sans Simplified Chinese';
h1, h2, h3 {
font-family: $basicFont;
html:lang(zh) & {
font-family: $chineseFont;
}
}
.box {
padding: 10px;
font-family: $basicFont;
html:lang(zh) & {
font-family: $chineseFont;
}
}
We have our websites in 2 languages(english and chinese) and we want to have the chinese version with a different font that is more fit to the job. So we add on each CSS rule with font-family $langFont, also a conditional selector html:lang(zh) &, meaning all selectors that’s parent has the language set to chinese should have the @langChineseFont applied as font-family. The problem becomes visible when we realize that we need to do this in 50+ selectors.
The first code optimization that comes into my mind is to place basic font and the conditional chinese font in a mixin and then just call the mixin each time in our selectors. Mixin is especially ok if you have more then 2 languages on your website or you have different sections in different languages.
$basicFont: 'dancing-script';
$chineseFont: 'Noto Sans Simplified Chinese';
$spanishFont: 'Acre Medium';
@mixin fontFamily {
font-family: $basicFont;
:lang(zh) & {
font-family: $chineseFont;
}
:lang(es) & {
font-family: $spanishFont;
}
}
h1,h2,h3 {
@include fontFamily;
}
.box {
padding: 10px;
@include fontFamily;
}
If you take a look at the parsed CSS originated from our SCSS code the result seems like an overhead:
h1, h2, h3 {
font-family: 'dancing-script';
}
:lang(zh) h1, :lang(zh) h2, :lang(zh) h3 {
font-family: 'Noto Sans Simplified Chinese';
}
:lang(es) h1, :lang(es) h2, :lang(es) h3 {
font-family: 'Acre Medium';
}
.box {
padding: 10px;
font-family: 'dancing-script';
}
:lang(zh) .box {
font-family: 'Noto Sans Simplified Chinese';
}
:lang(es) .box {
font-family: 'Acre Medium';
}
Instead of all this crazyness, we should have one variable with the default font value and if one of the conditions are met (:lang(zh) or :lang(es)) then that default value should be changed. This reassignment of a global variable can be done with the !global flag:
$baseFont: 'dancing-script';
$chineseFont: 'Noto Sans Simplified Chinese';
$spanishFont: 'Acre Medium';
html:lang(zh) {
$baseFont: $chineseFont !global;
}
html:lang(es) {
$baseFont: $spanishFont !global;
}
h1,h2,h3 {
font-family: $baseFont;
}
.box {
padding: 10px;
font-family: $baseFont;
}
We actually used the power of CSS “filtering”, by checking if the html tag has an attribute of lang with the value “zh” or “es” and based on that we changed the value of a global variable. It’s almost like an if-else conditioning. The code looks much cleaner now.
In case you still would like to change locally the $baseFont value you can always reassign the value to the $basefont variable omitting the !global flag;
.box {
$baseFont: Arial, Verdana;
padding: 10px;
font-family: $baseFont;
}