Making a word heavier to draw attention to it is a typographic habit that predates CSS by centuries. The font-weight property brings that habit to the web, with one twist many developers discover too late: asking for a weight does not guarantee getting it.
This property controls how thick the strokes of a text appear, from the thinnest to the heaviest, and it depends entirely on what the loaded font-family actually provides. A value that works perfectly with one font can produce no visible effect at all with another.
Definition
font-weight accepts two kinds of values: simple keywords, normal and bold, or a numeric value between 100 and 900, in steps of 100.
p {
font-weight: normal; /* same as 400 */
}
strong {
font-weight: bold; /* same as 700 */
}
.thin-heading {
font-weight: 300;
}normal and bold are actually shortcuts for 400 and 700. Nothing forces you to use the keywords: writing font-weight: 700; directly produces the exact same result, and gives access to every intermediate weight the keywords do not cover.
The full numeric scale
The scale runs from 100, the thinnest weight, to 900, the heaviest. Each step matches a name found in professional font catalogs, useful for knowing what to ask a designer for, or which file to download.
| Value | Common name |
|---|---|
100 | Thin |
300 | Light |
400 | Normal / Regular |
500 | Medium |
600 | SemiBold |
700 | Bold |
900 | Black |
With a variable font, a single file contains the entire range, and the browser smoothly interpolates between any value, including numbers like 550 that appear in no table at all. With a classic font, each weight is usually a separate file, loaded on its own.
The trap of a weight that does not exist
Writing font-weight: 600; triggers no error if the loaded font only ships Regular and Bold. The browser never rejects the value: depending on the case, it either shows the closest available weight, or synthesizes a fake bold by artificially thickening the strokes itself.
This browser-synthesized fake bold, sometimes called faux bold, tends to look slightly blurry or smudged, especially noticeable at small text sizes. It is a common symptom: text that looks fine at a glance, but whose letters seem less crisp than the rest of the page. The cause is almost always the same, a requested weight that was never actually loaded.
The fix is to declare, through @font-face, only the weights genuinely used in the stylesheet, and then to check that every font-weight value used matches one of them. A font file loaded for a weight nobody uses also adds needless page weight for nothing.
Best practices
Keep the number of different weights on a single site small, usually two or three is enough: a normal weight for body copy, a heavier one for headings, maybe a lighter one for an occasional decorative touch. Every extra weight is one more file to download, and one more chance to hit the faux bold trap if it is not loaded correctly.
Frequently asked questions
What is the difference between bold and font-weight: 700?
None in practice: bold is simply an alias for 700. Both produce an identical result, so the choice between the two is purely a matter of coding style.
Why does setting my text to bold not change anything on screen?
That is nearly always the sign that the loaded font does not include that weight. Check in the developer tools which font is actually being applied, and compare it against the files declared in the site's @font-face rules.
Can values like 450 or 550 be used?
Yes, but only with a variable font capable of interpolating between the standard steps. With a classic font made of separate files, an unplanned intermediate value simply falls back to the closest available file.
Does font-weight work on any element?
Technically yes, it applies to any element that displays text, but its effect always depends on whichever font-family is in effect at that exact spot, which can differ from one element to another through CSS inheritance and more specific rules elsewhere in the stylesheet.