HC

Typography

HTML & CSS · 11 entries

Font Family

syntax
font-family: "Font Name", fallback, generic;
example
body {
  font-family: "Inter", "Segoe UI", system-ui, sans-serif;
}

code, pre {
  font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
}

Note Always end the stack with a generic family (sans-serif, serif, monospace, cursive, system-ui). The system-ui keyword uses the operating system's default font. Quotes are required when font names contain spaces.

Font Size

syntax
font-size: value; /* px, rem, em, %, clamp() */
example
html {
  font-size: 16px; /* base for rem units */
}

body {
  font-size: 1rem;
}

h1 {
  font-size: clamp(1.75rem, 4vw, 3rem);
}

.small-text {
  font-size: 0.875rem; /* 14px at 16px base */
}

Note Use rem for consistent sizing relative to the root. em is relative to the parent's font size which compounds in nested elements. clamp() creates fluid typography that scales between a minimum and maximum.

Font Weight

syntax
font-weight: 100-900 | normal | bold | lighter | bolder;
example
.heading {
  font-weight: 700;
}

.body-text {
  font-weight: 400;
}

.light-text {
  font-weight: 300;
}

.semibold {
  font-weight: 600;
}

Note 100=Thin, 200=ExtraLight, 300=Light, 400=Normal, 500=Medium, 600=SemiBold, 700=Bold, 800=ExtraBold, 900=Black. The font file must include the requested weight or the browser will fake bold, which looks poor.

Line Height

syntax
line-height: number | length | percentage;
example
body {
  line-height: 1.6;
}

h1 {
  line-height: 1.2;
}

.compact {
  line-height: 1.4;
}

Note Use unitless numbers (like 1.6) rather than fixed units so the line height scales proportionally with font size. Body text typically reads best between 1.5 and 1.7. Headings look better tighter at 1.1 to 1.3.

Text Align

syntax
text-align: left | center | right | justify | start | end;
example
.hero-heading {
  text-align: center;
}

.article-body {
  text-align: start; /* respects writing direction */
}

.price {
  text-align: right;
}

Note Prefer start and end over left and right for internationalization support (RTL languages). Avoid text-align: justify for body text on the web since it creates uneven word spacing without hyphenation.

Text Decoration

syntax
text-decoration: line style color thickness;
text-underline-offset: value;
example
a {
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 2px;
}

a:hover {
  text-decoration-color: #3b82f6;
}

.no-underline {
  text-decoration: none;
}

Note Use text-underline-offset to move underlines away from the text baseline for better readability. text-decoration-skip-ink: auto (the default in most browsers) makes underlines skip descenders cleanly.

Text Transform

syntax
text-transform: uppercase | lowercase | capitalize | none;
example
.label {
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: 0.75rem;
}

.name {
  text-transform: capitalize;
}

Note When using uppercase, add letter-spacing (0.04em to 0.1em) to improve readability. Keep actual content in normal case in the HTML since text-transform is purely visual and screen readers may spell out uppercase letters.

Letter & Word Spacing

syntax
letter-spacing: value;
word-spacing: value;
example
.tracking-wide {
  letter-spacing: 0.05em;
}

.tracking-tight {
  letter-spacing: -0.02em;
}

.spaced-words {
  word-spacing: 0.1em;
}

Note Use em units for letter-spacing so it scales with font size. Tight letter-spacing works well for large headings. Wide letter-spacing suits small uppercase labels.

Word Break & Overflow Wrap

syntax
word-break: normal | break-all | keep-all;
overflow-wrap: normal | break-word | anywhere;
example
.comment {
  overflow-wrap: break-word;
}

.data-cell {
  word-break: break-all;
}

.cjk-text {
  word-break: keep-all;
}

Note overflow-wrap: break-word only breaks long words that would overflow their container. word-break: break-all breaks between any characters, even mid-word. Use overflow-wrap for most cases and word-break: break-all only for data like hashes or URLs.

Text Wrap Balance & Pretty

syntax
text-wrap: balance | pretty | stable;
example
h1, h2, h3 {
  text-wrap: balance;
}

.article-body {
  text-wrap: pretty;
}

Note text-wrap: balance distributes text evenly across lines, preventing headings with one orphaned word on the last line. text-wrap: pretty focuses on avoiding orphans in body text. balance has a limit of a few lines for performance reasons.

Loading Web Fonts

syntax
@font-face {
  font-family: "Name";
  src: url("path.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
example
@font-face {
  font-family: "CustomSans";
  src: url("/fonts/custom-sans-regular.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}

@font-face {
  font-family: "CustomSans";
  src: url("/fonts/custom-sans-bold.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
}

body {
  font-family: "CustomSans", sans-serif;
}

Note Use font-display: swap to show fallback text while the font loads, preventing invisible text. WOFF2 offers the best compression. Preload critical fonts with <link rel="preload" as="font" crossorigin>.