skillZs
★ LIVE SKILL TAGS ★
>>> LIVE SKILLS INDEX <<<
* OPEN SOURCE *
NO LOGIN, NO TRACKING
※ REAL INSTALL DATA ※
← back to all skills
twbs/bootstrap103 installs

bootstrap-v4-v6-migration

Migrate a project from Bootstrap 4 to Bootstrap 6. Use when upgrading from Bootstrap 4, jumping two major versions, or updating v4 class names, data attributes, forms, and JavaScript across the v4-to-v5 and v5-to-v6 steps.

How do I install this agent skill?

npx skills add https://github.com/twbs/bootstrap --skill bootstrap-v4-v6-migration
view source ↗

Is this agent skill safe to install?

  • Gen Agent Trust Hubpass

    This skill is a technical guide for migrating a project from Bootstrap 4 to Bootstrap 6. It outlines a two-step migration path through Bootstrap 5 and provides necessary shell commands, Sass updates, and JavaScript API changes. No security risks were found.

  • Snykpass

    Risk: LOW · No issues

What does this agent skill do?

Bootstrap v4 to v6 Migration

There is no direct v4 to v6 path. Migrate in two stages — v4 to v5 first (this skill), then v5 to v6 (the bootstrap-v5-v6-migration skill). Skipping the middle stage doesn't work, because many v4 names were renamed in v5 and renamed again in v6: .text-primary becomes .fg-primary only after passing through v5, and .badge-primary becomes .badge.theme-primary by way of .badge.bg-primary.

Workflow

Work through each step in order. After each step, search the codebase for remaining v4 patterns before moving on.

  • Step 1: Plan the two-stage migration
  • Step 2: v4 to v5 — dependencies, build, and Sass
  • Step 3: v4 to v5 — JavaScript
  • Step 4: v4 to v5 — classes and attributes
  • Step 5: v5 to v6 — hand off to the v6 migration skill
  • Step 6: Verify

Step 1: Plan the two-stage migration

  1. Get the project onto Bootstrap 5 and working — build passing, pages rendering, tests green — before touching v6. Landing the v5 stage as its own commit (or PR) keeps the two rename waves separable when something breaks.
  2. Inventory what you're dealing with first. The v4 features that cost the most time are custom forms, .input-group-append / .input-group-prepend, jumbotrons, .media objects, .card-deck / .card-columns, and any jQuery that calls Bootstrap plugins.
  3. Decide about jQuery separately. Bootstrap 5 dropped it, but your app may use it for other things; removing Bootstrap's dependency on it does not require removing jQuery itself.
  4. Note the browser floor. Bootstrap 5 drops IE. Bootstrap 6 requires Chrome and Edge 130, Firefox 132, and Safari 18 on macOS and iOS.

Step 2: v4 to v5 — dependencies, build, and Sass

  1. Update the dependency and drop the jQuery/Popper v1 pair:

    npm i --save bootstrap@5 @popperjs/core
    npm uninstall popper.js
    

    popper.js (v1) is replaced by @popperjs/core (v2). Bootstrap 5's bundle includes Popper; the standalone bootstrap.js does not.

  2. Switch the Sass compiler to Dart Sass (npm i --save-dev sass). Node Sass / LibSass is not supported. Keep using @import for now — v5 still uses it; the move to @use happens in the v6 stage.

  3. Sass maps no longer merge automatically. In v4, adding one key to $theme-colors was enough; in v5 you must define the complete map, including the keys you're keeping.

  4. Update renamed functions and mixins:

    v4v5
    color-yiq()color-contrast()
    theme-color(), gray()Removed — reference $theme-colors / $grays directly
    theme-color-level()tint-color() / shade-color()
    lighten() / darken()tint-color() / shade-color()
    media-breakpoint-down(md)media-breakpoint-down(lg) — takes the breakpoint itself, not the next one down
    media-breakpoint-between(sm, md)media-breakpoint-between(sm, lg) — same shift on the upper bound

    The breakpoint parameter change is silent: nothing errors, your media queries just apply one breakpoint off. Audit every call.

  5. Print styles, $enable-* flags, and the utility API all changed shape in v5. If you generated custom utilities with v4 mixins, rewrite them through v5's $utilities map.


