Instantly share code, notes, and snippets.

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

Font Face

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


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");


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;

This comment has been minimized.

WhiteBeetle 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?


This comment has been minimized.

Leaderproxima commented Oct 16, 2015


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?


This comment has been minimized.

inseldesign commented Dec 13, 2015

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


This comment has been minimized.

DerExilant 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 "{")


This comment has been minimized.

anup04sust 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


This comment has been minimized.

mamsoudi commented Mar 18, 2016

Thank you for the mixin! Works perfectly!


This comment has been minimized.

fabiowitt commented Mar 30, 2016

Nice job!


This comment has been minimized.

sjdeere 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


This comment has been minimized.

obcidio commented Apr 12, 2016


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).


This comment has been minimized.

vishalPGit commented Jun 9, 2016

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


This comment has been minimized.

surayashivji 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?


This comment has been minimized.

vovan4 commented Oct 3, 2016

=font-face($font-family, $file-path, $font-weight: normal, $font-style: normal)
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:
@media screen and (-webkit-min-device-pixel-ratio: 0)
font-family: $font-family
src: url('#{$file-path}.svg##{$font-family}') format('svg')


This comment has been minimized.

edkf commented Jan 27, 2017

Helpful. Thanks!


This comment has been minimized.

rahulraguvanshi commented Feb 28, 2017

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


This comment has been minimized.

Titoratus 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!


This comment has been minimized.

mattmartini 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);


This comment has been minimized.

elliottmangham commented Aug 22, 2018

Anyone managed to rewrite this in PostCSS?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment