Typography and Fonts
|
This content was generated with the assistance of AI and should be verified against the official Webflow documentation before being relied on in production. This sub-section’s Webflow bibliography lists the reference material consulted while preparing these pages. |
This page was written against Webflow as it was on 2026-10-28, the date on which its facts were checked against the official documentation. Webflow is a hosted service without version numbers, so the Fonts tab and the Typography section may move between two visits; https://webflow.com/updates and the developer changelog announce changes. Uploading custom fonts, adding Google Fonts and setting type in the Style panel do not need a paid Site plan or Workspace plan, so every step on this page can be tried on a free Starter site. Connecting Adobe Fonts needs a paid plan and an Adobe account. The developer examples use the Data API v2 and registered fonts belong to one site.
Type is most of what a visitor reads, and it is also one of the heaviest and most privacy-sensitive parts of a page: every font file is a download, and some font services are third-party requests. This page covers how to set type in the Designer, how to build a scale that adapts to the screen, where the fonts come from, how to self-host them, and how to keep them light. The running example is the Fernbrook Gardens site, a fictitious botanical garden. Fernbrook wants a serif heading font for the garden’s name and articles, a sans-serif body font, and a type scale that reads well from a phone to a large monitor, without sending visitor data to a third party.
Where type is set
Typography in Webflow is ordinary CSS written through the Typography section of the Style panel. Four places matter, and the order below is the order in which they should be used.
| Place | What it controls |
|---|---|
Body (All Pages) |
The tag selector for the |
Tag selectors |
Rules for |
Classes |
Variations: a hero heading, a caption, a button label. A class overrides the tag selector for the elements that carry it. |
Variables |
Reusable values for font families and sizes that classes and tags refer to, so a change is made once. |
Classes and tag selectors are explained in Classes, Combo Classes and Selectors; variables in Variables and Modes.
Body defaults and inheritance
CSS properties for text are inherited: a value set on body flows down to every descendant that does not set its own. This is why the first typographic decision of a site is made on the Body (All Pages) selector rather than on each paragraph. A new blank Webflow site starts with a neutral default on body (a system sans-serif at a small size with a fixed line height), which is a placeholder to be replaced, not a design.
For Fernbrook, the Body selector gets a sans-serif font, a readable size and a unitless line height.
body {
font-family: "Source Sans 3", Arial, sans-serif;
font-size: 1rem;
line-height: 1.5;
font-weight: 400;
color: #2b3a2f;
}
Three habits make this baseline robust.
-
Use
remfor font sizes. Aremis relative to the root font size, which the visitor’s browser setting controls. Text sized in pixels ignores a visitor who has chosen a larger default size for accessibility. Webflow lets a size field takepx,rem,em,%,vwand other units, so converting is a matter of typing the unit. -
Use a unitless line height.
line-height: 1.5multiplies the element’s own font size, so a child with a larger font gets a proportionally larger line height. A fixed24pxline height inherited by a large heading makes the lines overlap. -
Trace inherited values. In the Style panel a label coloured orange means the value is set on the selected selector and breakpoint, and a different colour means it is inherited from a parent or from a larger breakpoint. Click the label to see where it comes from. When a paragraph has an unexpected size, this is the quickest way to find the rule responsible.
The box model and the way the Style panel writes each value are in Style Panel and Box Model; the CSS inheritance rules themselves are in Selectors and Specificity.
The Typography section
The Typography section of the Style panel writes these properties.
| Control | CSS written | Notes |
|---|---|---|
Font |
|
Lists the site’s Google, Adobe and custom fonts, then the system fonts. Choosing a family writes a comma-separated stack with fallbacks. |
Weight |
|
Shows the weights available for the chosen family. A custom font offers the weights that were uploaded. |
Size |
|
Any unit; prefer |
Height |
|
A number without a unit is allowed; |
Color |
|
A swatch, a colour variable or any colour value. |
Align |
|
Left, centre, right, justify. |
Style |
|
Normal or italic. |
Decoration |
|
None, underline, line-through, overline. |
Letter spacing |
|
Small positive values help all-caps labels; avoid negative values on small text. |
Indent |
|
First-line indentation. |
Transform |
|
Capitalise, uppercase, lowercase, none. |
Direction |
|
Left to right or right to left, relevant to localised sites. |
Columns |
|
Multi-column text for long passages. |
Text shadow, text stroke |
|
Decorative effects; check contrast. |
Breaking |
|
Controls wrapping and truncation. |
Setting the controls on the right selector matters more than the values. A heading that should always look the same everywhere belongs on the h2 tag selector; a one-off look belongs on a class. The Fernbrook article titles use one tag selector, and the home-page hero uses a class that overrides only the size.
h1, h2, h3 {
font-family: "Fraunces", Georgia, serif;
font-weight: 600;
line-height: 1.15;
margin-top: 0;
}
.heading-hero {
letter-spacing: -0.01em;
}
Text elements and their semantics (Heading, Paragraph, Text Block, Rich Text) are described in Elements and Page Structure. Choose the heading tag for the document outline, not for the size: a heading that must look smaller than its level still keeps its level and gets a class that changes the size.
A type scale with clamp()
A type scale is a short list of sizes (for example caption, body, lead, h3, h2, h1) in a consistent ratio. On the web the scale should also be fluid: a heading is large on a wide monitor and smaller on a phone. The older method is a size per breakpoint, which means one value on Desktop and overrides on Tablet and Mobile. The modern method is clamp(minimum, preferred, maximum), which lets the size grow with the viewport between two limits and needs no media queries.
:root {
--text-body: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
--text-h3: clamp(1.25rem, 1.1rem + 0.75vw, 1.625rem);
--text-h2: clamp(1.625rem, 1.3rem + 1.6vw, 2.5rem);
--text-h1: clamp(2rem, 1.4rem + 3vw, 3.75rem);
}
Source: MDN: clamp()
Reading --text-h1: the size is never smaller than 2rem, never larger than 3.75rem, and between those it follows 1.4rem plus 3vw. The limits are in rem so that the browser’s text-size setting still applies, and the preferred value mixes rem and vw so that zooming the page still enlarges the text. A value that uses only vw would ignore a visitor’s zoom, which is an accessibility failure.
In Webflow the scale is stored as variables, not typed on every class.
-
Open the Variables panel and create a variable collection called
Typeif the site has none. -
Add Size variables named
text-body,text-h3,text-h2andtext-h1. -
Set each one to a function value. Function variables accept
calc(),clamp(),min(),max()andcolor-mix(), so aclamp()can be entered in the variable’s value field; the current limits of that field are described in Variables and Modes. -
In the Style panel, click the size field, choose the variable, and set it on the tag selectors:
h1usestext-h1,h2usestext-h2, andbodyusestext-body.
Because the scale sits on tag selectors and is shared, the whole site changes at once when the numbers change, and the responsive overrides on narrow breakpoints disappear. The same method applies to spacing; Responsive Design and Breakpoints shows it combined with breakpoint modes for sizes that must differ by breakpoint, and the CSS mechanics are in Variables and Media Queries.
Two cautions apply. A clamp() that is stored in an Embed’s :root block (as in the listing above) is not visible in the Variables panel, so it cannot be chosen from the Style panel; prefer variables when the team works in the Designer. And fluid sizes should be checked at the extremes: set the canvas to the smallest and largest widths and read the result, because a preferred value that grows too fast makes a heading wrap badly on a tablet.
Fonts: where they come from
Webflow supports four sources for the families offered in the Font dropdown. All are managed in Site settings > Fonts; the Font dropdown in the Style panel has a shortcut that opens the same tab.
| Source | Strength | Caveat | Plan |
|---|---|---|---|
System fonts |
No download, instant rendering |
Appearance varies by device |
Any |
Google Fonts |
Large free library, simple to add |
Loaded from Google’s servers, with a privacy caveat |
Any |
Adobe Fonts |
The Adobe library, managed in an Adobe account |
Needs an Adobe subscription and a token; the licence is tied to that account |
Paid |
Custom fonts |
Any font whose licence allows web use; fully self-hosted |
Needs a web-use licence and well-chosen formats |
Any |
Google Fonts and the GDPR caveat
To add a Google font, open Site settings > Fonts, choose Google fonts, pick the family, its variants (weights and italics) and the languages or scripts, and click Add font. The family then appears in the Font dropdown. Choosing only the variants the design uses is the most effective optimisation of this route, and the section on loading only what is needed returns to it.
The privacy caveat is stated in Webflow’s own article: the integration uses the Google Fonts API, which sends the visitor’s IP address to Google’s servers, and that may not be compatible with the GDPR for visitors in the European Union. Courts and data-protection authorities in Europe have treated loading fonts from Google’s service without consent as a data-transfer problem, and the article recommends downloading the font files and uploading them as custom fonts instead. This is a technical measure and not legal advice; a site that serves European visitors should take the decision with its data-protection adviser.
The remedy takes three steps.
-
Download the font family from Google Fonts, or from the foundry, in WOFF2 or a format that can be converted to it. Check that the licence allows self-hosting; the fonts of the Google library are open-source licensed, which normally does.
-
Upload the files as custom fonts (next section), using the same family name and weights.
-
Remove the Google font from the site and search the Designer for classes and selectors that still use it, then publish. A leftover reference to the Google family, or a font whose custom name matches the Google family name, can keep the page contacting Google, so check the published page’s network panel for requests to Google’s font hosts.
Fernbrook serves a European audience, so it takes this route: both fonts are downloaded, uploaded as custom fonts under unique family names and the Google entries are removed.
Adobe Fonts
Adobe Fonts are connected with an API token. In Adobe Fonts, create a web project that contains the families wanted and generate a token. In Webflow, paste the token into Site settings > Fonts > Adobe fonts and save it, then choose the web project and save. The families of the project appear in the Font dropdown. The token can also be stored once for a whole Workspace under the Workspace settings Integrations tab, so that every site of the Workspace can use the same Adobe fonts. A paid plan is required.
Adobe Fonts are a licensed service. The licence follows the Adobe account, the fonts load from Adobe’s servers (the same privacy discussion as for Google Fonts applies), and they stop working if the subscription lapses or the site’s domain is not allowed in the project. They suit agencies that already license Adobe’s library; a site that must be fully self-hosted should use custom fonts.
Uploading custom fonts
Custom fonts are font files that the site owner uploads, and Webflow serves them from its own hosting, which is why this is the self-hosting route.
-
Open Site settings > Fonts and scroll to Custom fonts.
-
Click Upload and choose the files.
-
Webflow reads the family name and the weight from each file and lists them. Check and, if necessary, correct the family name, the weight (100 to 900) and whether the file is italic.
-
Save, then publish the site. The family appears in the Font dropdown of the Style panel.
The rules that matter:
-
Format. WOFF2 is the recommended format: it is compressed, supported by every current browser and the smallest of the web formats. Webflow also accepts WOFF, TTF and OTF; EOT and SVG fonts are not supported. A TTF or OTF can be converted to WOFF2 with a font tool before uploading.
-
Size. A single font file can be at most 4 MB.
-
One file per weight and style, unless the font is variable (next section). Fernbrook uploads Regular (400), Italic (400 italic) and Bold (700) of the body font, and two weights of the serif.
-
Names. Give each family a name that is unique on the site. A custom family named like a Google family, such as Montserrat, can make the published page keep loading the Google version; naming it
Montserrat Fernbrookavoids the conflict. -
Licence. A font bought for print or for an application is not automatically licensed for web embedding. Keep the licence with the project documentation.
Webflow writes an @font-face rule for every uploaded file into the published site’s stylesheet. The rule resembles the one below; the exact URL and the loading behaviour are chosen by Webflow.
@font-face {
font-family: "Fraunces Fernbrook";
src: url("https://cdn.prod.website-files.com/<site-id>/<file-id>_Fraunces-Regular.woff2") format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
font-display: swap shows text immediately in the fallback font and swaps in the custom font when it has loaded, which avoids invisible text; the trade-off is a brief change of letter shapes. The Designer has no switch for this value, but the Custom Fonts API (later in this page) takes a fontDisplay field when fonts are registered programmatically.
Fallback fonts matter just as much as the custom family. If the custom font is slow or fails, the browser uses the next family in the stack, so choose a fallback with similar proportions (Georgia for a serif, Arial or system-ui for a sans-serif) so that the text does not jump when the font arrives.
Variable fonts
A variable font is one file that contains a continuous range of a design: instead of separate files for Light, Regular and Bold, a single file describes the weight axis from 100 to 900, and sometimes also width, slant or optical size. Webflow supports variable fonts in TTF, OTF, WOFF and WOFF2. After a variable font is uploaded, the Typography section exposes its axes as controls for the selected element, and the weight field accepts any value in the supported range rather than a few steps.
@font-face {
font-family: "Fraunces Fernbrook";
src: url("<variable-font-url>.woff2") format("woff2");
font-weight: 100 900;
font-style: normal;
font-display: swap;
}
.heading-hero {
font-family: "Fraunces Fernbrook", Georgia, serif;
font-weight: 650;
font-variation-settings: "opsz" 72;
}
Whether a variable font is lighter than the static files depends on how many weights the site uses. A variable file that holds the whole weight range is usually larger than a single static weight but smaller than four or five static weights combined. For a site that uses two weights, two static WOFF2 files may be the smaller choice; for a design system with many weights, or one that animates weight on hover, a variable font is better. A variable font that was uploaded before Webflow supported variation axes should be deleted and uploaded again so that the axes appear.
Unused axes cost bytes. If a font family ships with width and slant axes that the design never uses, a subsetted file with only the weight axis is smaller, and font tools can produce it.
Font variables
Font families can be stored as Font type variables, one of the five variable types (Color, Size, Font, Number, Percentage). A font variable holds a family name, and the Typography section of the Style panel can be bound to it. The benefit is the same as for colours: a rebrand changes the variable once. Fernbrook defines two font variables.
:root {
--font-heading: "Fraunces Fernbrook", Georgia, serif;
--font-body: "Source Sans Fernbrook", Arial, sans-serif;
}
h1, h2, h3 { font-family: var(--font-heading); }
body { font-family: var(--font-body); }
Source: Webflow Help Center: Variables
A font variable can also be given different values in different modes, for example a heavier display family in a seasonal mode, and an element or a whole page can pick the mode (see Variables and Modes). Font variables work with the families the site already has: a family has to be added in Site settings > Fonts before it can be chosen in the variable.
When fonts must be shared between sites, a shared library carries fonts together with components, variables and assets inside one Workspace; the details are in Shared Libraries.
Loading only what is needed
Every weight and style is a separate request or a separate range in a file, so the common performance problem is a site that loads far more type than it shows. The book Webflow by Example makes the point clearly for Google Fonts, and the advice still holds: select only the weights the design uses. The practical rules are below.
-
Two families at most, one for headings and one for text, and three or four weights between them. Each additional weight is another file for the browser to fetch and another chance of a layout shift.
-
Audit before publishing. List every distinct family, weight and style used in the Style panel (the class list shows them) and delete the variants that no class uses. Remove unused custom fonts from the Fonts tab as well.
-
Subset when you can. A font file that contains Latin, Cyrillic, Greek and Vietnamese glyphs is larger than one that contains only the Latin range the site needs. Choose only the languages needed when adding a Google font, and subset custom files with a font tool, keeping the accents of the languages the site is written in. A localised site (see Localization) needs the glyphs of every locale.
-
Prefer WOFF2. The format is compressed and is the one Webflow recommends.
-
Test with the network panel. Open the published page with the browser’s developer tools, filter by Font and check the number of files, their sizes and their host. A request to a host other than the site’s own means a Google or Adobe font still in use.
-
Avoid text in images. Type that is part of an image cannot be selected, translated or enlarged and does not use the fonts at all; reserve it for logos.
More general loading and image advice is in Performance Optimization, and the platform-independent rules for fonts and loading are in Loading Performance.
The Custom Fonts API
Fonts can be registered from code. The Data API v2 has endpoints under /v2/sites/{site_id}/custom_fonts that register a font, upload its file and list or delete fonts. They suit an agency that moves a font set between many sites, or a migration script. The example registers one font; the response includes a presigned upload target.
POST https://api.webflow.com/v2/sites/<site-id>/custom_fonts
Authorization: Bearer <site-token>
Content-Type: application/json
{
"fileName": "Fraunces-Regular.woff2",
"fileHash": "<md5-hex-digest-of-the-file>",
"fontFamily": "Fraunces Fernbrook",
"weight": 400,
"italic": false,
"fontDisplay": "swap"
}
Source: Webflow Data API: Custom fonts
The call returns the registered customFont and an upload object with a url and a set of fields. The binary is sent to that URL as multipart/form-data with every returned field first and the file field last. Webflow’s API never receives the font itself.
curl -X POST "<upload-url>" \ -F "<field-name-1>=<field-value-1>" \ -F "<field-name-2>=<field-value-2>" \ -F "file=@Fraunces-Regular.woff2"
Source: Webflow Data API: Custom fonts
The facts to remember:
-
A registration answers with status 202; the upload to the presigned URL answers with 201, and the URL expires after about 15 minutes.
-
The endpoints are
POST /custom_fonts(one font),POST /custom_fonts/batchCreate(up to 25),POST /custom_fonts/batchDelete(up to 100 identifiers),GET /custom_fontsandGET /custom_fonts/{id}. -
The formats are WOFF2, WOFF, TTF, OTF and EOT; new SVG fonts are rejected. A file larger than 4 MB fails with
EntityTooLarge. -
A variable font can declare up to 16 axes in the optional
axesarray. -
A site has a limit on the number of fonts. Exceeding it answers
409 Conflict, and in a batch the extra fonts are returned in afailedlist while the others are registered.
Authentication, scopes and error handling are the same as for the rest of the Data API; see Data API Authentication and Scopes and Data API: Assets, Forms and Custom Code. Keep tokens out of scripts and repositories; the placeholders above show where a token goes.
Checklist for the Fernbrook Gardens site
-
Choose two families and verify that their licences allow web embedding and self-hosting.
-
Download WOFF2 files, or convert them, and subset them to the needed languages.
-
Upload them in Site settings > Fonts > Custom fonts with unique family names, correct weights and italics.
-
Remove any Google or Adobe fonts that remain, and search for classes that still use them.
-
Set
bodyto the body family with aremsize and a unitless line height. -
Create the
Typevariable collection and set the heading and body sizes withclamp(). -
Bind the heading tags to the size variables and to the heading font variable.
-
Publish, open the page in a clean browser profile, and check in the network panel that fonts come from the site’s own host and that only the expected files load.
-
Check contrast and text enlargement with the Audit panel and a browser zoom to 200 percent (see Accessibility).
Common mistakes and pitfalls
-
Sizing everything in pixels. The text then ignores the visitor’s size preference. Use
rem, andclamp()limits inrem. -
Fluid sizes in
vwonly. They do not respond to zoom. Always add aremterm. -
A fixed line height on an inherited element. Use a unitless value.
-
Adding Google Fonts "for now". The first publish already sends visitor IPs to Google. Start with self-hosted files for European audiences.
-
Uploading every weight of a family. Each is a file the browser may download.
-
Reusing a Google family name for a custom upload. The published page may keep loading the Google file. Use a unique name.
-
Fallbacks that differ widely. A fallback with very different proportions makes the layout jump when the real font loads.
-
Treating a licence lightly. A font licence, not Webflow, decides whether a file may be embedded on a website.
Corrections to older tutorials
Ali Rushdan Tariq’s Webflow by Example (Packt, 2021) shows adding Google Fonts through the old project settings and recommends loading only the weights needed, which remains good advice. It does not mention the privacy issue of the Google Fonts API, so for European audiences the self-hosting route above should replace it. It also predates variable fonts, font variables and function variables, and it sets sizes in pixels per breakpoint where a clamp() scale needs far fewer overrides. Its vocabulary (a "project", Project Settings) is now a site and Site settings.