Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
SASS @font-face mixin

Font Face

A mixin for writing @font-face rules in SASS.

Usage

Create a font face rule. Embedded OpenType, WOFF2, WOFF, TrueType, and SVG files are automatically sourced.

@include font-face(Samplino, fonts/Samplino);

Rendered as CSS:

@font-face {
	font-family: "Samplino";
	src: url("fonts/Samplino.eot?") format("eot"),
		 url("fonts/Samplino.woff2") format("woff2"),
		 url("fonts/Samplino.woff") format("woff"),
		 url("fonts/Samplino.ttf") format("truetype"),
		 url("fonts/Samplino.svg#Samplino") format("svg");
}

Create a font face rule that applies to bold and italic text.

@include font-face("Samplina Neue", fonts/SamplinaNeue, bold, italic);

Rendered as CSS:

@font-face {
	font-family: "Samplina Neue";
	font-style: italic;
	font-weight: bold;
	src: url("fonts/SamplinaNeue.eot?") format("eot"),
	     url("fonts/SamplinaNeue.woff2") format("woff2"),
	     url("fonts/SamplinaNeue.woff") format("woff"),
	     url("fonts/SamplinaNeue.ttf") format("truetype"),
	     url("fonts/SamplinaNeue.svg#Samplina_Neue") format("svg");
}

Create a font face rule that only sources a WOFF.

@include font-face(Samplinoff, fonts/Samplinoff, null, null, woff);

Rendered as CSS:

@font-face {
	font-family: "Samplinoff";
	src: url("fonts/Samplinoff.woff") format("woff");
}

Create a font face rule that applies to 500 weight text and sources EOT, WOFF2, and WOFF.

@include font-face(Samplinal, fonts/Samplinal, 500, normal, eot woff2 woff);

Rendered as CSS:

@font-face {
	font-family: "Samplinal";
	font-style: normal;
	font-weight: 500;
	src: url("fonts/Samplinal.eot?") format("eot"),
	     url("fonts/Samplinal.woff2") format("woff2"),
	     url("fonts/Samplinal.woff") format("woff");
}

Notes

IE≥9 prioritizes valid font formats over invalid ones. Therefore, while embedded-opentype is the correct format for an .eot font, eot is used to fool modern IE into prioritizing other, newer font formats.

IE≤8 only supports .eot fonts and parses the src property incorrectly, interpreting everything between the first opening parenthesis ( and the last closing parenthesis ) as a single URL. Therefore, a ? is appended to the .eot’s URL, fooling older IE into reading all other sources as query parameters.

// =============================================================================
// String Replace
// =============================================================================
@function str-replace($string, $search, $replace: "") {
$index: str-index($string, $search);
@if $index {
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
@return $string;
}
// =============================================================================
// Font Face
// =============================================================================
@mixin font-face($name, $path, $weight: null, $style: null, $exts: eot woff2 woff ttf svg) {
$src: null;
$extmods: (
eot: "?",
svg: "#" + str-replace($name, " ", "_")
);
$formats: (
otf: "opentype",
ttf: "truetype"
);
@each $ext in $exts {
$extmod: if(map-has-key($extmods, $ext), $ext + map-get($extmods, $ext), $ext);
$format: if(map-has-key($formats, $ext), map-get($formats, $ext), $ext);
$src: append($src, url(quote($path + "." + $extmod)) format(quote($format)), comma);
}
@font-face {
font-family: quote($name);
font-style: $style;
font-weight: $weight;
src: $src;
}
}
@WhiteBeetle

This comment has been minimized.

Copy link

commented Jan 3, 2015

Hey, Djb... Love the heart. Gotta admit I'm catching up fast with my limited and geofenced redirected bogus app store apps and all the rest. Not bad eh? MKA- Mobility Kit for Android? Wag? Windows Android Grant? We are Global? What about Grant?

@Leaderproxima

This comment has been minimized.

Copy link

commented Oct 16, 2015

Hi,

I'm trying to use this mixin on my stylesheet but i've encountered an issue. When choosing a font that is in a higher directory (eg. one folder up) then it encounters an issue at compile.

What I want it to display:

@font-face {
  font-family: "SoftElegance";
  src: url("../fonts/SoftElegance.ttf") format("truetype"); }

The "../" breaks the mixin and doesn't allow it to compile. Anyway to include the ability to use parent directories instead of having to have the fonts folder inside my css folder?

@inseldesign

This comment has been minimized.

Copy link

commented Dec 13, 2015

It works for me with @include font-face(Samplino, "../fonts/Samplino");

@DerExilant

This comment has been minimized.

Copy link

commented Jan 25, 2016

I do also have a problem with the code. It says:
Invalid CSS after "... $replace: "") ": expected expression (e.g. 1px, bold), was "{")

