Spacing, Sizing & Borders

Bootstrap · Lesson 7 of 28 6 min read Updated

Good spacing is the difference between a page that feels cramped and one that feels professional. Bootstrap's utility classes let you add margin, padding, widths, borders and shadows straight in your HTML, using a fixed scale so everything lines up.

In this lesson you will learn the spacing formula that powers hundreds of classes, then size elements and decorate them with borders and shadows.

The spacing formula

Every spacing class follows one pattern:

Text
{property}{side}-{size}              for example  mt-3, px-2, p-0
{property}{side}-{breakpoint}-{size} for example  mb-md-4, px-lg-5
PartValuesMeaning
propertym, pmargin or padding
sidet, b, s, etop, bottom, start, end
sidex, yboth left and right, both top and bottom
side(nothing)all four sides
size0 to 5, autosee the scale below; auto is for margin only

The sizes come from one base value, $spacer, which is 1rem (16px in most browsers):

SizeValuePixels (approx.)
000
10.25rem4
20.5rem8
31rem16
41.5rem24
53rem48

So pt-3 is "padding-top 1rem", mx-2 is "margin left and right 0.5rem", and mb-md-0 is "no bottom margin from tablets upwards". Start and end mean left and right in English, and automatically flip in right-to-left languages such as Urdu.