Step 3: v4 to v5 — JavaScript

  1. Namespace every data attribute with bs. This is a mechanical but wide-reaching change:

    v4v5
    data-toggledata-bs-toggle
    data-targetdata-bs-target
    data-dismissdata-bs-dismiss
    data-parentdata-bs-parent
    data-ridedata-bs-ride
    data-slide, data-slide-todata-bs-slide, data-bs-slide-to
    data-spydata-bs-spy
    data-backdrop, data-keyboarddata-bs-backdrop, data-bs-keyboard
    data-content, data-placement, data-triggerdata-bs-content, data-bs-placement, data-bs-trigger

    Any option passed as an attribute follows the same rule: data-<option> becomes data-bs-<option>.

  2. Replace jQuery plugin calls with constructors or static getters:

    // v4
    $('#myModal').modal('show')
    $('#myTooltip').tooltip()
    
    // v5
    const modal = new bootstrap.Modal(document.querySelector('#myModal'))
    modal.show()
    
    bootstrap.Tooltip.getOrCreateInstance(document.querySelector('#myTooltip'))
    
  3. Replace jQuery event handlers with native listeners. Bootstrap 5 dispatches native CustomEvents, so $(el).on('shown.bs.modal', …) stops firing:

    // v5
    document.querySelector('#myModal').addEventListener('shown.bs.modal', event => {
      // event.relatedTarget replaces event.relatedTarget from the jQuery event
    })
    
  4. Smaller API renames:

    • _getInstance() → getInstance(), and prefer the new getOrCreateInstance().
    • The sanitizer option whiteList → allowList.
    • Tooltip and Popover title / content still accept functions, but this is no longer the jQuery element.
  5. If you relied on jQuery's noConflict or on $.fn.button('toggle')-style calls, rewrite them against the class API — there is no jQuery interface left to shim.


Step 4: v4 to v5 — classes and attributes

Directional utilities become logical (RTL support)

v4v5
.ml-*, .mr-*.ms-*, .me-*
.pl-*, .pr-*.ps-*, .pe-*
.float-left, .float-right.float-start, .float-end
.text-left, .text-right.text-start, .text-end
.border-left, .border-right.border-start, .border-end
.rounded-left, .rounded-right.rounded-start, .rounded-end
.dropleft, .dropright.dropstart, .dropend

The responsive variants follow the same rename (.ml-md-3 → .ms-md-3).

Typography and helpers

v4v5
.font-weight-bold, -normal, -light, -bolder, -lighter.fw-bold, .fw-normal, .fw-light, .fw-bolder, .fw-lighter
.font-italic.fst-italic
.text-monospace.font-monospace
.sr-only, .sr-only-focusable.visually-hidden, .visually-hidden-focusable
.embed-responsive, .embed-responsive-16by9.ratio, .ratio-16x9
.text-justify, .text-hide, .pre-scrollableRemoved
.rounded-sm, .rounded-lg.rounded-1, .rounded-3

Forms

This is the largest v4 to v5 rewrite: custom form controls were merged into the standard classes.

v4v5
.custom-select.form-select
.custom-range.form-range
.custom-file, .form-control-file.form-control (on <input type="file">)
.form-control-range.form-range
.custom-control.custom-checkbox.form-check
.custom-control.custom-radio.form-check
.custom-control.custom-switch.form-check.form-switch
.custom-control-input.form-check-input
.custom-control-label.form-check-label
.custom-control-inline.form-check-inline
.form-groupSpacing utilities, e.g. .mb-3
.form-row.row plus gutter utilities (.g-*)
.form-inlineGrid or flex utilities (.row .row-cols-lg-auto, .d-flex)
<label> with no class<label class="form-label">

Input groups lose their wrappers: delete .input-group-append and .input-group-prepend and place .input-group-text, buttons, and controls as direct children of .input-group. Validation feedback moves out of the removed wrappers too.

Components dropped or restructured

