This mixin relies on a string replace utility function I took from CSS Tricks, modified for the latest Dart Sass specification. It looks like this:
@use 'sass:string';
@function str-replace($string, $search, $replace: '') {
$index: string.index($string, $search);
@if $index {
@return string.slice($string, 1, $index - 1) + $replace +
str-replace(
string.slice($string, $index + string.length($search)),
$search,
$replace
);
}
}
I find SCSS slightly easier to read and maintain than the equivalent indented syntax, so I’ll use it here.
@use 'sass:map';
// snip
$font-weights: (
400: 'Regular',
500: 'Medium',
600: 'Semibold',
700: 'Bold',
);
@mixin font-face($name, $weight: 400, $style: regular) {
$name-path: str-replace($name, ' ', '');
$style-path: if($style == 'italic', 'Italic', '');
$path: $name-path + '/' + $name-path + '-' + map.get($font-weights, $weight) +
$style-path;
@font-face {
font-family: $name;
src: url('/path/to/fonts/' + $path + '.woff2') format('woff2');
src: url('/path/to/fonts/' + $path + '.woff') format('woff');
font-weight: $weight;
font-style: $style;
}
}
My intent in the first place is to minimize the number of repetitive
parameters that I must input later when I declare specific fonts. As
such, I (kind of hackily) manipulate the font name into a valid path
according to some agreed-upon name scheme. If I import the font Commit
Mono, for instance, I would store in /path/to/fonts/
a subdirectory CommitMono/
with each file named CommitMono-WeightStyle.ext
. This
can be reconfigured. If, say, you would rather have a font folder
called commit_mono/
, you can perform a bit of string manipulation,
like this:
@use 'sass:string';
// snip
$path: string.to-lower-case(str-replace($name, ' ', '_')) + '/' +
str-replace($name, ' ', '') + map.get($font-weights, $weight) + $style-path;
// snip
We’re all set up. Now I can import fonts by writing something like the following:
@include font-face('Commit Mono'); // default args: ...400, regular
@include font-face('Commit Mono', 400, italic);
Or, if I have a font I need at every weight listed in $font-weights
in both regular and italic forms, I can use another SASS rule to
iterate through them:
@each $weight, $name in $font-weights {
@include font-face('EB Garamond', $weight);
@include font-face('EB Garamond', $weight, italic);
}