HTMLTry it yourself
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Spacing</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
  <style>.demo { background: #e9e3f5; }</style>
</head>
<body>
  <div class="container py-3">
    <div class="demo p-1 mb-2">p-1</div>
    <div class="demo p-3 mb-2">p-3</div>
    <div class="demo p-5 mb-2">p-5</div>
    <div class="demo px-5 py-1 mb-4">px-5 py-1</div>

    <div class="border rounded p-3 mb-4">
      <h2 class="h5 mb-1">Farhan Qureshi</h2>
      <p class="text-body-secondary mb-3">Class 12, Science, Kochi</p>
      <button type="button" class="btn btn-primary btn-sm me-2">Message</button>
      <button type="button" class="btn btn-outline-secondary btn-sm">Profile</button>
    </div>

    <div class="w-50 mx-auto p-3 text-center bg-body-tertiary border rounded">
      w-50 mx-auto: half width, centred
    </div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

In the profile box, mb-1 keeps the name close to the subtitle, mb-3 separates the text from the buttons, and me-2 puts space at the end of the first button so the two do not touch. mx-auto centres a block element that has a width, because the browser shares the leftover space equally on both sides.

Gap

When elements sit in a flex or grid container, gap-* is cleaner than putting margins on every child. It only adds space between items, never around the outside. row-gap-* and column-gap-* set one direction.

HTML
<div class="d-flex gap-2">
  <button class="btn btn-success">Accept</button>
  <button class="btn btn-outline-danger">Decline</button>
</div>

gap needs d-flex or d-grid on the parent. You will learn those in Display & Flex Utilities.

Width and height

Sizing classes set width or height as a percentage of the parent:

  • w-25, w-50, w-75, w-100 and w-auto for width.
  • h-25, h-50, h-75, h-100 and h-auto for height. A percentage height only works if the parent has a height.
  • mw-100 and mh-100 set max-width: 100% and max-height: 100%.
  • vw-100 and vh-100 use the whole viewport; min-vh-100 is useful for a full-screen login page that can still grow.

These classes cover common cases only. For an exact width such as 280px, write your own CSS class or use the grid.

Borders, rounded corners and shadows

HTMLTry it yourself
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Borders and shadows</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
  <div class="container py-3">
    <div class="row row-cols-2 row-cols-md-3 g-3 mb-4">
      <div class="col"><div class="p-3 border">border</div></div>
      <div class="col"><div class="p-3 border border-primary border-2">border-primary border-2</div></div>
      <div class="col"><div class="p-3 border-start border-success border-4">border-start border-4</div></div>
      <div class="col"><div class="p-3 border rounded-3">rounded-3</div></div>
      <div class="col"><div class="p-3 border rounded-pill text-center">rounded-pill</div></div>
      <div class="col"><div class="p-3 border border-top-0">border-top-0</div></div>
    </div>
    <div class="row row-cols-1 row-cols-sm-3 g-4">
      <div class="col"><div class="p-3 bg-body shadow-sm rounded">shadow-sm</div></div>
      <div class="col"><div class="p-3 bg-body shadow rounded">shadow</div></div>
      <div class="col"><div class="p-3 bg-body shadow-lg rounded">shadow-lg</div></div>
    </div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

The border classes:

  • Add: border on all sides, or one side with border-top, border-end, border-bottom, border-start.
  • Remove: border-0, or one side with border-top-0 and so on.
  • Colour and width: any theme colour (border-danger, border-primary-subtle), widths border-1 to border-5, and border-opacity-{10|25|50|75}.
  • Corners: rounded, sizes rounded-0 to rounded-5, rounded-circle, rounded-pill, and one side with rounded-top, rounded-end-3 and so on.
  • Shadows: shadow-sm, shadow, shadow-lg, and shadow-none to remove one.

A left border in a colour, like border-start border-success border-4, is a popular way to mark a "success" or "note" panel.

Why utility classes use !important

Every utility class is declared with !important. That sounds like bad practice, but it is deliberate: a utility class is a direct instruction, so mt-0 must win even against a component style that sets a margin. The downside is that your own CSS cannot override a utility class without also using !important. The practical rule: if you need a different value, remove the utility class from the HTML rather than fighting it in CSS.

Common mistakes

  • Using ml-2 or pr-3 in Bootstrap 5. Those are Bootstrap 4 names and do nothing now. Use ms-2 and pe-3.
  • Adding mx-auto to an element with no width. A full-width block has no leftover space to share, so nothing moves. Give it a width (w-50, a column, or your own class) first.
  • Using gap-3 without d-flex or d-grid. Gap only works on flex and grid containers.
  • Trying to override a utility in your stylesheet. Utilities use !important; change the class in the HTML instead.

Key points

  • Spacing classes follow {m|p}{t|b|s|e|x|y}-{breakpoint}-{0-5|auto}.
  • The scale is based on 1rem: 1 = 0.25rem, 2 = 0.5rem, 3 = 1rem, 4 = 1.5rem, 5 = 3rem.
  • s and e mean start and end, which flip automatically for right-to-left languages.
  • gap-* spaces items inside flex and grid containers; mx-auto centres a block that has a width.
  • w-*, h-*, border-*, rounded-* and shadow-* handle sizing and decoration, and all utilities use !important.

Exercise

Create a "Train ticket" box for a journey from Jaipur to Pune. It should be 75% wide on all screens and centred, with padding of 1.5rem, a 4px left border in the primary colour, rounded corners (size 3) and a medium shadow. Inside, show the train name with a small bottom margin, the date in secondary text, and two buttons ("Download" and "Cancel") with a gap between them.

Show solution
HTML
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Train ticket</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
  <div class="container py-4">
    <div class="w-75 mx-auto p-4 border-start border-primary border-4 rounded-3 shadow">
      <h1 class="h5 mb-1">Jaipur to Pune Express</h1>
      <p class="text-body-secondary mb-3">Thursday, 12 November, Coach B2, Seat 34</p>
      <div class="d-flex gap-2">
        <button type="button" class="btn btn-primary">Download</button>
        <button type="button" class="btn btn-outline-danger">Cancel</button>
      </div>
    </div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

w-75 mx-auto gives the box a width and centres it, p-4 is 1.5rem padding, and d-flex gap-2 spaces the buttons without margins on each one.

Quick Quiz

1. What does px-3 do?

2. Which Bootstrap 5 class replaces Bootstrap 4's ml-auto?

3. Why does gap-2 do nothing on a plain <div> with two buttons inside?

4. What is the value of mb-5?

Learn Bootstrap 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