Skip to content

Tailwind CSS font size, weight and family: every class in v4

Published 8 min read

On this page

In Tailwind CSS v4 you set font size with text-* (from text-xs at 12px to text-9xl at 128px), font weight with font-* (from font-thin at 100 to font-black at 900) and font family with font-sans, font-serif and font-mono. This page lists every default class with its real value, shows how line height pairs with each size, and explains how to change the scale and add your own fonts in v4's CSS-first config.

All values below come from the theme.css file that ships with Tailwind CSS 4.3, so you can copy them with confidence.

Font size classes#

Every text-* size class sets two things: font-size and a matching default line-height. Sizes are in rem, so the px values below assume the browser default root size of 16px.

ClassFont sizeDefault line height
text-xs0.75rem (12px)1rem (16px), ratio 1.333
text-sm0.875rem (14px)1.25rem (20px), ratio 1.429
text-base1rem (16px)1.5rem (24px), ratio 1.5
text-lg1.125rem (18px)1.75rem (28px), ratio 1.556
text-xl1.25rem (20px)1.75rem (28px), ratio 1.4
text-2xl1.5rem (24px)2rem (32px), ratio 1.333
text-3xl1.875rem (30px)2.25rem (36px), ratio 1.2
text-4xl2.25rem (36px)2.5rem (40px), ratio 1.111
text-5xl3rem (48px)1
text-6xl3.75rem (60px)1
text-7xl4.5rem (72px)1
text-8xl6rem (96px)1
text-9xl8rem (128px)1

In v4 the line heights are stored as unitless ratios, for example --text-sm--line-height: calc(1.25 / 0.875). That works out to the same 20px as before, but it scales with the font size if you override it. From text-5xl up the line height is 1, which is tight on purpose: large headings look loose with body-text leading.

So what does text-base mean? It is the base body size: 1rem with a 1.5 line height. It is also what you get when you set no size at all, because browsers default to 16px.

Set line height in the same class

You can override the default line height with a slash modifier. The number after the slash is a spacing step (each step is 0.25rem), a named leading value or an arbitrary value:

<p class="text-sm/6">14px text, 24px line height</p>
<p class="text-lg/7">18px text, 28px line height</p>
<p class="text-base/[1.6]">16px text, 1.6 line height</p>
<h2 class="text-3xl/tight">30px text, 1.25 line height</h2>
<p class="text-sm/none">line height 1</p>

The separate leading-* classes still work and win over the size's default line height. The named ones are:

ClassLine height
leading-none1
leading-tight1.25
leading-snug1.375
leading-normal1.5
leading-relaxed1.625
leading-loose2

Numeric classes such as leading-6 or leading-7 use the spacing scale, so leading-7 is 1.75rem.

Arbitrary font sizes

When the scale doesn't have the size you need, use square brackets:

<p class="text-[17px]">...</p>
<p class="text-[1.0625rem]/7">...</p>
<p class="text-(length:--article-size)">...</p>

Two things to know. An arbitrary size sets only font-size, not a line height, so add one with the slash modifier or a leading-* class. And text-[...] is also the color utility, so when you pass a CSS variable, use the parentheses shorthand with a length: hint, as in text-(length:--article-size). Without the hint Tailwind treats the variable as a color.

If you use the same arbitrary value more than twice, it belongs in your theme. More on that below.

Responsive font sizes

Prefix a size with a breakpoint to change it from that width up. Tailwind is mobile first, so the class without a prefix is the small-screen size:

<h1 class="text-3xl md:text-5xl lg:text-6xl font-bold">Page title</h1>
<p class="text-base/7 md:text-lg/8">Intro paragraph</p>

The default breakpoints are sm (40rem, 640px), md (48rem, 768px), lg (64rem, 1024px), xl (80rem, 1280px) and 2xl (96rem, 1536px).

Fluid font sizes with clamp()

Instead of jumping between sizes at breakpoints, you can let a heading grow with the viewport. Pass a clamp() as an arbitrary value. Commas need no escaping, but you can't use spaces inside the brackets:

<h1 class="text-[clamp(2rem,1.5rem+2.5vw,3.5rem)]/[1.1]">...</h1>