@anup04sust

This comment has been minimized.

Copy link

commented Feb 12, 2016

I do also have a problem with the code. It says
Syntax error: Invalid CSS after " eot": expected ")", was ": "?","
on line 23 of []/scss/mixin/_fontface.scss

@mamsoudi

This comment has been minimized.

Copy link

commented Mar 18, 2016

Thank you for the mixin! Works perfectly!

@fabiowitt

This comment has been minimized.

Copy link

commented Mar 30, 2016

Nice job!

@sjdeere

This comment has been minimized.

Copy link

commented Apr 12, 2016

what if there is no woff2
@include font-face("name", "https://cdn.domain/fonts/fontname_LT_4_, 400", normal, eot woff ttf svg);

i look at the output and woff2 is also output

@obcidio

This comment has been minimized.

Copy link

commented Apr 12, 2016

Beautiful.

For anyone else's info, place your paths in quotes and as another variable. Also, remember the path is relative to the final destination of the output css file(s).

@vishalPGit

This comment has been minimized.

Copy link

commented Jun 9, 2016

Use @include font-face(Samplino, "../fonts/Samplino") instead of @include font-face(Samplino, ../fonts/Samplino) and its working for me.
Thanks

@surayashivji

This comment has been minimized.

Copy link

commented Sep 4, 2016

If we create this as an @function instead of an @mixin to create font variables, is it syntactically correct to say

@return @font-face {
font-family : quote($name); // add quotes to name string
font-style: $style;
font-weight: $weight;
src: $src;
}

also, does the mixin's name, font-face have anything to do with setting the font-face's values at the end of the mixin?

@vovan4

This comment has been minimized.

Copy link

commented Oct 3, 2016

=font-face($font-family, $file-path, $font-weight: normal, $font-style: normal)
@font-face
font-family: $font-family
src: url('#{$file-path}.eot')
src: url('#{$file-path}.eot?#iefix') format('embedded-opentype'), url('#{$file-path}.woff2') format('woff2'), url('#{$file-path}.woff') format('woff'), url('#{$file-path}.ttf') format('truetype'), url('#{$file-path}.svg##{$font-family}') format('svg')
font-weight: $font-weight
font-style: $font-style

// Chrome for Windows rendering fix: http://www.adtrak.co.uk/blog/font-face-chrome-rendering/
@media screen and (-webkit-min-device-pixel-ratio: 0)
@font-face
font-family: $font-family
src: url('#{$file-path}.svg##{$font-family}') format('svg')

@edkf

This comment has been minimized.

Copy link

commented Jan 27, 2017

Helpful. Thanks!

@rahulraguvanshi

This comment has been minimized.

Copy link

commented Feb 28, 2017

I used @include font-face("Font-Name", ../fonts/Font-Name, null);
Error: Invalid CSS after "fontname": expected expression

@Titoratus

This comment has been minimized.

Copy link

commented May 22, 2017

