# Bootstrap 4 to 5 Migration: Critical CSS Breaking Changes That Destroy Layouts

> Migrate Bootstrap 4 to 5 seamlessly by understanding critical CSS breaking changes. Learn how to update utilities, grids, and remove deprecated classes to prevent style collapse and ensure a smooth transition.

- Repository: [Tailwind Labs/tailwindcss](https://github.com/tailwindlabs/tailwindcss)
- Tags: migration-guide
- Published: 2026-02-16

---

**Migrating from Bootstrap 4 to 5 requires replacing directional utilities like `ml-*` with `ms-*`, updating grid systems to use CSS `gap` instead of negative margins, and removing deprecated classes like `.btn-block` and `.custom-*`, or your entire application styling will collapse.**

Upgrading a production application from Bootstrap 4 to Bootstrap 5 introduces fundamental changes to the CSS framework that can cause complete UI failure if not addressed systematically. While the Tailwind CSS team has developed sophisticated codemods in `tailwindlabs/tailwindcss` to handle similar utility-class migrations—specifically the `migrateLegacyClasses` function in `packages/@tailwindcss-upgrade/src/codemods/template/migrate-legacy-classes.ts`—Bootstrap 5 requires manual auditing of several critical breaking changes that affect layout, spacing, and component styling.

## Utility Class Renames in Bootstrap 4 to 5 Migration

The most immediate breaking change during a bootstrap 4 to 5 migration is the comprehensive renaming of directional utility classes. Bootstrap 5 replaced physical direction names (left/right) with logical properties (start/end) to improve RTL (right-to-left) language support.

### Directional Spacing Utilities

The margin and padding utilities changed their prefixes entirely:

- `ml-*` (margin-left) → `ms-*` (margin-start)
- `mr-*` (margin-right) → `me-*` (margin-end)
- `pl-*` (padding-left) → `ps-*` (padding-start)
- `pr-*` (padding-right) → `pe-*` (padding-end)

Since these utilities control spacing throughout most layouts, their removal causes immediate visual collapse. Elements using `ml-3` or `mr-auto` will lose their spacing entirely because these class names are no longer generated in Bootstrap 5's CSS output.

### Float and Text Alignment Updates

Float and text alignment utilities also adopted the start/end naming convention:

- `float-left` → `float-start`
- `float-right` → `float-end`
- `text-left` → `text-start`
- `text-right` → `text-end`

Applications relying on these classes for navigation bars, image positioning, or text alignment will experience visual regressions until these classes are updated.

## Grid System Overhaul: From Negative Margins to CSS Gap

Bootstrap 5 fundamentally changed how grid gutters work, which can break custom grid implementations that relied on the previous behavior.

### Row Gutter Implementation

In Bootstrap 4, `.row` elements used negative margins to create gutters between columns. Bootstrap 5 replaces this with the CSS `gap` property. While this is more modern and easier to override, existing custom CSS that targeted `.row` margins or padding may now clash with the gap-based layout, causing misaligned columns.

If your application uses custom grid overrides that relied on negative margins or specific padding calculations, you must update them to respect the new gap model or explicitly disable gutters using `g-0`.

### Column Class Simplification

The grid tier class names were simplified, and the `xs` breakpoint was effectively removed (it now starts at `null` and applies to all breakpoints). Custom media queries that assumed specific Bootstrap 4 breakpoint behaviors may shift unexpectedly at viewport widths of 576px, 992px, and other thresholds, causing responsive layout jumps.

## Form Control and Component Removals

Bootstrap 5 removed several component-specific classes and rewrote form controls entirely, which can cause forms to appear unstyled or broken.

### Removal of Custom Form Classes

The `.custom-*` class namespace was removed entirely. You must replace these classes with their new equivalents:

- `.custom-select` → `.form-select`
- `.custom-file` → `.form-control` (with `type="file"`)
- `.custom-range` → `.form-range`

These new classes use native form controls with updated base styling. Existing forms using the old `.custom-control` wrappers will lose their styling, spacing, and focus indicators, appearing as default browser inputs.

### Button Layout Breaking Changes

The `.btn-block` class was removed entirely. Buttons that previously stretched full-width by using `.btn-block` will revert to inline size, breaking layouts that depended on full-width buttons.

To achieve the same effect in Bootstrap 5, you must use utility classes like `.w-100` or wrapper elements with `.d-grid` and `.gap-2`.

## Typography and Iconography Adjustments

Typography utilities underwent significant changes that affect text density and hierarchy. The `.lead` class now has a different line-height, which may cause text blocks to appear too dense. Additionally, the display heading utilities (`.display-1` through `.display-4`) were removed from the base classes and replaced with font-size utilities (`.fs-1`, `.fs-2`, etc.).

Applications relying on display classes for hero sections or large typography will need to update their class names or manually adjust font sizes and line heights.

Bootstrap 5 also dropped the built-in SVG icon set. The `bi` icon class prefix changed, and icons will disappear entirely if the Bootstrap Icons library is not explicitly included.

## Automating the Migration with Codemods

While Bootstrap does not provide an official codemod, you can automate class name replacements using regex-based scripts similar to those found in `tailwindlabs/tailwindcss`. The `migrateLegacyClasses` function in `packages/@tailwindcss-upgrade/src/codemods/template/migrate-legacy-classes.ts` demonstrates how to map legacy utilities while preserving responsive variants, and the safety checks in `packages/@tailwindcss-upgrade/src/codemods/template/is-safe-migration.test.ts` ensure migrations do not unintentionally change user-defined values.

The following TypeScript utility, inspired by the Tailwind migration logic in `packages/@tailwindcss-upgrade/src/index.ts`, automatically rewrites CSS files to convert Bootstrap 4 directional utilities to their Bootstrap 5 equivalents:

```typescript
// utils/bootstrap5-migration.ts
import fs from 'node:fs';
import path from 'node:path';

// Mapping of old utilities → new utilities
const MAP = new Map<string, string>([
  ['ml-', 'ms-'],
  ['mr-', 'me-'],
  ['pl-', 'ps-'],
  ['pr-', 'pe-'],
  ['float-left', 'float-start'],
  ['float-right', 'float-end'],
  ['text-left', 'text-start'],
  ['text-right', 'text-end'],
]);

export function migrateBootstrap4(filePath: string) {
  const src = fs.readFileSync(filePath, 'utf8');
  let transformed = src;

  for (const [oldPrefix, newPrefix] of MAP) {
    // Handle numbered utilities like ml-3, mr-auto, etc.
    const regex = new RegExp(`\\b${oldPrefix}(\\w+)\\b`, 'g');
    transformed = transformed.replace(regex, `${newPrefix}$1`);
  }

  fs.writeFileSync(filePath, transformed);
  console.log(`Migrated ${filePath}`);
}

// Example usage:
// migrateBootstrap4(path.resolve('src/styles/main.css'));

```

This script implements the same defensive migration strategy found in `packages/@tailwindcss-upgrade/src/codemods/template/migrate-legacy-classes.ts`, ensuring that only exact class name matches are replaced. For version detection logic to guard against running migrations on wrong versions, reference the pattern in `packages/@tailwindcss-upgrade/src/utils/version.ts`.

## Summary

- **Directional utilities renamed**: `ml-*` becomes `ms-*`, `mr-*` becomes `me-*`, and similar changes affect padding, float, and text alignment classes.
- **Grid system uses CSS gap**: Negative margin hacks on `.row` elements no longer work; gutters now use the `gap` property.
- **Custom form classes removed**: `.custom-select`, `.custom-file`, and `.custom-range` are replaced with `.form-select`, `.form-control`, and `.form-range`.
- **Button blocks eliminated**: `.btn-block` is removed; use `.w-100` or grid utilities instead.
- **Automation possible**: Adapt codemod patterns from `tailwindlabs/tailwindcss`, specifically `migrateLegacyClasses` in `packages/@tailwindcss-upgrade/src/codemods/template/migrate-legacy-classes.ts`, to automate class replacements.

## Frequently Asked Questions

### What is the most common breaking change in Bootstrap 4 to 5 migration?

The most common breaking change is the renaming of directional utility classes from left/right to start/end. Classes like `ml-3` (margin-left) and `mr-auto` (margin-right) no longer exist in Bootstrap 5; they have been replaced with `ms-*` (margin-start) and `me-*` (margin-end). Since these utilities control spacing throughout most layouts, their removal causes immediate visual collapse across the entire application.

### How do I migrate custom form controls to Bootstrap 5?

Bootstrap 5 removed the entire `.custom-*` namespace for form controls. You must replace `.custom-select` with `.form-select`, `.custom-file` with `.form-control` (using `type="file"`), and `.custom-range` with `.form-range`. These new classes use native form elements with updated base styling, so you should also audit any custom CSS that targeted the old wrapper structures, as the DOM hierarchy and class names have changed significantly.

### Are Bootstrap 4 and 5 compatible?

Bootstrap 4 and 5 are not compatible in the same project. You cannot mix Bootstrap 4 and 5 classes because Bootstrap 5 uses different CSS custom properties, changed breakpoint behaviors, and removed or renamed numerous utility classes. Attempting to use both versions simultaneously will result in conflicting styles, broken layouts, and unpredictable component behavior. A complete migration of all templates and stylesheets is required.

### How can I automate the Bootstrap 4 to 5 migration?

While Bootstrap does not provide an official codemod, you can automate class name replacements using regex-based scripts similar to those in `tailwindlabs/tailwindcss`. The `migrateLegacyClasses` function in `packages/@tailwindcss-upgrade/src/codemods/template/migrate-legacy-classes.ts` demonstrates how to map legacy utilities while preserving responsive variants. You can adapt this pattern to create a Node.js script that scans your HTML and CSS for Bootstrap 4 classes (like `ml-*` or `float-left`) and rewrites them to their Bootstrap 5 equivalents (`ms-*`, `float-start`), though you should always verify the output with visual regression testing.