That's hard to read in markup, so for anything you reuse, put the clamp in your theme as a named size (see customizing the scale). Keep a rem part in the middle value (1.5rem + 2.5vw) so text still responds to the user's browser zoom.

Font weight classes#

ClassFont weight
font-thin100
font-extralight200
font-light300
font-normal400
font-medium500
font-semibold600
font-bold700
font-extrabold800
font-black900

A weight class only looks different if the font has that weight. If you load Inter with just 400 and 700, then font-medium renders as 400 and font-semibold as 700 (or the browser fakes a bold). The system font stack that Tailwind uses by default has most weights on macOS and Windows, but a web font has exactly what you load.

Variable fonts and arbitrary weights

With a variable font you get every weight in its range, so in-between values are useful. Use an arbitrary value:

<h2 class="font-[650]">Slightly heavier than semibold</h2>
<p class="font-[450]">Body text a touch darker than normal</p>

Or add a named weight to your theme so you can write font-heading:

@theme {
  --font-weight-heading: 650;
}

Variable fonts often have a width axis too. Tailwind v4 has font-stretch-* classes for that, from font-stretch-ultra-condensed to font-stretch-ultra-expanded, plus percentages between 50% and 200% such as font-stretch-75%.

Font family classes#

Tailwind has three font families out of the box. These are the exact stacks in Tailwind 4.3:

ClassFont stack
font-sans-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', 'Noto Sans', Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'
font-serifui-serif, Georgia, Cambria, 'Times New Roman', Times, serif
font-monoui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace

You don't need to put font-sans on your body. Tailwind's base styles already apply --font-sans to html, and code, pre and kbd get --font-mono.

Add a custom font in v4

In v4 a font family is a theme variable in the --font-* namespace. Define one and the class exists:

@import "tailwindcss";

@theme {
  --font-display: "Fraunces", ui-serif, Georgia, serif;
}

Now font-display sets font-family: var(--font-display). The theme variable only names the font. You still have to load the font file, in one of three ways.

Self-hosted with @font-face. Put the files in public/fonts/ and declare them at the top level of your CSS, outside @theme:

@font-face {
  font-family: "Fraunces";
  src: url("/fonts/fraunces-variable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

The range 100 900 tells the browser one variable file covers all weights. For static fonts, write one @font-face per weight.

Fontsource. Install the package and import it. Variable packages register the family with a "Variable" suffix:

npm install @fontsource-variable/inter
@import "tailwindcss";
@import "@fontsource-variable/inter";

@theme {
  --font-sans: "Inter Variable", ui-sans-serif, system-ui, sans-serif;
}

Google Fonts. Add the link in your HTML head and reference the family in @theme the same way:

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400..700&display=swap" rel="stylesheet">

Self-hosting is usually faster and avoids sending visitor IPs to Google, which matters for GDPR. Fontsource is self-hosting with less work.

Change the default sans font

Redefining --font-sans, as in the Fontsource example, changes font-sans and the default font of the whole page in one go, because the base styles read that variable. Always end the stack with fallbacks so text renders while the web font loads. To use a CSS variable that's not in your theme, use font-(family-name:--brand-font).

A body and heading setup that works#

Classes on every heading get repetitive. A small base layer sets sensible defaults, and you override them with classes where needed:

@import "tailwindcss";
@import "@fontsource-variable/inter";

@theme {
  --font-sans: "Inter Variable", ui-sans-serif, system-ui, sans-serif;
  --font-display: "Inter Variable", ui-sans-serif, system-ui, sans-serif;
}

@layer base {
  body {
    @apply text-base/7 text-gray-800 antialiased;
  }
  h1 {
    @apply font-display text-4xl/tight font-bold tracking-tight md:text-5xl/tight;
  }
  h2 {
    @apply font-display text-2xl/snug font-semibold tracking-tight md:text-3xl/snug;
  }
  h3 {
    @apply text-xl/snug font-semibold;
  }
}

A few choices here: body text gets a 28px line height (/7) for easier reading than the default 24px, headings get tighter leading, and large headings get tracking-tight (-0.025em) because big text looks spaced out at normal tracking. The tracking scale is tracking-tighter (-0.05em), tracking-tight (-0.025em), tracking-normal (0em), tracking-wide (0.025em), tracking-wider (0.05em) and tracking-widest (0.1em).

For long text from a CMS or Markdown, where you can't add classes, use the typography plugin's prose classes. I wrote about that, and about setting typographic defaults in general, in The best way to set typographic defaults in Tailwind CSS. That post is from the v2 days, so translate its config examples to @theme, but the approach still holds.

Customize the font size scale in v4#

In v4 the scale lives in CSS. Every --text-* variable in @theme becomes a text-* class, and optional sub-variables set its line height, letter spacing and weight.

Extend or override sizes

Add new sizes or change existing ones next to the defaults:

@theme {
  /* change a default */
  --text-base: 1.0625rem;
  --text-base--line-height: 1.65;

  /* add a new size */
  --text-hero: clamp(2.5rem, 1.75rem + 3.75vw, 4.5rem);
  --text-hero--line-height: 1.05;
  --text-hero--letter-spacing: -0.02em;
  --text-hero--font-weight: 700;
}

text-hero now sets size, line height, tracking and weight in one class. A leading-*, tracking-* or font-* class on the same element still overrides those defaults.

Replace the whole scale

To drop all default sizes and keep only your own, reset the namespace with --text-*: initial:

@theme {
  --text-*: initial;

  --text-sm: 0.875rem;
  --text-sm--line-height: 1.5;
  --text-base: 1rem;
  --text-base--line-height: 1.6;
  --text-lg: 1.25rem;
  --text-lg--line-height: 1.5;
  --text-xl: 1.5625rem;
  --text-xl--line-height: 1.3;
  --text-2xl: 1.953rem;
  --text-2xl--line-height: 1.2;
  --text-3xl: 2.441rem;
  --text-3xl--line-height: 1.1;
}

After this, text-xs or text-5xl no longer exist, which is useful for keeping a team on one scale. The example uses a 1.25 ratio (each step is 1.25 times the previous). Working that out by hand for every step is tedious, so I made a Tailwind font size generator that builds a modular scale from a base size and ratio and outputs the @theme block, line heights included.

The same in Tailwind v3

In v3 you did this in tailwind.config.js. A size can be a string or an array with options, and extend adds to the defaults while a key directly under theme replaces them:

// tailwind.config.js (v3)
const defaultTheme = require('tailwindcss/defaultTheme')

module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: ['Inter', ...defaultTheme.fontFamily.sans],
        display: ['Fraunces', ...defaultTheme.fontFamily.serif],
      },
      fontSize: {
        hero: ['4.5rem', { lineHeight: '1.05', letterSpacing: '-0.02em', fontWeight: '700' }],
      },
      fontWeight: {
        heading: '650',
      },
    },
  },
}

Moving such a config to v4 is mostly mechanical: fontSize.hero becomes --text-hero, fontFamily.display becomes --font-display and fontWeight.heading becomes --font-weight-heading. The classes you write in HTML stay the same. Our Tailwind config to v4 converter does it for you.

FAQ#

What is the default font size in Tailwind?

Tailwind doesn't set a root font size, so the page uses the browser default of 16px. text-base matches that: 1rem with a 1.5 line height (24px). If a user raises the browser's font size, all rem-based text-* classes scale with it.

How do I change the font family in Tailwind v4?

Load the font (with @font-face, Fontsource or a Google Fonts link) and set --font-sans in @theme to make it the default, or add a new variable such as --font-display to get a font-display class. There's no tailwind.config.js needed in v4.

Can I set font size and font weight in one class?

Not with the default sizes, but you can with your own. Give a size a --font-weight sub-variable in @theme, like --text-hero--font-weight: 700, and text-hero sets both. Otherwise combine two classes: text-2xl font-semibold.

Why does font-semibold look the same as font-bold?

Because the font you loaded doesn't include weight 600, so the browser picks the nearest weight it has. Load the missing weight, or switch to the variable version of the font, which covers the full range.

For the full reference, see the official docs on font-size, font-weight and font-family.

Build faster with Tailwind CSS

Admin themes, website templates and landing pages. Almost all of it free.

Browse the library