It works fine! Just DO NOT create .sass file, but .scss. Click "Download ZIP", import _mixins.scss into your folder, include it in main .sass file (@import '_mixins.scss' or @import 'mixins.scss' [it's no difference]). Then include your fonts.
For me it's not working — @include font-face(RobotoCondensed, fonts/RobotoCondensed);
But it works — @include font-face(RobotoCondensed, "../fonts/RobotoCondensed/RobotoCondensed", null, null, ttf woff woff2);
Notice that ttf has to be first!

@mattmartini

This comment has been minimized.

Copy link

commented Jun 8, 2017

To make this work with asset pipeline in Rails 4.2 I changed url to font-url.

$src: append($src, font-url(quote($path + "." + $extmod)) format(quote($format)), comma);

@elliottmangham

This comment has been minimized.

Copy link

commented Aug 22, 2018

Anyone managed to rewrite this in PostCSS?

@zeroedprgrammer

This comment has been minimized.

Copy link

commented Jan 23, 2019

Hi, the following worked for me:
(.sass)

@font-face
font-family: 'Roboto'
src: url('./utils/roboto/roboto_regular.woff') format('woff')
body
font-family: Roboto

@nickimola

This comment has been minimized.

Copy link

commented Jul 9, 2019

Hi, just as a suggestion (which I've included in the mixin I downloaded):
It would be nice to include font-display: swap so that while the fonts are loading the browser falls back to the defaults.
On mine, I have done it this way:

@font-face { font-family: quote($name); font-style: $style; font-weight: $weight; font-display: swap; src: $src; }

The font-display property is suggested by google here: https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/webfont-optimization#the_font_display_timeline and you have probably seen it on google dev tool audits as well.

@Amathos

This comment has been minimized.

Copy link

commented Sep 30, 2019

What if you need to use two fonts?

@nickimola

This comment has been minimized.

Copy link

commented Sep 30, 2019

What if you need to use two fonts?

This is what i did
@include font-face(One, fonts/one);
@include font-face(Two, fonts/two);

@odyright

This comment has been minimized.

Copy link

commented Oct 8, 2019

hello what if we need to use two/multi differents weight for a single font?

@odyright

This comment has been minimized.

Copy link

commented Oct 8, 2019

Hi, just as a suggestion (which I've included in the mixin I downloaded):
It would be nice to include font-display: swap so that while the fonts are loading the browser falls back to the defaults.
On mine, I have done it this way:

@font-face { font-family: quote($name); font-style: $style; font-weight: $weight; font-display: swap; src: $src; }

The font-display property is suggested by google here: https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/webfont-optimization#the_font_display_timeline and you have probably seen it on google dev tool audits as well.

can i have your file?

@nickimola

This comment has been minimized.

Copy link

commented Oct 8, 2019

Hi, just as a suggestion (which I've included in the mixin I downloaded):
It would be nice to include font-display: swap so that while the fonts are loading the browser falls back to the defaults.
On mine, I have done it this way:
@font-face { font-family: quote($name); font-style: $style; font-weight: $weight; font-display: swap; src: $src; }
The font-display property is suggested by google here: https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/webfont-optimization#the_font_display_timeline and you have probably seen it on google dev tool audits as well.

can i have your file?

Sure


@function str-replace($string, $search, $replace: "") {
	$index: str-index($string, $search);

	@if $index {
		@return str-slice($string, 1, $index - 1) + $replace +
			str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
	}

	@return $string;
}


@mixin font-face($name, $path, $weight: null, $style: null, $exts: eot woff2 woff ttf svg) {
	$src: null;

	$extmods: (
		eot: "?",
		svg: "#" + str-replace($name, " ", "_")
	);

	$formats: (
		otf: "opentype",
		ttf: "truetype"
	);

	@each $ext in $exts {
		$extmod: if(map-has-key($extmods, $ext), $ext + map-get($extmods, $ext), $ext);
		$format: if(map-has-key($formats, $ext), map-get($formats, $ext), $ext);
		$src: append($src, url(quote($path + "." + $extmod)) format(quote($format)), comma);
	}

	@font-face {
		font-family: quote($name);
		font-style: $style;
		font-weight: $weight;
		font-display: swap;
		src: $src;
	}
}

it's the same, i've just added font-display: swap and nothing more than that.

@odyright

This comment has been minimized.

Copy link

commented Oct 8, 2019

😄 thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.