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
100through900
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.
.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:
-
normalis usually the same as400 -
boldis usually the same as700
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;
}
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:
-
400for body text -
600for important labels or subheadings -
700for 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:
-
Check that you spelled
font-weightcorrectly - Confirm the selector matches the element you want to style
- Inspect the element in developer tools and see which rule is winning
- Verify that the font actually includes the requested weight
-
Try a larger difference such as
400versus700 - 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:
400ornormal -
Common bold text:
700orbold -
Light: often
300 -
Medium: often
500 -
Semibold: often
600 -
Heavy:
800or900 - 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:
-
400usually means normal -
700usually 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.