v4v5
.jumbotronRemoved — compose with .bg-*, .p-*, .rounded-*
.mediaRemoved — use .d-flex and gap/margin utilities
.card-deck, .card-columnsRemoved — use the grid, or CSS columns for masonry
.close.btn-close (drop the &times; child; the icon is a background image)
.badge-primary and friends.badge plus .bg-primary
.badge-pill.rounded-pill
.btn-blockA .d-grid wrapper (add .gap-* for stacked buttons)
.thead-light, .thead-dark.table-light, .table-dark on <thead>
.arrow (tooltip/popover).tooltip-arrow, .popover-arrow
.carousel-item-left, -right.carousel-item-start, -end

Badges also lost their link styling — a <a class="badge"> no longer gets hover/focus states.

Grid, navbars, and navs

  • .no-gutters → .g-0, and gutters are now controlled by the .g-*, .gx-*, .gy-* utilities.
  • A new xxl breakpoint (1400px) exists; existing xl classes keep their meaning.
  • Navbars now require a container inside .navbar (<nav class="navbar"><div class="container">…).
  • For tabs and pills, .active moves from .nav-item to .nav-link. .nav-item is optional as a wrapper.
  • .dropdown-menu items can be <button> or <a>; .dropdown-item-text was added for plain text.

Step 5: v5 to v6 — hand off to the v6 migration skill

Once the project builds and renders on Bootstrap 5, switch to the bootstrap-v5-v6-migration skill and work through its steps. Do not attempt those renames while v4 patterns are still present — its find-and-replace steps assume v5 names.

That stage covers, among other things:

  • @import to @use, and the move from Sass scalars to CSS token maps (defaults() merges theme maps again in v6)
  • Popper to Floating UI, plus Vanilla Calendar Pro for Datepicker. The bundled build includes both peers; the standalone build leaves them external.
  • The md: responsive prefix syntax replacing -md- infixes
  • Modal to Dialog, Offcanvas to Drawer, Dropdown to Menu. Dialog and Drawer use native <dialog> elements.
  • .btn-primary to .btn-solid .theme-primary, and .text-* to .fg-*
  • ESM-only JavaScript with no window.bootstrap global
  • Container-query contexts for responsive stacks, CSS Grid, navbars, list groups, card groups, and stacked tables

Two v4-era details worth flagging before you start it: the .close → .btn-close element you produced in Step 4 keeps that name in v6 (but must stay empty, with no child SVG), and the .form-check markup you just wrote gets rebuilt again into v6's .check / .radio / .switch structure.


Step 6: Verify

  1. Build the project and fix compilation errors before looking at the rendered output.
  2. Search for leftover v4 patterns:
    • data-toggle=, data-target=, data-dismiss=, data-ride=, data-slide, data-spy= (should all be data-bs-*)
    • class="close", &times; inside a close button (should be .btn-close)
    • badge-, badge-pill (should be .badge .bg-* / .rounded-pill)
    • custom-select, custom-control, custom-switch, custom-range, custom-file
    • form-group, form-row, form-inline, input-group-append, input-group-prepend
    • \bm[lr]-, \bp[lr]-, float-left, float-right, text-left, text-right, border-left, border-right
    • font-weight-, font-italic, text-monospace
    • no-gutters, sr-only, embed-responsive, jumbotron, media-body, card-deck, card-columns, btn-block, thead-light, thead-dark, pre-scrollable, text-justify
    • \$(, jQuery( near Bootstrap plugin names (.modal(, .tooltip(, .collapse()
    • theme-color(, color-yiq(, theme-color-level(, media-breakpoint-down(
  3. Click through every interactive component — the data attribute renames fail silently, so a missed data-toggle looks like a dead button rather than an error.
  4. Check forms especially closely: custom controls, input groups, and validation feedback all changed structure.
  5. Then move to Step 5 and repeat this discipline for the v6 stage.

Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.

<a href="https://skillzs.dev/skills/twbs/bootstrap/bootstrap-v4-v6-migration">View bootstrap-v4-v6-migration on skillZs</a>