What is CSS font weight?

The CSS font-weight property controls how thick or thin text appears. In plain English, it changes how heavy the strokes of each letter look. A lighter weight feels airy and delicate, while a heavier weight feels stronger and more attention-grabbing.

This property is one of the easiest ways to create visual hierarchy. You can use it to make headings stand out, to emphasize key words, or to give different parts of a layout distinct personalities without changing the font family itself.

Think of font-weight as the typographic equivalent of speaking softly versus speaking with confidence. Same voice, different intensity.

.title {
  font-weight: 300;
}
  
.title {
  font-weight: 400;
}
  
.title {
  font-weight: 700;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.preview {
font-family: Helvetica, sans-serif, Arial;
padding: 1.25rem;
max-width: 34rem;
border: 1px solid #d0d7de;
border-radius: 0.75rem;
background: #ffffff;
}

.title {
margin: 0 0 0.5rem;
font-size: 2rem;
line-height: 1.1;
}

.text {
margin: 0;
color: #444;
} 

CSS Font Weight

The same text can feel elegant, neutral, or strong depending on its weight.

The font-weight property

The basic syntax is wonderfully straightforward:

.selector {
  font-weight: value;
}

That value can be a keyword such as normal or bold, or it can be a number like 300, 400, or 700.

Here is a very simple example:

.note {
  font-weight: bold;
}
  
.note {
  font-weight: normal;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.note {
font-family: Arial, Helvetica, sans-serif;
font-size: 1.25rem;
padding: 1rem 1.25rem;
border: 1px solid #d0d7de;
border-radius: 0.75rem;
background: #f8fafc;
max-width: 26rem;
} 

Important: font-weight changes the thickness of the text.

The initial default weight for most normal text is typically 400, which corresponds to normal. That means if you do not specify a weight, regular body text often appears at that value by default.

CSS font weight values and options

CSS gives you several kinds of values for font-weight:

  • Keyword values: normal, bold
  • Relative values: lighter, bolder
  • Numeric values: usually 100 through 900

In practice, numeric values give you the most control, especially if your chosen font actually includes multiple weights. That last part matters a lot. CSS can ask politely for 500 or 600, but if the font file does not contain those weights, the browser may fall back to the nearest available one.

.demo-100 {
  font-weight: 100;
}
.demo-400 {
  font-weight: 400;
}
.demo-700 {
  font-weight: 700;
}
.demo-900 {
  font-weight: 900;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.stack {
font-family: sans-serif, Helvetica, Arial;
max-width: 30rem;
padding: 1rem;
border: 1px solid #d0d7de;
border-radius: 0.75rem;
background: #fff;
}

.stack p {
margin: 0.45rem 0;
font-size: 1.5rem;
} 

Weight 100

Weight 400

Weight 700

Weight 900

Named font weights: light, normal, medium, semibold, bold

Beginners often hear names like light, medium, semibold, and bold. These names are common in design tools and font libraries, but in CSS you usually express most of them with numbers.

A very common mapping looks like this:

  • Light is often around 300
  • Normal is usually 400
  • Medium is often 500
  • Semibold is often 600
  • Bold is usually 700

Notice the repeated word often. That is intentional. These labels are common conventions, but what you actually see depends on the font you are using.

font-weight:
.sample {
  font-weight: 400;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.sample {
  font-family: sans-serif, Helvetica, Arial;
  font-size: 2rem;
  line-height: 1.2;
  padding: 1.25rem;
  border: 1px solid #d0d7de;
  border-radius: 0.75rem;
  background: #fff;
  max-width: 30rem;
  margin: 0;
}
  

Watch this sentence gain confidence as the weight increases.

Numeric font weight values from 100 to 900

The traditional numeric scale runs from 100 to 900 in steps of 100. Here is the usual idea:

  • 100 = very thin
  • 200 = extra light
  • 300 = light
  • 400 = normal
  • 500 = medium
  • 600 = semibold
  • 700 = bold
  • 800 = extra bold
  • 900 = black or very heavy

Not every font includes every one of these weights. Some fonts only ship with 400 and 700. Others provide a richer family. Variable fonts can provide a much broader range and smoother control.

.w100 {
  font-weight: 100;
}
  
.w300 {
  font-weight: 300;
}
  
.w500 {
  font-weight: 500;
}
  
.w700 {
  font-weight: 700;
}
  
.w900 {
  font-weight: 900;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.weights {
font-family: sans-serif, Helvetica, Arial;
padding: 1rem 1.25rem;
max-width: 34rem;
border: 1px solid #d0d7de;
border-radius: 0.75rem;
background: #fff;
}

.weights p {
margin: 0.35rem 0;
font-size: 1.5rem;
line-height: 1.2;
} 

100 Thin

300 Light

500 Medium

700 Bold

900 Black

normal and bold keywords

CSS also gives you these simple keyword shortcuts:

  • normal is usually the same as 400
  • bold is usually the same as 700

These are great for readable code when you do not need super-precise control.

.a {
  font-weight: normal;
}
  
.b {
  font-weight: bold;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.compare {
font-family: sans-serif, Helvetica, Arial;
max-width: 28rem;
padding: 1rem 1.25rem;
border: 1px solid #d0d7de;
border-radius: 0.75rem;
background: #fff;
}

.compare p {
margin: 0.5rem 0;
font-size: 1.4rem;
} 

This is normal text.

This is bold text.

CSS font weight and size

Font weight and font size are different properties, but they work together constantly. Size changes how large the text is. Weight changes how thick the letters are.

A big heading with a light weight can feel elegant and modern. A smaller label with a bold weight can feel compact and assertive. Neither property replaces the other. They collaborate.

.headline {
  font-size: 2.4rem;
  font-weight: 500;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.headline {
  font-family: sans-serif, Helvetica, Arial;
  line-height: 1.1;
  margin: 0;
  padding: 1.25rem;
  border: 1px solid #d0d7de;
  border-radius: 0.75rem;
  background: #fff;
  max-width: 36rem;
}
  

Font size and font weight shape the personality of text together.

When to change size and when to change weight

Use font-size when the text should occupy more or less visual space. Use font-weight when the text should feel more or less prominent without necessarily becoming larger.

  • Make headings larger with font-size
  • Make headings stronger with font-weight
  • Make captions smaller with font-size
  • Make labels stand out with font-weight

Font weight inheritance

font-weight is an inherited property. That means if you set it on a parent element, child elements often receive that weight automatically unless they override it.

This is handy, because you can set a general weight on a card or section, then bump up just the title or callout text.

.card {
  font-weight: 300;
}
  
.card {
  font-weight: 300;
}

.card strong {
font-weight: 700;
} 
*,
::before,
::after {
  box-sizing: border-box;
}

.card {
  font-family: sans-serif, Helvetica, Arial;
  max-width: 32rem;
  padding: 1.25rem;
  border: 1px solid #d0d7de;
  border-radius: 0.75rem;
  background: #fff;
  line-height: 1.5;
}

.card p {
  margin: 0;
}
  

This paragraph inherits its weight from the card, but this phrase can be heavier when explicitly styled.

Relative values: lighter and bolder

CSS supports relative weights too:

  • lighter
  • bolder

These values do not point to one exact number. Instead, they adjust the weight relative to the parent element's current weight, using the browser's font-weight mapping rules.

Because they depend on context, they can be less predictable than numeric values. They are valid CSS, but people usually find explicit numeric values easier to control.

.parent {
  font-weight: 700;
}

.child {
font-weight: lighter;
} 
.parent {
  font-weight: 400;
}

.child {
  font-weight: bolder;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.parent {
  font-family: sans-serif, Helvetica, Arial;
  font-size: 1.6rem;
  padding: 1.25rem;
  border: 1px solid #d0d7de;
  border-radius: 0.75rem;
  background: #fff;
  max-width: 30rem;
}

.child {
  display: block;
  margin-top: 0.5rem;
}
  
Parent text Child text

Why font-weight sometimes does not work

This is one of the most common beginner questions, and honestly, it is a good one. When font weight appears not to work, the problem is usually not the CSS syntax. The problem is often the font itself.

Reason 1: the font does not include that weight

If a font only has regular and bold files, asking for 500 or 600 may not create a visibly distinct result. The browser will choose the nearest available weight.

.line-a {
  font-weight: 500;
}

.line-b {
font-weight: 600;
} 
*,
::before,
::after {
  box-sizing: border-box;
}

.wrapper {
  font-family: sans-serif, Helvetica, Arial;
  max-width: 28rem;
  padding: 1rem 1.25rem;
  border: 1px solid #d0d7de;
  border-radius: 0.75rem;
  background: #fff;
}

.wrapper p {
  margin: 0.5rem 0;
  font-size: 1.4rem;
}
  

Requested weight: 500

Requested weight: 600

Reason 2: another selector is overriding it

Your CSS may be correct, but another rule with greater specificity or later source order may be winning.

.text {
  font-weight: 300;
}
.panel .text {
  font-weight: 700;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.panel {
font-family: sans-serif, Helvetica, Arial;
padding: 1rem 1.25rem;
max-width: 26rem;
border: 1px solid #d0d7de;
border-radius: 0.75rem;
background: #fff;
}

.text {
margin: 0;
font-size: 1.5rem;
} 

CSS specificity can change which font weight actually applies.

Learn more about specificity in the CSS Specificity Interactive Tutorial.

Reason 3: you are looking at a synthetic or fake bold

Some browsers can simulate bold when a true bold file is not available. The result may look awkward or inconsistent. It can seem like font-weight is working, but not in a very trustworthy way.

For polished typography, it is best to use fonts that actually provide the weights you intend to use.

Reason 4: the weight change is too subtle

A change from 400 to 500 may be hard to notice in some fonts, especially at small sizes. Try a larger size or a bigger jump like 400 to 700.

Practical font weight patterns

Let us move from theory to useful interface patterns. These are the kinds of combinations you will use in real projects.

Pattern: headings and body text

A common approach is to give the heading a stronger weight while keeping paragraphs normal for readability.

.card-title {
  font-weight: 700;
}

.card-text {
font-weight: 400;
} 
.card-title {
  font-weight: 600;
}

.card-text {
  font-weight: 300;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.card {
  font-family: sans-serif, Helvetica, Arial;
  max-width: 28rem;
  padding: 1.25rem;
  border: 1px solid #d0d7de;
  border-radius: 0.75rem;
  background: #fff;
}

.card-title {
  margin: 0 0 0.5rem;
  font-size: 1.5rem;
  line-height: 1.2;
}

.card-text {
  margin: 0;
  line-height: 1.5;
  color: #444;
}
  

Readable hierarchy

Headings usually carry more weight than paragraph text so users can scan faster.

Pattern: buttons and labels

Buttons and labels often use a medium or semibold weight so they feel actionable without becoming visually shouty.

.button {
  font-weight: 500;
}
  
.button {
  font-weight: 600;
}
  
.button {
  font-weight: 700;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.button {
font-family: sans-serif, Helvetica, Arial;
font-size: 1rem;
padding: 0.8rem 1.1rem;
border: 1px solid #111;
border-radius: 0.65rem;
background: #111;
color: #fff;
display: inline-block;
} 

  

Pattern: subtle secondary text

A lighter weight can make secondary information feel quieter, but be careful not to go overboard. Very light text at small sizes can become hard to read quickly.

.meta {
  font-weight: 300;
}
  
.meta {
  font-weight: 400;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.meta {
font-family: sans-serif, Helvetica, Arial;
font-size: 0.95rem;
color: #666;
padding: 1rem 1.25rem;
max-width: 26rem;
border: 1px solid #d0d7de;
border-radius: 0.75rem;
background: #fff;
margin: 0;
} 

Updated 2 minutes ago by editorial team

Font weight with variable fonts

Variable fonts can support much more flexible weight control than traditional font files. Instead of just a few fixed weights, a variable font may allow many values across a range.

In CSS, that still often means using font-weight, but the browser can interpolate more smoothly if the font supports it. This is one reason variable fonts are so attractive for modern interfaces.

For a beginner, the key takeaway is simple: variable fonts can make numeric weights more precise and more visually consistent.

Accessibility and readability tips

Font weight is not just about style. It affects readability too.

  • Avoid extremely light text for body copy
  • Use enough contrast between text and background
  • Do not rely only on weight to communicate important meaning
  • Test your text at the actual size users will see

For long paragraphs, 400 is often a safe baseline. Some fonts also read well at 300 or 500, but that depends on the font design and the size of the text.

.copy {
  font-weight: 200;
}
  
.copy {
  font-weight: 400;
}
  
.copy {
  font-weight: 500;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.copy {
font-family: sans-serif, Helvetica, Arial;
max-width: 34rem;
padding: 1.25rem;
border: 1px solid #d0d7de;
border-radius: 0.75rem;
background: #fff;
font-size: 1rem;
line-height: 1.6;
color: #222;
margin: 0;
} 

Good body text should feel comfortable to read, not like it is trying out for a fainting contest.

Common font weight mistakes

Mistake: using too many weights

If every heading, label, card, caption, and button uses a different weight, your interface can feel chaotic. A smaller type scale often feels more professional.

Many projects work beautifully with just three main weights:

  • 400 for body text
  • 600 for important labels or subheadings
  • 700 for strong headings

Mistake: making everything bold

If everything is bold, nothing stands out. Bold is useful because it contrasts with regular text.

Mistake: ignoring the font family

Different fonts behave very differently. A 500 in one font might look like a 600 in another. Always judge the result with your actual chosen font, not just the number.

Mistake: confusing font weight with font style

font-weight controls thickness. font-style controls things like italic. They are separate properties.

.one {
  font-weight: 700;
}
  
.one {
  font-style: italic;
}
  
.one {
  font-weight: 700;
  font-style: italic;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.one {
font-family: sans-serif, Helvetica, Arial;
font-size: 1.8rem;
padding: 1rem 1.25rem;
max-width: 24rem;
border: 1px solid #d0d7de;
border-radius: 0.75rem;
background: #fff;
margin: 0;
} 

Bold and italic are different ideas.

Font weight troubleshooting checklist

When font-weight seems broken, work through this list:

  1. Check that you spelled font-weight correctly
  2. Confirm the selector matches the element you want to style
  3. Inspect the element in developer tools and see which rule is winning
  4. Verify that the font actually includes the requested weight
  5. Try a larger difference such as 400 versus 700
  6. Test with a simple system font like Arial to isolate the problem
.target {
  font-weight: 700;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.panel {
font-family: sans-serif, Helvetica, Arial;
padding: 1rem 1.25rem;
max-width: 28rem;
border: 1px solid #d0d7de;
border-radius: 0.75rem;
background: #fff;
}

.target {
margin: 0;
font-size: 1.5rem;
} 

Start simple. If this works, your syntax is fine.

CSS font weight cheat sheet

  • Property: font-weight
  • Common default body text: 400 or normal
  • Common bold text: 700 or bold
  • Light: often 300
  • Medium: often 500
  • Semibold: often 600
  • Heavy: 800 or 900
  • Inherited: yes
  • Relative options: lighter, bolder

Final recap

The CSS font-weight property controls how heavy text appears. It accepts keywords like normal and bold, relative values like lighter and bolder, and numeric values such as 300, 400, 500, 600, and 700.

The most important beginner lessons are these:

  • 400 usually means normal
  • 700 usually means bold
  • Not every font includes every weight
  • Font size and font weight work together, but they are different properties
  • Light text can look stylish, but readability comes first

Once you get comfortable with font weight, you will start seeing it everywhere: in headings, buttons, cards, menus, labels, and interface hierarchy in general. It is a small property with a surprisingly big personality.

And that, dear CSS adventurer, is how you teach text to lift weights without ever stepping foot in a gym.