Skip to content

CSS3 Fonts

Using Custom Fonts on Your Website

Web fonts allow designers and developers to use fonts that are not pre-installed on the user’s computer, ensuring consistent typography across different devices.

The CSS @font-face rule lets you specify custom fonts to be downloaded along with your website assets.

Once you have legally obtained font files (e.g., from Google Fonts, Adobe Fonts, or purchased licenses), you host them on your server (or use a hosting service) and define them using @font-face.

The @font-face rule itself is supported by all modern browsers.

FeatureChromeEdgeFirefoxSafariOpera
@font-faceChrome 4+Edge 12+Firefox 3.5+Safari 3.2+Opera 10+

However, browser support varies for different font formats.

The most recommended format. Offers the best compression and performance. Based on TrueType (TTF) or OpenType (OTF).

The previous standard. Essentially a compressed version of TTF/OTF with metadata. Excellent fallback for older browsers that don’t support WOFF2.

Standard desktop font formats. Less compressed than WOFF/WOFF2, resulting in larger file sizes. Use as a fallback if necessary for very old browsers.

These are largely outdated for web font usage. EOT was specific to older Internet Explorer versions. SVG fonts have accessibility and performance issues and lack broad support. Avoid using these unless targeting extremely old browsers.

Focus on providing WOFF2 and WOFF for the best combination of modern support and compatibility.

Font FormatChromeEdgeFirefoxSafariOpera
WOFF2Chrome 36+Edge 14+Firefox 39+Safari 10+Opera 26+
WOFFChrome 5+Edge 12+Firefox 3.6+Safari 5.1+Opera 11.1+
TTF/OTFChrome 4+Edge 12+Firefox 3.5+Safari 3.1+Opera 10+

Note: Support for TTF/OTF might have licensing restrictions (‘installable’ setting) in older IE versions, but this is less relevant today.

Inside the @font-face rule, you define a custom name for your font using font-family and point to the font file(s) using the src descriptor. Provide multiple formats for broader compatibility, listing the preferred format (WOFF2) first.

Best Practice Tip: Always use lowercase for font URLs and ensure file paths are correct relative to your CSS file.

Example defining a custom font ‘MyCustomFont’:

@font-face {
font-family: 'MyCustomFont'; /* Name you'll use in CSS */
src:
/* Modern browsers */
url('fonts/mycustomfont-regular.woff2') format('woff2'),
/* Older browsers */
url('fonts/mycustomfont-regular.woff') format('woff');
/* Optional: Define weight and style if not standard */
font-weight: normal;
font-style: normal;
/* Optional: Improve loading performance */
font-display: swap;
}

To apply this font to an element, use the font-family name you defined:

body {
font-family: 'MyCustomFont', sans-serif; /* Fallback font */
}
h1 {
font-family: 'MyCustomFont', Georgia, serif;
}

font-display: swap; is highly recommended. It tells the browser to show a fallback font immediately while the custom font loads, preventing invisible text (FOIT - Flash of Invisible Text).

To use bold, italic, or other weights/styles of your custom font, you need separate font files for each variation and corresponding @font-face rules.

Define each variation with the same font-family name but specify the correct font-weight and font-style values within their respective @font-face rules.

@font-face {
font-family: 'MyCustomFont';
src:
url('fonts/mycustomfont-regular.woff2') format('woff2'),
url('fonts/mycustomfont-regular.woff') format('woff');
font-weight: 400; /* 400 is normal */
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'MyCustomFont';
src:
url('fonts/mycustomfont-bold.woff2') format('woff2'),
url('fonts/mycustomfont-bold.woff') format('woff');
font-weight: 700; /* 700 is bold */
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'MyCustomFont';
src:
url('fonts/mycustomfont-italic.woff2') format('woff2'),
url('fonts/mycustomfont-italic.woff') format('woff');
font-weight: 400; /* normal weight */
font-style: italic;
font-display: swap;
}

Now, when you apply font-weight: bold; or font-style: italic; to an element using ‘MyCustomFont’, the browser will automatically select the appropriate font file defined in the corresponding @font-face rule.

.some-element {
font-family: 'MyCustomFont', sans-serif;
font-weight: bold; /* Uses mycustomfont-bold.woff2/woff */
}
em {
font-family: 'MyCustomFont', sans-serif;
font-style: italic; /* Uses mycustomfont-italic.woff2/woff */
}

Key descriptors used within the @font-face rule:

DescriptorValuesDescription
font-familystringRequired. Defines the name you’ll use to refer to this font in your CSS.
srcurl() [format()] listRequired. Specifies the path(s) to the font file(s). Include format() hints (e.g., ‘woff2’, ‘woff’) for optimization.
font-weightnormal | bold | 100-900Optional. Specifies the weight this font file corresponds to. Default is normal (400).
font-stylenormal | italic | obliqueOptional. Specifies the style this font file corresponds to. Default is normal.
font-displayauto | block | swap | fallback | optionalOptional. Controls how the font is displayed while loading. swap is often recommended. Default is auto.
font-stretchnormal | condensed | expanded | …Optional. Specifies the stretch value (width variation) this font file corresponds to. Default is normal.
unicode-rangeOptional. Specifies the range of Unicode characters the font supports. Used for optimization, loading fonts only for specific character sets.

For comprehensive details: MDN @font-face Documentation