Units & Sizing Functions

CSS · Lesson 9 of 55 6 min read Updated

Every size in CSS needs a unit: font sizes, widths, padding, gaps. Picking the right unit is what makes a design scale smoothly from a small phone to a large monitor, and what makes it respect a reader who has set a bigger default font size.

In this lesson you will learn the units that matter in modern CSS and the four maths functions, calc(), min(), max() and clamp(), that let one value adapt to the space it has.

Absolute units: px

A CSS pixel (px) is a fixed size. It is not the same as a physical dot on your screen: a high-resolution phone uses several device dots for one CSS pixel, so 16px text looks about the same size on most screens.

Pixels are fine for things that should not scale with text, such as a 1px border or a small shadow. Other absolute units (cm, mm, in, pt) are mainly for print style sheets.

Font-relative units: rem and em

  • rem is relative to the font size of the root element (<html>). In most browsers that is 16px by default, so 1rem is 16px and 1.5rem is 24px.
  • em is relative to the font size of the current element. When used for font-size itself, it is relative to the parent's font size.
  • ch is about the width of the "0" character in the current font, which makes it handy for line lengths: max-width: 65ch keeps paragraphs comfortable to read.

Use rem for font sizes. Many people, especially older readers and people with low vision, increase the default font size in their browser settings. Sizes in rem grow with that setting; sizes in px ignore it.

The danger with em is that it compounds: an em inside an em multiplies.

HTMLTry it yourself
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>rem vs em</title>
  <style>
    body { font-family: system-ui, sans-serif; padding: 1rem; }
    .em-box  { font-size: 1.2em; }
    .rem-box { font-size: 1.2rem; }
    div { border-left: 3px solid #8aa1c1; padding-left: 0.6rem; margin-top: 0.3rem; }
    .btn { font-size: 1rem; padding: 0.5em 1em; background: #0b6e4f; color: white; border: none; }
    .btn.big { font-size: 1.5rem; }
  </style>
</head>
<body>
  <div class="em-box">1.2em
    <div class="em-box">1.2em inside 1.2em
      <div class="em-box">and again: keeps growing</div>
    </div>
  </div>
  <div class="rem-box">1.2rem
    <div class="rem-box">1.2rem inside 1.2rem
      <div class="rem-box">and again: stays the same</div>
    </div>
  </div>
  <p><button class="btn">Book ticket</button> <button class="btn big">Book ticket</button></p>
</body>
</html>

The nested em boxes keep getting bigger, while the rem boxes stay the same size. The buttons show where em is the right choice: their padding is in em, so the bigger button gets proportionally bigger padding without any extra rules.

Percentages

A percentage is relative to something else, and what that is depends on the property. For width, it is the width of the parent (strictly, the containing block). For font-size, it is the parent's font size.

One surprise: padding and margin percentages are always based on the parent's width, even for top and bottom.

Viewport units

Viewport units are relative to the browser window (the viewport):

UnitMeans
vw1% of the viewport width
vh1% of the viewport height
svh1% of the small viewport height (mobile browser bars shown)
lvh1% of the large viewport height (bars hidden)
dvh1% of the dynamic viewport height (updates as bars show and hide)

On phones, the address bar and toolbar slide in and out as you scroll. Old 100vh often equals the height with the bars hidden, so a "full-screen" section is taller than the visible area and its bottom is cut off. The newer units fix this:

CSS
.hero {
  min-height: 100svh;   /* always fits when the browser bars are visible */
}
.app-shell {
  height: 100dvh;       /* follows the bars as they move */
}

svh is the safe choice for most full-height sections. dvh is good for app-like layouts, but because it changes while scrolling it can make content jump. These units are supported in current versions of all major browsers. There are matching width units too (svw, lvw, dvw).

Two more unit families appear later in the course: fr in CSS Grid Basics and container units like cqi in Container Queries.

Maths functions

calc()

calc() does arithmetic, and it can mix units, which is impossible to do by hand:

CSS
.sidebar-layout main {
  width: calc(100% - 18rem);              /* full width minus a sidebar */
}
.sticky-offset {
  top: calc(var(--header-height) + 1rem); /* works with custom properties */
}

Always put spaces around + and - inside calc(). calc(100%-2rem) is invalid.

min(), max() and clamp()

  • min(a, b) uses whichever value is smaller.
  • max(a, b) uses whichever value is larger.
  • clamp(minimum, preferred, maximum) uses the preferred value, but never goes below the minimum or above the maximum.

These replace many media queries. Run this example and resize the Try-it window:

HTMLTry it yourself
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>clamp and min</title>
  <style>
    body { font-family: system-ui, sans-serif; margin: 0; background: #f3f5f8; }
    .container {
      width: min(100% - 2rem, 40rem);
      margin-inline: auto;
      background: white;
      padding: clamp(1rem, 4vw, 2.5rem);
    }
    h1 {
      font-size: clamp(1.75rem, 1.2rem + 3vw, 3rem);
      line-height: 1.15;
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>Kochi Marathon 2026</h1>
    <p>Registration is open for the 5 km, 10 km and half marathon routes along the waterfront.</p>
  </div>
</body>
</html>

The container is the full width minus 2rem on small screens, but never wider than 40rem, so the text never stretches into very long lines. The heading grows smoothly with the window between 1.75rem and 3rem, and the padding does the same.

Common mistakes

  • Font sizes in px. They ignore the user's font-size setting. Use rem.
  • 100vh on mobile. Content hides behind the browser bars. Use 100svh or 100dvh.
  • No spaces in calc(). Write calc(100% - 2rem), not calc(100%-2rem).
  • Missing units. width: 300 is ignored. Only 0 can be written without a unit.
  • Deep em nesting. Sizes compound unexpectedly. Prefer rem unless you want scaling with the local text.

Key points

  • Use rem for font sizes so text respects the reader's browser settings.
  • em scales with the element's own font size; it suits padding on buttons but compounds when nested.
  • Percentages depend on the property; padding and margin percentages use the parent's width.
  • Prefer svh or dvh over vh for full-height sections on phones.
  • calc() mixes units; min(), max() and clamp() create sizes that adapt without media queries.

Exercise

Create a card for a cricket coaching camp in Rohtak. Make the card min(100% - 2rem, 30rem) wide and centred, give the heading a fluid size with clamp() between 1.5rem and 2.5rem, and set paragraph text to 1rem with a maximum line length of 60ch. Give a button padding in em units.

Show solution
HTML
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Coaching camp</title>
  <style>
    body { font-family: system-ui, sans-serif; margin: 0; padding-block: 1rem; }
    .card {
      width: min(100% - 2rem, 30rem);
      margin-inline: auto;
      padding: 1.25rem;
      border: 1px solid #c9d3df;
      border-radius: 10px;
    }
    h2 { font-size: clamp(1.5rem, 1rem + 2vw, 2.5rem); }
    p { font-size: 1rem; max-width: 60ch; }
    button { font-size: 1rem; padding: 0.6em 1.2em; }
  </style>
</head>
<body>
  <div class="card">
    <h2>Summer Cricket Camp, Rohtak</h2>
    <p>Daily batting, bowling and fielding drills for players aged 10 to 16.</p>
    <button>Register</button>
  </div>
</body>
</html>

min() picks the smaller of the two widths, so the card fills small screens but stops growing at 30rem.

Quick Quiz

1. The root font size is 16px. How big is 2rem?

2. Why can height: 100vh cause problems on phones?

3. What does clamp(1rem, 5vw, 2rem) return on a very wide screen where 5vw is 60px?

4. Which calc() is valid?

Learn CSS with a mentor

Free lessons get you started. Our Full Stack Web Development training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call