All Posts

How to control font weight in Tailwind CSS

Font weight is one of those things you probably adjust all the time without thinking much about it. Making headings bolder. Lightening up some secondary text. It's part of creating visual hierarchy and guiding your users through content...

The great thing about Tailwind CSS is how simple it makes this. You get nine ready-to-use font weight utilities that cover pretty much every weight you'll ever need, from super thin to heavy black text. No more remembering numeric values or writing custom CSS classes.

I've been working with Tailwind for years and I still appreciate how quick it is to just add font-bold or font-light to an element. Let me show you exactly how these utilities work and how you can use them to make your typography stand out.

The nine font weight utilities

Tailwind gives you nine built-in classes for controlling font weight. Each one maps to a specific numeric value, just like in regular CSS.

Here's the complete list:

Class

CSS Value

When to Use It

font-thin

100

Very delicate text, large headings that need subtlety

font-extralight

200

Light decorative elements, oversized display text

font-light

300

Subheadings, captions, secondary content

font-normal

400

Body text, default reading content

font-medium

500

Slight emphasis without going bold

font-semibold

600

Subheadings that need more presence

font-bold

700

Headings, call-to-action text, important info

font-extrabold

800

Hero headings, major section titles

font-black

900

Maximum impact, display typography

Let me show you how these look in action:

<div class='space-y-4'>
  <p class='font-thin text-2xl text-gray-800'>This is font-thin (100)</p>
  <p class='font-extralight text-2xl text-gray-800'>This is font-extralight (200)</p>
  <p class='font-light text-2xl text-gray-800'>This is font-light (300)</p>
  <p class='font-normal text-2xl text-gray-800'>This is font-normal (400)</p>
  <p class='font-medium text-2xl text-gray-800'>This is font-medium (500)</p>
  <p class='font-semibold text-2xl text-gray-800'>This is font-semibold (600)</p>
  <p class='font-bold text-2xl text-gray-800'>This is font-bold (700)</p>
  <p class='font-extrabold text-2xl text-gray-800'>This is font-extrabold (800)</p>
  <p class='font-black text-2xl text-gray-800'>This is font-black (900)</p>
</div>

You can see the progression clearly. The difference between each weight creates that visual hierarchy I mentioned earlier.

One thing to keep in mind though - not every font includes all nine weights. If you're using a custom font that only has regular and bold, classes like font-thin or font-black might not render differently. The browser will do its best to fake the weight but it won't look as good as a font that actually includes those weights.

Here's a practical example showing how you might use different weights in a real card component:

<div class='max-w-sm mx-auto bg-white rounded-lg shadow-md p-6'>
  <span class='font-semibold text-sm text-blue-600 uppercase tracking-wide'>Featured</span>
  <h2 class='font-bold text-2xl text-gray-900 mt-2'>Pro Membership Plan</h2>
  <p class='font-normal text-gray-600 mt-3'>Get access to all premium features and priority support for your team.</p>
  <div class='mt-4'>
    <span class='font-black text-4xl text-gray-900'>$49</span>
    <span class='font-light text-gray-500'>/month</span>
  </div>
  <button class='mt-6 w-full bg-blue-600 text-white font-semibold py-3 rounded-lg hover:bg-blue-700'>
    Get Started
  </button>
</div>

See how each element uses a different weight to create clear distinction? The badge is semibold, the heading is bold, body text stays normal, the price goes black for impact, and the lighter "per month" text provides balance. That's the power of having all these options at your fingertips.

Going beyond the defaults with arbitrary values

Sometimes the nine standard weights aren't enough. Maybe you're working with a variable font that supports any weight from 100 to 1000, or you need a specific weight that falls between the defaults.

That's where Tailwind's arbitrary value syntax comes in handy.

You can use font-[value] to set any weight you want. Just put the numeric value in square brackets and Tailwind will generate the CSS for you on the fly.

<div class='space-y-4'>
  <p class='font-[350] text-2xl text-gray-800'>Custom weight of 350</p>
  <p class='font-[450] text-2xl text-gray-800'>Custom weight of 450</p>
  <p class='font-[550] text-2xl text-gray-800'>Custom weight of 550</p>
  <p class='font-[750] text-2xl text-gray-800'>Custom weight of 750</p>
  <p class='font-[950] text-2xl text-gray-800'>Custom weight of 950</p>
</div>

This is especially useful when you're working with variable fonts. These modern fonts can smoothly transition between any weight value, giving you way more control than traditional fonts.

You can also use CSS variables with the syntax font-(<custom-property>). Tailwind will automatically wrap it in the var() function for you:

<div class='space-y-4'>
  <p class='font-(--heading-weight) text-2xl text-gray-800' style='--heading-weight: 700;'>Uses CSS variable for heading weight</p>
  <p class='font-(--body-weight) text-lg text-gray-600' style='--body-weight: 400;'>Uses CSS variable for body weight</p>
</div>

This approach is perfect for design systems where you want to define weights once in CSS variables and reference them throughout your components. Change the variable value in one place and it updates everywhere.

Making weights responsive with breakpoints

One of the coolest things about Tailwind is how easy it is to adjust font weights at different screen sizes. Just add a breakpoint prefix and you're done.

The pattern is simple: {breakpoint}:font-{weight}.

