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="relative bg-surface-3 border rounded-lg" style="height:180px">
<span class="absolute text-bg-primary rounded-md px-2 small top-0 start-0">1</span> <span class="absolute text-bg-primary rounded-md px-2 small top-0 end-0">2</span> <span class="absolute text-bg-primary rounded-md px-2 small top-1/2 start-1/2">3</span> <span class="absolute text-bg-primary rounded-md px-2 small bottom-1/2 end-1/2">4</span> <span class="absolute text-bg-primary rounded-md px-2 small bottom-0 start-0">5</span> <span class="absolute text-bg-primary rounded-md 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="relative bg-surface-3 border rounded-lg m-4" style="height:180px">
<span class="absolute text-bg-primary rounded-md px-2 small top-0 start-0 -translate-x-1/2 -translate-y-1/2">TL</span> <span class="absolute text-bg-primary rounded-md px-2 small top-0 start-1/2 -translate-x-1/2 -translate-y-1/2">T</span> <span class="absolute text-bg-primary rounded-md px-2 small top-0 start-full -translate-x-1/2 -translate-y-1/2">TR</span> <span class="absolute text-bg-primary rounded-md px-2 small top-1/2 start-0 -translate-x-1/2 -translate-y-1/2">L</span> <span class="absolute text-bg-primary rounded-md px-2 small top-1/2 start-1/2 -translate-x-1/2 -translate-y-1/2">C</span> <span class="absolute text-bg-primary rounded-md px-2 small top-1/2 start-full -translate-x-1/2 -translate-y-1/2">R</span> <span class="absolute text-bg-primary rounded-md px-2 small top-full start-0 -translate-x-1/2 -translate-y-1/2">BL</span> <span class="absolute text-bg-primary rounded-md px-2 small top-full start-1/2 -translate-x-1/2 -translate-y-1/2">B</span> <span class="absolute text-bg-primary rounded-md px-2 small top-full start-full -translate-x-1/2 -translate-y-1/2">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="flex gap-6 pt-2">
<button type="button" class="btn btn-primary relative"><i class="bi bi-envelope" aria-hidden="true"></i> Inbox <span class="absolute top-0 start-full -translate-x-1/2 -translate-y-1/2 badge rounded-full bg-danger">91<span class="sr-only"> unread messages</span></span> </button>
<button type="button" class="btn btn-outline-secondary relative" aria-label="Alerts"><i class="bi bi-bell-fill" aria-hidden="true"></i> <span class="absolute top-0 start-full -translate-x-1/2 -translate-y-1/2 p-1 bg-danger border border-light rounded-full"><span class="sr-only">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="flex gap-4">
<span class="relative inline-block"><img src="../assets/img/avatar-1.svg" alt="Ava Moreau" width="64" height="64" class="rounded-full"><span class="absolute bottom-0 end-0 bg-success border border-3 border-white rounded-full" style="width:18px;height:18px"><span class="sr-only">Online</span></span></span> <span class="relative inline-block"><img src="../assets/img/avatar-2.svg" alt="Diego Varga" width="64" height="64" class="rounded-full"><span class="absolute bottom-0 end-0 bg-warning border border-3 border-white rounded-full" style="width:18px;height:18px"><span class="sr-only">Busy</span></span></span> <span class="relative inline-block"><img src="../assets/img/avatar-3.svg" alt="Jonah Fischer" width="64" height="64" class="rounded-full"><span class="absolute bottom-0 end-0 bg-secondary border border-3 border-white rounded-full" style="width:18px;height:18px"><span class="sr-only">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="relative inline-block mt-2"> <img src="../assets/img/avatar-6.svg" alt="Chloe Harlow" width="56" height="56" class="rounded-lg"> <span class="absolute top-0 start-full -translate-x-1/2 -translate-y-1/2 badge rounded-full text-bg-primary border border-2 border-white">17</span> </span>6Ribbon on a card
An absolutely placed label at top-0 end-0 of a card.
<div class="relative border rounded-xl overflow-hidden" style="max-width:18rem">
<img src="../assets/img/product-9.svg" alt="Masterclass" class="w-full block"> <span class="absolute top-0 end-0 text-bg-danger px-4 py-1 small font-semibold" style="border-bottom-left-radius:var(--ui-border-radius)">-26%</span>
<div class="p-4">
<div class="font-medium">
Masterclass
</div>
<div class="small text-muted">
$32.98
</div>
</div>
</div>7Stretched link
stretched-link on the link makes the whole position-relative card clickable.
Virtual passes let you join the main stage live from anywhere.
Read the story<div class="relative border rounded-lg p-4" style="max-width:22rem">
<div class="font-semibold">
Learn, connect and get inspired
</div>
<p class="small text-muted">Virtual passes let you join the main stage live from anywhere.</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.
Three days of keynotes, hands-on workshops and evening meetups. Our team has done this many times, so you never have to guess.
Workshops are limited to thirty seats, so everyone gets hands-on time. Virtual passes let you join the main stage live from anywhere.
The networking app helps you meet the right people before you arrive. Group tickets include a private meeting room for your team.
Start in minutes and get help from a real person whenever you need it. Our team has done this many times, so you never have to guess.
<div class="border rounded-lg overflow-auto" style="height:170px">
<div class="sticky-top bg-surface-2 px-4 py-2 font-semibold small">
Section A (sticky-top)
</div>
<p class="px-4 small">Three days of keynotes, hands-on workshops and evening meetups. Our team has done this many times, so you never have to guess.</p>
<p class="px-4 small">Workshops are limited to thirty seats, so everyone gets hands-on time. Virtual passes let you join the main stage live from anywhere.</p>
<p class="px-4 small">The networking app helps you meet the right people before you arrive. Group tickets include a private meeting room for your team.</p>
<p class="px-4 small mb-0">Start in minutes and get help from a real person whenever you need it. Our team has done this many times, so you never have to guess.</p>
</div>9position-sticky with a custom offset
position-sticky plus top-0 on a table header row inside a scroll box.
| Item | Price |
|---|---|
| Group bundle | $64.11 |
| Student pass | $71.86 |
| Early bird pass | $48.22 |
| Recording pass | $68.62 |
| Early bird pass | $11.32 |
| Student pass | $89.77 |
<div class="border rounded-lg overflow-auto" style="max-height:170px">
<table class="table table-sm mb-0">
<thead class="sticky top-0">
<tr>
<th scope="col" class="bg-surface-3">Item</th>
<th scope="col" class="bg-surface-3 text-end">Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>Group bundle</td>
<td class="text-end">$64.11</td>
</tr>
<tr>
<td>Student pass</td>
<td class="text-end">$71.86</td>
</tr>
<tr>
<td>Early bird pass</td>
<td class="text-end">$48.22</td>
</tr>
<tr>
<td>Recording pass</td>
<td class="text-end">$68.62</td>
</tr>
<tr>
<td>Early bird pass</td>
<td class="text-end">$11.32</td>
</tr>
<tr>
<td>Student pass</td>
<td class="text-end">$89.77</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="relative inline-block rounded-xl overflow-hidden" style="max-width:24rem">
<img src="https://images.unsplash.com/photo-1560523159-94c9d18bcf27?auto=format&fit=crop&w=1200&h=800&q=70" alt="Toronto" class="w-full block"> <span class="absolute bottom-0 start-0 m-4 badge text-bg-light"><i class="bi bi-geo-alt" aria-hidden="true"></i> Copenhagen</span>
</div>11Play button centred on a video
top-50 start-50 translate-middle centres the play button on the poster image.
<div class="relative rounded-xl overflow-hidden" style="max-width:26rem">
<img src="https://images.unsplash.com/photo-1774094453087-0207a0cd2309?auto=format&fit=crop&w=1600&h=700&q=70" alt="Video poster" class="w-full block">
<button type="button" class="btn btn-light rounded-full absolute top-1/2 start-1/2 -translate-x-1/2 -translate-y-1/2 shadow-md text-2xl flex items-center justify-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-4 py-6">
<div class="relative" style="height:4px">
<div class="bg-surface-2 w-full h-full rounded-full">
</div>
<div class="absolute top-0 start-0 bg-primary h-full w-1/2 rounded-full">
</div>
<span class="absolute top-1/2 start-0 -translate-x-1/2 -translate-y-1/2 btn btn-sm btn-primary rounded-full" style="width:2rem;height:2rem">1</span> <span class="absolute top-1/2 start-1/2 -translate-x-1/2 -translate-y-1/2 btn btn-sm btn-primary rounded-full" style="width:2rem;height:2rem">2</span> <span class="absolute top-1/2 start-full -translate-x-1/2 -translate-y-1/2 btn btn-sm btn-secondary rounded-full" 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="relative border rounded-lg p-4 pe-12 bg-surface-3">
<button type="button" class="btn-close absolute top-0 end-0 m-2" aria-label="Close"></button>
<div class="font-semibold">
Meet the people shaping the future
</div>
<div class="small">
The venue is a short walk from the station and fully accessible.
</div>
</div>14Icon inside an input
An icon at top-50 translate-middle-y on the start of a padded input.
<div class="relative" style="max-width:22rem">
<span class="absolute top-1/2 start-0 -translate-y-1/2 ms-4 text-muted"><i class="bi bi-search" aria-hidden="true"></i></span>
<label class="sr-only" for="ut-q-1254">Search</label>
<input id="ut-q-1254" type="search" class="form-control ps-12" placeholder="Search Workshop">
</div>15Tooltip arrow label
A label positioned above an element with bottom-100 start-50 translate-middle-x.
<div class="pt-12 text-center">
<span class="relative inline-block"> <span class="absolute bottom-full start-1/2 -translate-x-1/2 mb-2 text-bg-dark rounded-md px-2 py-1 small whitespace-nowrap">26 saved</span>
<button type="button" class="btn btn-outline-primary"><i class="bi bi-bookmark" 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="grid gap-2 small">
<div class="static text-bg-dark rounded-md p-2">
<code class="text-inherit">fixed-top</code> - pins a bar to the top of the viewport
</div>
<div class="static text-bg-secondary rounded-md p-2">
<code class="text-inherit">sticky-top</code> - sticks after scrolling to it
</div>
<div class="static text-bg-dark rounded-md p-2">
<code class="text-inherit">fixed-bottom</code> - pins a bar to the bottom
</div>
<div class="static text-bg-secondary rounded-md p-2">
<code class="text-inherit">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.
Every detail is handled by people who care about getting it right. We keep things simple, so you can focus on what matters to you.
<div class="relative border rounded-lg p-4 overflow-hidden" style="max-width:22rem">
<div class="font-semibold">
Ten talks you should not miss this year
</div>
<p class="small mb-0">Every detail is handled by people who care about getting it right. We keep things simple, so you can focus on what matters to you.</p>
<div class="absolute top-0 start-0 w-full h-full bg-page flex items-center justify-center">
<div class="spinner-border text-primary-ink" role="status">
<span class="sr-only">Loading</span>
</div>
</div>
</div>18Map pin
A pin positioned at percentage offsets with bottom-50 and translate-middle-x.
<div class="relative rounded-xl overflow-hidden" style="max-width:26rem">
<img src="https://images.unsplash.com/photo-1773828755374-0ee802d9f44b?auto=format&fit=crop&w=1600&h=700&q=70" alt="Map of Porto" class="w-full block"> <span class="absolute top-1/2 start-1/2 -translate-x-1/2 -translate-y-1/2 text-danger-emphasis text-3xl leading-none"><i class="bi bi-geo-alt-fill" aria-hidden="true"></i></span> <span class="absolute bottom-0 end-0 m-2 badge text-bg-light">Lisbon</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="relative rounded-xl overflow-hidden" style="max-width:26rem">
<img src="https://images.unsplash.com/photo-1762968274962-20c12e6e8ecd?auto=format&fit=crop&w=1200&h=800&q=70" alt="Join the conference of the year" class="w-full block">
<button type="button" class="btn btn-light btn-sm rounded-full absolute top-1/2 start-0 -translate-y-1/2 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-full absolute top-1/2 end-0 -translate-y-1/2 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-4">
<div class="relative border border-2 border-primary rounded-xl p-6 text-center" style="max-width:16rem">
<span class="absolute top-0 start-1/2 -translate-x-1/2 -translate-y-1/2 badge rounded-full text-bg-primary px-4">Best value</span>
<div class="small">
Yearly
</div>
<div class="text-2xl font-bold">
$137.45
</div>
</div>
</div>