Position
Position utilities set position (static, relative, absolute, fixed, sticky) and place absolute children with top-*, bottom-*, start-* and end-* at 0, 50 or 100. translate-middle, translate-middle-x and translate-middle-y centre an element on its point, which is how badges and status indicators sit on buttons and avatars.
1Edge positions
top-0, top-50, top-100 with start-0, start-50, start-100 place absolute children on a grid of nine points.
<div class="position-relative bg-body-tertiary border rounded-3" style="height:180px">
<span class="position-absolute bg-primary text-white rounded-2 px-2 small top-0 start-0">1</span> <span class="position-absolute bg-primary text-white rounded-2 px-2 small top-0 end-0">2</span> <span class="position-absolute bg-primary text-white rounded-2 px-2 small top-50 start-50">3</span> <span class="position-absolute bg-primary text-white rounded-2 px-2 small bottom-50 end-50">4</span> <span class="position-absolute bg-primary text-white rounded-2 px-2 small bottom-0 start-0">5</span> <span class="position-absolute bg-primary text-white rounded-2 px-2 small bottom-0 end-0">6</span>
</div>2Centre with translate-middle
translate-middle shifts an element back by half its size so its centre sits on the point.
<div class="position-relative bg-body-tertiary border rounded-3 m-3" style="height:180px">
<span class="position-absolute bg-primary text-white rounded-2 px-2 small top-0 start-0 translate-middle">TL</span> <span class="position-absolute bg-primary text-white rounded-2 px-2 small top-0 start-50 translate-middle">T</span> <span class="position-absolute bg-primary text-white rounded-2 px-2 small top-0 start-100 translate-middle">TR</span> <span class="position-absolute bg-primary text-white rounded-2 px-2 small top-50 start-0 translate-middle">L</span> <span class="position-absolute bg-primary text-white rounded-2 px-2 small top-50 start-50 translate-middle">C</span> <span class="position-absolute bg-primary text-white rounded-2 px-2 small top-50 start-100 translate-middle">R</span> <span class="position-absolute bg-primary text-white rounded-2 px-2 small top-100 start-0 translate-middle">BL</span> <span class="position-absolute bg-primary text-white rounded-2 px-2 small top-100 start-50 translate-middle">B</span> <span class="position-absolute bg-primary text-white rounded-2 px-2 small top-100 start-100 translate-middle">BR</span>
</div>3Notification badge on a button
position-relative on the button, translate-middle on the counter at top-0 start-100.
<div class="d-flex gap-4 pt-2">
<button type="button" class="btn btn-primary position-relative"><i class="bi bi-envelope-fill" aria-hidden="true"></i> Inbox <span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">18<span class="visually-hidden"> unread messages</span></span> </button>
<button type="button" class="btn btn-outline-secondary position-relative" aria-label="Alerts"><i class="bi bi-bell-fill" aria-hidden="true"></i> <span class="position-absolute top-0 start-100 translate-middle p-1 bg-danger border border-light rounded-circle"><span class="visually-hidden">New alerts</span></span> </button>
</div>4Online indicator on an avatar
The indicator sits at bottom-0 end-0 of a position-relative wrapper.
<div class="d-flex gap-3">
<span class="position-relative d-inline-block"><img src="../assets/img/avatar-1.svg" alt="Mason Silva" width="64" height="64" class="rounded-circle"><span class="position-absolute bottom-0 end-0 bg-success border border-3 border-white rounded-circle" style="width:18px;height:18px"><span class="visually-hidden">Online</span></span></span> <span class="position-relative d-inline-block"><img src="../assets/img/avatar-2.svg" alt="Zoe Kim" width="64" height="64" class="rounded-circle"><span class="position-absolute bottom-0 end-0 bg-warning border border-3 border-white rounded-circle" style="width:18px;height:18px"><span class="visually-hidden">Busy</span></span></span> <span class="position-relative d-inline-block"><img src="../assets/img/avatar-3.svg" alt="Ava Silva" width="64" height="64" class="rounded-circle"><span class="position-absolute bottom-0 end-0 bg-secondary border border-3 border-white rounded-circle" style="width:18px;height:18px"><span class="visually-hidden">Offline</span></span></span>
</div>5Count badge on an avatar
A number badge at top-0 start-100 with translate-middle on a square avatar.
<span class="position-relative d-inline-block mt-2"> <img src="../assets/img/avatar-7.svg" alt="Kenji Whitaker" width="56" height="56" class="rounded-3"> <span class="position-absolute top-0 start-100 translate-middle badge rounded-pill text-bg-primary border border-2 border-white">14</span> </span>6Ribbon on a card
An absolutely placed label at top-0 end-0 of a card.
<div class="position-relative border rounded-4 overflow-hidden" style="max-width:18rem">
<img src="../assets/img/product-9.svg" alt="Desk lamp" class="w-100 d-block"> <span class="position-absolute top-0 end-0 text-bg-danger px-3 py-1 small fw-semibold" style="border-bottom-left-radius:var(--ui-border-radius)">-38%</span>
<div class="p-3">
<div class="fw-medium">
Ceramic mug
</div>
<div class="small text-body-secondary">
$85.17
</div>
</div>
</div>7Stretched link
stretched-link on the link makes the whole position-relative card clickable.
This modern process keeps projects moving forward from the very first day.
Read the story<div class="position-relative border rounded-3 p-3" style="max-width:22rem">
<div class="fw-semibold">
Shop the collection everyone talks about
</div>
<p class="small text-body-secondary">This modern process keeps projects moving forward from the very first day.</p>
<a href="#" class="stretched-link small">Read the story</a>
</div>8Sticky top inside a scroll area
sticky-top keeps a header visible while its scroll container moves.
Our secure checkout guides customers coming back at a fair price. This clear launch gives time back in your day in just a few clicks.
This simple community lets every detail in view from the very first day. This clear release helps results you can measure on any device.
A simple update shows new ideas to life without the usual hassle. The new member prices connects your work organised at a fair price.
A modern workflow turns customers coming back on any device. Our gift wrapping connects results you can measure in just a few clicks.
<div class="border rounded-3 overflow-auto" style="height:170px">
<div class="sticky-top bg-body-secondary px-3 py-2 fw-semibold small">
Section A (sticky-top)
</div>
<p class="px-3 small">Our secure checkout guides customers coming back at a fair price. This clear launch gives time back in your day in just a few clicks.</p>
<p class="px-3 small">This simple community lets every detail in view from the very first day. This clear release helps results you can measure on any device.</p>
<p class="px-3 small">A simple update shows new ideas to life without the usual hassle. The new member prices connects your work organised at a fair price.</p>
<p class="px-3 small mb-0">A modern workflow turns customers coming back on any device. Our gift wrapping connects results you can measure in just a few clicks.</p>
</div>9position-sticky with a custom offset
position-sticky plus top-0 on a table header row inside a scroll box.
| Item | Price |
|---|---|
| Leather wallet | $49.35 |
| Ceramic mug | $39.75 |
| Canvas tote | $72.52 |
| Canvas tote | $89.58 |
| Glass bottle | $59.20 |
| Glass bottle | $70.50 |
<div class="border rounded-3 overflow-auto" style="max-height:170px">
<table class="table table-sm mb-0">
<thead class="position-sticky top-0">
<tr>
<th scope="col" class="bg-body-tertiary">Item</th>
<th scope="col" class="bg-body-tertiary text-end">Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>Leather wallet</td>
<td class="text-end">$49.35</td>
</tr>
<tr>
<td>Ceramic mug</td>
<td class="text-end">$39.75</td>
</tr>
<tr>
<td>Canvas tote</td>
<td class="text-end">$72.52</td>
</tr>
<tr>
<td>Canvas tote</td>
<td class="text-end">$89.58</td>
</tr>
<tr>
<td>Glass bottle</td>
<td class="text-end">$59.20</td>
</tr>
<tr>
<td>Glass bottle</td>
<td class="text-end">$70.50</td>
</tr>
</tbody>
</table>
</div>10Caption over an image
position-absolute bottom-0 start-0 with margin places a label on the photo corner.
<div class="position-relative d-inline-block rounded-4 overflow-hidden" style="max-width:24rem">
<img src="../assets/img/photo-2.svg" alt="Melbourne" class="w-100 d-block"> <span class="position-absolute bottom-0 start-0 m-3 badge text-bg-light"><i class="bi bi-geo-alt-fill" aria-hidden="true"></i> Toronto</span>
</div>11Play button centred on a video
top-50 start-50 translate-middle centres the play button on the poster image.
<div class="position-relative rounded-4 overflow-hidden" style="max-width:26rem">
<img src="../assets/img/wide-4.svg" alt="Video poster" class="w-100 d-block">
<button type="button" class="btn btn-light rounded-circle position-absolute top-50 start-50 translate-middle shadow fs-3 d-flex align-items-center justify-content-center" style="width:64px;height:64px" aria-label="Play"><i class="bi bi-play-fill" aria-hidden="true"></i></button>
</div>12Step progress with positioned dots
A line with translate-middle steps positioned at start-0, start-50 and start-100.
<div class="px-3 py-4">
<div class="position-relative" style="height:4px">
<div class="bg-body-secondary w-100 h-100 rounded-pill">
</div>
<div class="position-absolute top-0 start-0 bg-primary h-100 w-50 rounded-pill">
</div>
<span class="position-absolute top-50 start-0 translate-middle btn btn-sm btn-primary rounded-pill" style="width:2rem;height:2rem">1</span> <span class="position-absolute top-50 start-50 translate-middle btn btn-sm btn-primary rounded-pill" style="width:2rem;height:2rem">2</span> <span class="position-absolute top-50 start-100 translate-middle btn btn-sm btn-secondary rounded-pill" style="width:2rem;height:2rem">3</span>
</div>
</div>13Close button in the corner
A btn-close at top-0 end-0 with a small margin.
<div class="position-relative border rounded-3 p-3 pe-5 bg-body-tertiary">
<button type="button" class="btn-close position-absolute top-0 end-0 m-2" aria-label="Close"></button>
<div class="fw-semibold">
Everyday essentials, beautifully made
</div>
<div class="small">
This focused release shows new ideas to life without the usual hassle.
</div>
</div>14Icon inside an input
An icon at top-50 translate-middle-y on the start of a padded input.
<div class="position-relative" style="max-width:22rem">
<span class="position-absolute top-50 start-0 translate-middle-y ms-3 text-body-secondary"><i class="bi bi-search" aria-hidden="true"></i></span>
<label class="visually-hidden" for="ut-q-1254">Search</label>
<input id="ut-q-1254" type="search" class="form-control ps-5" placeholder="Search Apparel">
</div>15Tooltip arrow label
A label positioned above an element with bottom-100 start-50 translate-middle-x.
<div class="pt-5 text-center">
<span class="position-relative d-inline-block"> <span class="position-absolute bottom-100 start-50 translate-middle-x mb-2 text-bg-dark rounded-2 px-2 py-1 small text-nowrap">8 saved</span>
<button type="button" class="btn btn-outline-primary"><i class="bi bi-bookmark-fill" aria-hidden="true"></i> Save</button>
</span>
</div>16Fixed and sticky classes (preview)
fixed-top, fixed-bottom and sticky-top attach bars to the viewport; here they are previewed as static boxes with position-static.
fixed-top - pins a bar to the top of the viewportsticky-top - sticks after scrolling to itfixed-bottom - pins a bar to the bottomsticky-md-top - sticky from md up<div class="d-grid gap-2 small">
<div class="position-static text-bg-dark rounded-2 p-2">
<code class="text-white">fixed-top</code> - pins a bar to the top of the viewport
</div>
<div class="position-static text-bg-secondary rounded-2 p-2">
<code class="text-white">sticky-top</code> - sticks after scrolling to it
</div>
<div class="position-static text-bg-dark rounded-2 p-2">
<code class="text-white">fixed-bottom</code> - pins a bar to the bottom
</div>
<div class="position-static text-bg-secondary rounded-2 p-2">
<code class="text-white">sticky-md-top</code> - sticky from md up
</div>
</div>17Overlay covering a card
position-absolute top-0 start-0 w-100 h-100 covers the card with a loading layer.
This reliable journey connects the whole team on the same page without extra tools. The new hand-checked quality guides time back in your day without extra tools.
<div class="position-relative border rounded-3 p-3 overflow-hidden" style="max-width:22rem">
<div class="fw-semibold">
4 lessons from our community
</div>
<p class="small mb-0">This reliable journey connects the whole team on the same page without extra tools. The new hand-checked quality guides time back in your day without extra tools.</p>
<div class="position-absolute top-0 start-0 w-100 h-100 bg-body bg-opacity-75 d-flex align-items-center justify-content-center">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading</span>
</div>
</div>
</div>18Map pin
A pin positioned at percentage offsets with bottom-50 and translate-middle-x.
<div class="position-relative rounded-4 overflow-hidden" style="max-width:26rem">
<img src="../assets/img/wide-3.svg" alt="Map of Austin" class="w-100 d-block"> <span class="position-absolute top-50 start-50 translate-middle text-danger fs-2 lh-1"><i class="bi bi-geo-alt-fill" aria-hidden="true"></i></span> <span class="position-absolute bottom-0 end-0 m-2 badge text-bg-light">Austin</span>
</div>19Vertical centre on one side
top-50 end-0 translate-middle-y places a next arrow on the side of a slider.
<div class="position-relative rounded-4 overflow-hidden" style="max-width:26rem">
<img src="../assets/img/photo-10.svg" alt="Designed to last, priced to love" class="w-100 d-block">
<button type="button" class="btn btn-light btn-sm rounded-circle position-absolute top-50 start-0 translate-middle-y ms-2" aria-label="Previous"><i class="bi bi-chevron-left" aria-hidden="true"></i></button>
<button type="button" class="btn btn-light btn-sm rounded-circle position-absolute top-50 end-0 translate-middle-y me-2" aria-label="Next"><i class="bi bi-chevron-right" aria-hidden="true"></i></button>
</div>20Corner tag on a pricing card
A badge at top-0 start-50 translate-middle sits on the top border.
<div class="pt-3">
<div class="position-relative border border-2 border-primary rounded-4 p-4 text-center" style="max-width:16rem">
<span class="position-absolute top-0 start-50 translate-middle badge rounded-pill text-bg-primary px-3">Best value</span>
<div class="small">
Yearly
</div>
<div class="fs-3 fw-bold">
$288.07
</div>
</div>
</div>