This comes in handy all the time. Maybe you want bolder headings on desktop where there's more space, or lighter text on mobile to improve readability on small screens.

<div class='space-y-6'>
  <h1 class='font-normal md:font-bold lg:font-black text-4xl text-gray-900'>
    Responsive Heading Weight
  </h1>
  <p class='text-gray-600 text-sm'>
    This heading is normal weight on mobile, bold on tablets, and black on desktop screens.
  </p>

  <div class='bg-blue-50 p-6 rounded-lg'>
    <h2 class='font-light sm:font-medium md:font-semibold text-2xl text-gray-800 mb-3'>
      Feature Highlight
    </h2>
    <p class='font-normal text-gray-600'>
      Notice how the heading weight increases as the viewport gets larger, creating stronger visual hierarchy on bigger screens.
    </p>
  </div>
</div>

The responsive approach works great for mobile-first design. Start with lighter weights for small screens where space is limited, then progressively add more weight as screens get bigger.

Here's a real-world example of a hero section that adapts its typography:

<div class='bg-gradient-to-r from-blue-600 to-purple-600 p-8 md:p-12 lg:p-16 rounded-xl'>
  <h1 class='font-semibold md:font-bold lg:font-extrabold text-3xl md:text-5xl lg:text-6xl text-white mb-4'>
    Build Faster with Tailwind
  </h1>
  <p class='font-normal md:font-medium text-base md:text-lg text-white/90 max-w-2xl'>
    Create beautiful, responsive interfaces without leaving your HTML. No more context switching between files.
  </p>
  <button class='mt-6 font-medium md:font-semibold bg-white text-blue-600 px-6 py-3 rounded-lg hover:bg-blue-50'>
    Get Started Free
  </button>
</div>

See how everything scales up together? The heading gets progressively bolder, the description text gains more weight for better readability, and even the button becomes more prominent on larger screens. It all works together to create a cohesive experience across devices.

Adding interactivity with hover and focus states

Font weight isn't just for static text. You can combine it with Tailwind's state variants like hover:, focus:, and active: to create interactive typography that responds to user actions.

This technique works really well for links, buttons, navigation items, and anywhere you want to provide visual feedback when users interact with your content.

<div class='space-y-6'>
  <a href='#' class='block font-normal hover:font-semibold text-xl text-blue-600 transition-all duration-200'>
    Hover to see this link get bolder
  </a>

  <nav class='flex gap-6'>
    <a href='#' class='font-normal hover:font-bold text-gray-700 hover:text-blue-600 transition-all'>Home</a>
    <a href='#' class='font-normal hover:font-bold text-gray-700 hover:text-blue-600 transition-all'>About</a>
    <a href='#' class='font-normal hover:font-bold text-gray-700 hover:text-blue-600 transition-all'>Contact</a>
  </nav>

  <button class='font-medium hover:font-bold active:font-extrabold bg-blue-600 hover:bg-blue-700 text-white px-6 py-3 rounded-lg transition-all'>
    Click Me
  </button>
</div>

Notice how I added transition-all to smooth out the weight changes? Without it, the shift can feel jarring. The transition makes everything feel more polished and intentional.

Here's a more complex example with a card that responds to hover:

<div class='max-w-md mx-auto bg-white rounded-xl shadow-md overflow-hidden hover:shadow-xl transition-all duration-300 group'>
  <div class='p-8'>
    <div class='uppercase tracking-wide text-sm font-semibold group-hover:font-bold text-indigo-600 transition-all'>
      Case Study
    </div>
    <h3 class='mt-2 font-semibold group-hover:font-bold text-2xl text-gray-900 transition-all'>
      How We Increased Sales by 200%
    </h3>
    <p class='mt-3 font-normal text-gray-600'>
      Learn how this e-commerce company transformed their checkout experience and tripled their conversion rate in just three months.
    </p>
    <div class='mt-4'>
      <span class='font-medium group-hover:font-semibold text-indigo-600 transition-all'>
        Read more →
      </span>
    </div>
  </div>
</div>

The group utility is doing the heavy lifting here. When you hover over the card, all the child elements with group-hover: modifiers respond together. The badge, heading, and call-to-action all get bolder simultaneously, creating a cohesive interactive experience.

This subtle weight change combined with the shadow increase makes the whole card feel more engaging without being over the top.

That's pretty much everything you need to know about controlling font weight in Tailwind CSS.

You've got nine solid utilities for everyday use, arbitrary values when you need something specific, responsive variants for different screen sizes, and interactive states to make your typography come alive.

The beauty of Tailwind's approach is how it keeps everything in your HTML. No jumping between files, no hunting through stylesheets to find where that font weight is defined. It's all right there where you need it.

Start with the basics - font-normal for body text, font-semibold or font-bold for headings. Then experiment with the responsive and interactive features as you get more comfortable. You'll be surprised how much visual interest you can create just by adjusting weight at the right moments.

Other posts you might like...

See more

Subscribe to our newsletter

Get notified when we add new templates, components, and more!

Thanks for subscribing!
Please check your email to confirm your subscription.

WindyBase Make development a breeze

WindyBase is a weekly curated Tailwind CSS template and tool directory built for the modern developer.

© 2026 WindyBase. All rights reserved.