Quick translation guide for Bootstrap users. Same components, cleaner markup, modern CSS.
| Bootstrap | Airframe | Notes |
|---|
btn | af-btn | Base button |
btn btn-primary | af-btn | Primary button (now default) |
btn btn-secondary | af-btn af-is-secondary | Secondary button |
btn btn-success | af-btn af-is-success | Success variant |
btn btn-danger | af-btn af-is-danger | Danger variant |
btn btn-warning | af-btn af-is-warning | Warning variant |
btn btn-info | af-btn af-is-info | Info variant |
btn btn-sm | af-btn af-is-sm | Small size |
btn btn-lg | af-btn af-is-lg | Large size |
Use component tokens to tweak sizing without new classes:
<style>
:root { --af-control-min-height: 3rem; --af-btn-gap: 0.75rem; --af-input-placeholder-color: rgba(0, 0, 0, 0.45); }
</style>
<button class="af-btn">
Primary
</button>
<input class="af-input" placeholder="Custom input" />
| Bootstrap | Airframe | Notes |
|---|
card | af-card | Base card |
card-body | af-card__body | Card body |
card-header | af-card__header | Card header |
card-footer | af-card__footer | Card footer |
card-title | af-card__title | Card title |
| Bootstrap | Airframe | Notes |
|---|
alert | af-alert | Base alert |
alert alert-primary | af-alert af-is-primary | Primary alert |
alert alert-success | af-alert af-is-success | Success alert |
alert alert-danger | af-alert af-is-danger | Danger alert |
alert alert-warning | af-alert af-is-warning | Warning alert |
alert alert-info | af-alert af-is-info | Info alert |
| Bootstrap | Airframe | Notes |
|---|
badge | af-badge | Base badge |
badge badge-primary | af-badge af-is-primary | Primary badge |
badge badge-success | af-badge af-is-success | Success badge |
badge badge-danger | af-badge af-is-danger | Danger badge |
badge badge-warning | af-badge af-is-warning | Warning badge |
badge badge-info | af-badge af-is-info | Info badge |
| Bootstrap | Airframe | Notes |
|---|
form-control | af-input | Text inputs, email, password, etc. |
form-control (select) | af-select or form.af-form select | Select dropdown (requires class or wrapper) |
form-control (textarea) | af-textarea | Textarea |
form-label | af-label or af-field__label | Form label |
form-check | af-checkbox | Checkbox input |
form-check-input | af-checkbox | Checkbox input class |
form-check-label | (label element) | Checkbox label |
form-select | af-select or form.af-form select | Select dropdown (requires class or wrapper) |
Note: For classless forms, wrap in form.af-form. Select elements require either .af-select class or .af-form wrapper.
For equal-width columns, prefer the simple grid system. By default: af-grid adjusts to the number of children.
| Bootstrap | Airframe | Notes |
|---|
row with 2 equal col-6 | af-grid | Auto-adjusts to 2 columns |
row with 3 equal col-4 | af-grid | Auto-adjusts to 3 columns |
row with 4 equal col-3 | af-grid | Auto-adjusts to 4 columns |
row with 2 equal col-6 (explicit) | af-grid-2 | Explicit 2 columns |
row with 3 equal col-4 (explicit) | af-grid-3 | Explicit 3 columns |
row with 4 equal col-3 (explicit) | af-grid-4 | Explicit 4 columns |
row with 5 equal columns | af-grid-5 | 5 columns |
row with 6 equal columns | af-grid-6 | 6 columns |
row col-12 col-md-6 (2 equal) | af-grid af-grid-1@sm af-grid-2@md | Responsive equal columns |
Example:
<!-- Bootstrap -->
<div class="row">
<div class="col-6">
Item 1
</div>
<div class="col-6">
Item 2
</div>
</div>
<!-- Airframe (auto-adjusting - simplest!) -->
<div class="af-grid">
<div>
Item 1
</div>
<div>
Item 2
</div>
</div>
<!-- Airframe (explicit - also works) -->
<div class="af-grid-2">
<div>
Item 1
</div>
<div>
Item 2
</div>
</div>
Use the 12-column system when migrating Bootstrap code or when you need asymmetric layouts:
| Bootstrap | Airframe | Notes |
|---|
container | af-container | Container |
container-fluid | af-container | Fluid container |
row | af-grid | Grid container (auto-detects 12-column when children have af-col-span-* classes) |
col | (no class needed) | Full width is default |
col-6 | af-col-span-6 | Half width (or use af-grid-2 for new code) |
col-4 | af-col-span-4 | One third (or use af-grid-3 for new code) |
col-3 | af-col-span-3 | One quarter (or use af-grid-4 for new code) |
col-8 | af-col-span-8 | Two thirds (asymmetric - use 12-col) |
col-12 | (no class needed) | Full width is default |
Note: Use af-grid with af-col-span-* classes for Bootstrap migration. The grid automatically detects span classes and applies a 12-column layout. For equal-width columns, use af-grid (auto-adjusts) or af-grid-2 through af-grid-6 for explicit column counts.
| Bootstrap | Airframe | Notes |
|---|
col-12 col-md-6 (equal) | af-grid af-grid-1@sm af-grid-2@md | Prefer simple grid |
col-12 col-md-6 (keep 12-col) | af-col-span-6@md | Direct migration (full width is default) |
col-12 col-lg-8 | af-col-span-8@lg | Asymmetric layout (full width is default) |
col-12 col-lg-4 | af-col-span-4@lg | Asymmetric layout (full width is default) |
col-sm-6 col-md-4 (equal) | af-grid af-grid-2@sm af-grid-3@md | Prefer simple grid |
col-lg-6 | af-col-span-6@lg | Large breakpoint only |
| Bootstrap | Airframe | Notes |
|---|
row g-0 | af-grid af-gap-0 | No gap (override default) |
row g-1 | af-grid af-gap-xs | Small gap (override default) |
row g-2 | af-grid af-gap-sm | Small gap (override default) |
row g-3 | af-grid | Medium gap (default, no override needed) |
row g-4 | af-grid af-gap-lg | Large gap (override default) |
| Bootstrap | Airframe | Notes |
|---|
d-flex | af-inline | Flex display (recipe-first) |
d-flex flex-column | af-stack | Vertical stack |
d-flex flex-row | af-inline | Horizontal inline |
d-flex flex-wrap | af-inline | Wrapping inline |
d-grid | af-grid | Grid display |
d-none | af-hidden | Hidden |
d-block | af-block | Block display |
| Bootstrap | Airframe | Notes |
|---|
d-flex flex-wrap align-items-center | af-cluster | Default semantic cluster |
d-flex flex-wrap align-items-center (explicit) | af-inline af-items-center | Explicit utilities |
d-flex align-items-center justify-content-between | af-spread | Default semantic spread |
d-flex align-items-center justify-content-between (explicit) | af-inline af-items-center af-justify-between | Explicit utilities |
d-flex align-items-center justify-content-center | af-center | Default semantic center |
d-flex align-items-center justify-content-center (explicit) | af-inline af-items-center af-justify-center | Explicit utilities |
| Bootstrap | Airframe | Notes |
|---|
text-center | af-text-center | Center text |
text-left | af-text-start | Start-aligned text (LTR/RTL safe) |
text-right | af-text-end | End-aligned text (LTR/RTL safe) |
| Bootstrap | Airframe | Notes |
|---|
tabular-nums | af-numeric | Tabular numbers |
| Bootstrap | Airframe | Notes |
|---|
w-100 | af-w-full | Full width |
| Bootstrap | Airframe | Notes |
|---|
m-0 | af-m-0 | No margin |
m-1 | af-m-xs | Small margin |
m-2 | af-m-sm | Medium margin |
m-3 | af-m-md | Large margin |
m-4 | af-m-lg | Extra large margin |
m-5 | af-m-xl | XXL margin |
| Bootstrap | Airframe | Notes |
|---|
p-0 | af-p-0 | No padding |
p-1 | af-p-xs | Extra small padding |
p-2 | af-p-sm | Small padding |
p-3 | af-p-md | Medium padding |
p-4 | af-p-lg | Large padding |
p-5 | af-p-xl | Extra large padding |
<!-- Bootstrap -->
<div class="card">
<div class="card-header">
Header
</div>
<div class="card-body">
<h5 class="card-title">
Title
</h5>
<p class="card-text">
Content
</p>
</div>
<div class="card-footer">
Footer
</div>
</div>
<!-- Airframe -->
<div class="af-card">
<div class="af-card__header">
Header
</div>
<div class="af-card__body">
<h5 class="af-card__title">
Title
</h5>
<p class="af-card__body">
Content
</p>
</div>
<div class="af-card__footer">
Footer
</div>
</div>
<!-- Bootstrap -->
<div class="container">
<div class="row g-3">
<div class="col-12 col-lg-8">
Main Content
</div>
<div class="col-12 col-lg-4">
Sidebar
</div>
</div>
</div>
<!-- Airframe -->
<div class="af-container">
<div class="af-grid">
<div class="af-col-span-8@lg">
Main Content
</div>
<div class="af-col-span-4@lg">
Sidebar
</div>
</div>
</div>
<!-- Bootstrap -->
<div class="d-flex gap-2">
<button class="btn btn-primary">
Save
</button>
<button class="btn btn-secondary">
Cancel
</button>
</div>
<!-- Airframe -->
<div class="af-inline af-gap-sm">
<button class="af-btn">
Save
</button>
<button class="af-btn af-is-secondary">
Cancel
</button>
</div>
<!-- Bootstrap -->
<div class="alert alert-warning d-flex justify-content-between align-items-center">
<span>
Warning message
</span>
<button class="btn btn-sm btn-warning">
Action
</button>
</div>
<!-- Airframe -->
<div class="af-alert af-is-warning af-inline af-justify-between af-items-center">
<span>
Warning message
</span>
<button class="af-btn af-is-sm af-is-warning">
Action
</button>
</div>
<!-- Bootstrap -->
<div class="container">
<div class="row">
<div class="col-12 col-md-6">
<div class="card">
<div class="card-body">
<h5 class="card-title">
Form Title
</h5>
<form>
<div class="mb-3">
<label class="form-label" for="name">
Name
</label>
<input type="text" id="name" class="form-control">
</div>
<div class="mb-3">
<label class="form-label" for="country">
Country
</label>
<select id="country" class="form-select">
<option>
Choose...
</option>
</select>
</div>
<button type="submit" class="btn btn-primary">
Submit
</button>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- Airframe -->
<div class="af-container">
<div class="af-grid">
<div class="af-col-span-6@md">
<div class="af-card">
<div class="af-card__body">
<h5 class="af-card__title">
Form Title
</h5>
<form class="af-form">
<div class="af-field">
<label class="af-field__label" for="name">
Name
</label>
<input type="text" id="name" class="af-input">
</div>
<div class="af-field">
<label class="af-field__label" for="country">
Country
</label>
<select id="country" class="af-select">
<option>
Choose...
</option>
</select>
</div>
<button type="submit" class="af-btn">
Submit
</button>
</form>
</div>
</div>
</div>
</div>
</div>
See also: Tailwind Cheat Sheet | Why Airframe?