Spacing, Sizing & Borders
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:
{property}{side}-{size} for example mt-3, px-2, p-0
{property}{side}-{breakpoint}-{size} for example mb-md-4, px-lg-5| Part | Values | Meaning |
|---|---|---|
| property | m, p | margin or padding |
| side | t, b, s, e | top, bottom, start, end |
| side | x, y | both left and right, both top and bottom |
| side | (nothing) | all four sides |
| size | 0 to 5, auto | see the scale below; auto is for margin only |
The sizes come from one base value, $spacer, which is 1rem (16px in most browsers):
| Size | Value | Pixels (approx.) |
|---|---|---|
0 | 0 | 0 |
1 | 0.25rem | 4 |
2 | 0.5rem | 8 |
3 | 1rem | 16 |
4 | 1.5rem | 24 |
5 | 3rem | 48 |
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.
<!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.
<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-100andw-autofor width.h-25,h-50,h-75,h-100andh-autofor height. A percentage height only works if the parent has a height.mw-100andmh-100setmax-width: 100%andmax-height: 100%.vw-100andvh-100use the whole viewport;min-vh-100is 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
<!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:
borderon all sides, or one side withborder-top,border-end,border-bottom,border-start. - Remove:
border-0, or one side withborder-top-0and so on. - Colour and width: any theme colour (
border-danger,border-primary-subtle), widthsborder-1toborder-5, andborder-opacity-{10|25|50|75}. - Corners:
rounded, sizesrounded-0torounded-5,rounded-circle,rounded-pill, and one side withrounded-top,rounded-end-3and so on. - Shadows:
shadow-sm,shadow,shadow-lg, andshadow-noneto 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-2orpr-3in Bootstrap 5. Those are Bootstrap 4 names and do nothing now. Usems-2andpe-3. - Adding
mx-autoto 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-3withoutd-flexord-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. sandemean start and end, which flip automatically for right-to-left languages.gap-*spaces items inside flex and grid containers;mx-autocentres a block that has a width.w-*,h-*,border-*,rounded-*andshadow-*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
<!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?
p is padding, x is both horizontal sides, and size 3 is 1rem.
2. Which Bootstrap 5 class replaces Bootstrap 4's ml-auto?
Bootstrap 5 uses start and end (s and e) instead of left and right.
3. Why does gap-2 do nothing on a plain <div> with two buttons inside?
Add d-flex or d-grid to the parent so gap has an effect.
4. What is the value of mb-5?
The scale jumps at the top: 4 is 1.5rem and 5 is 3rem.
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
