CoreUI ONE — 250+ PRO components and 25+ admin templates for React, Angular, Vue, Bootstrap and Next.js, plus Data Grid, Scheduler, 4,300+ PRO icons and the Next.js boilerplate. One license. → See what you get

CoreUI v6 Alpha vs Bootstrap 6 Alpha: What We Took, What We Didn't, and Why

CoreUI v6 Alpha vs Bootstrap 6 Alpha: What We Took, What We Didn't, and Why

Bootstrap published its first v6 alpha on October 8. CoreUI v6 followed with its first alpha two weeks later. CoreUI has been built on Bootstrap from the start, so the obvious question is how close the two v6 lines are.

The short answer: as close as we could make them, with a list of deliberate exceptions. For every file we share with Bootstrap we follow one rule. Class names, CSS custom properties, options, events and public methods stay the same as in Bootstrap wherever we can manage it, so moving from one to the other does not mean rewriting markup. The code behind those names is a separate question. Where we can do better than Bootstrap without changing a name, we do. Where following Bootstrap would cost our users a migration step that buys them nothing, we don’t.

This post goes through all three cases: what we took, what we left out, and where we kept the name but changed what is behind it.

Table of Contents

Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


One difference before we start: the prefix

Bootstrap 6 writes its custom properties without a prefix in the Sass source and adds bs- to them at build time, so its tokens come out as --bs-*. Its data attributes (data-bs-*) and events (*.bs.*) are written into the source as they are. CoreUI keeps the custom property prefix as a Sass variable, $prefix, with cui- as the default, because our React, Vue and Angular editions and the admin templates all build on it. Our tokens are --cui-*, our data attributes data-coreui-* and our events *.coreui.*.

So “the same name” in this post means the same name after the prefix: Bootstrap’s --bs-alert-bg is our --cui-alert-bg.

What we took

The Sass and CSS architecture

This is the biggest piece, and we took it whole:

  • Sass modules only. Customisation goes through @use and @forward. @import is no longer supported in either library.

  • The same cascade layers in the same order:

    @layer colors, config, root, reboot, layout, content, forms, components, custom, helpers, utilities;
    

    Utilities sit on top and no longer need !important, and your unlayered CSS no longer has to out-specify the library’s selectors.

  • A token map per component, merged with defaults(), so overriding one token keeps the rest. Root tokens are emitted on :root, :host, so components inside a shadow root see them too.

  • The theme model. .theme-* classes set a family of nine slots (base, fg, fg-emphasis, bg, bg-subtle, bg-muted, border, focus-ring, contrast) with the same names as in Bootstrap, and .theme-reset clears them for one part of a component. CoreUI adds two more slots, hover and active, for the interactive states.

  • The colour model. The palette is defined in oklch, tints and shades are color-mix() in the browser, light and dark modes resolve through light-dark(), and the *-rgb variables are gone.

  • The scales. The lg, xl and 2xl breakpoints move to 1024, 1280 and 1536 px (xxl is now 2xl), spacing has 13 steps, radius is a numeric scale, shadows are layered, and the focus ring is drawn with outline.

If you know how to customise Bootstrap 6, you know how to customise CoreUI v6. Component token and theme slot overrides carry over with a different prefix. The palette is the one exception, covered further down.

Native HTML

Bootstrap 6 replaced a lot of JavaScript with platform features, and we followed:

  • One base on the native <dialog> element, with showModal(), for Dialog and Drawer.
  • Accordion on <details> and <summary>.
  • Carousel on CSS scroll snap.
  • Validation on :user-invalid, scoped by a data-*-validate attribute on the form, in place of .was-validated.
  • Enter and exit transitions with @starting-style.

Forms

The checkbox and radio classes move onto the <input> itself (.check, .radio), and .form-select folds into .form-control. The switch is one place where the markup differs: Bootstrap wraps the input in <div class="switch">, CoreUI puts .switch on the input like the other two. Range becomes a JavaScript component in both, with different option names for its value tooltip.

JavaScript

Both libraries are written in TypeScript and ship their own type declarations. Both replaced Popper with Floating UI, and the option has the same name, floatingConfig. In both, show() and hide() return a promise on the components that animate in and out, and neither ships a separate right-to-left stylesheet any more.

What we did not take, and why

Responsive prefixes

Bootstrap 6 moves responsive and state variants from a suffix to a prefix: .d-md-none becomes .md:d-none, .col-lg-6 becomes .lg:col-6, and .underline-offset-2-hover becomes .hover:underline-offset-2. Its announcement calls this a direct copy of how Tailwind does responsive.

CoreUI v6 keeps the suffixes. Responsive classes appear on almost every page of a real application, so renaming them is the most expensive migration step there is, and for the utilities and components CoreUI ships, the prefix and the suffix say exactly the same thing. A colon also has to be escaped everywhere a class name is used as a selector, in your CSS and in querySelector() alike (.md\:d-none).

We do ask you to rename some classes in v6. Colour modifiers like .btn-primary give way to theme classes, and for those we ship coreui-legacy.css so you can move one page at a time. Responsive classes are not worth that cost.

Bootstrap 6 renamed three components and their classes. .modal, .offcanvas and .dropdown are gone, replaced by .dialog, .drawer and .menu. These are three of the most-used components in any Bootstrap application.

CoreUI v6 ships Dialog, Drawer and Menu with Bootstrap’s names, and keeps Modal, Offcanvas and Dropdown next to them. Modal and Offcanvas run on the same native <dialog> base as Dialog and Drawer. When the JavaScript starts on v5-style <div class="modal"> markup, it builds a <dialog> inside it and keeps the original element in the page as a display: contents wrapper, so your references to it and your event listeners on it keep working. CSS aimed at the old structure does not survive: the .modal-dialog and .modal-content wrappers are gone, and state classes such as .show give way to the native open attribute.

Modal, Offcanvas and Dropdown are deprecated in v6 and may be removed in v7, so new code should use Dialog, Drawer and Menu. Existing code keeps working while you get there.

UMD bundles and jQuery

Bootstrap 6 is ESM-only: no UMD build, no window.bootstrap global and no jQuery support. In this alpha, CoreUI still ships UMD bundles, an ESM bundle, per-file .js and .mjs modules, and the jQuery integration.

Many of our users load CoreUI with a plain <script> tag, often straight from an admin template. Dropping UMD would break every one of those pages, and it would save very little: in this alpha, the minified UMD and ESM bundles differ by about 120 bytes gzip. Keeping the same names as Bootstrap is about names, not about the format of the files we publish.

A lower browser floor

Bootstrap 6 supports Chrome and Edge 130, Firefox 132 and Safari 18. CoreUI v6 supports Chrome and Edge 123, Firefox 130 and Safari 18.

Our floor is set by the newest feature our code actually needs, nothing more: light-dark() sets Chrome 123, <details name> for exclusive accordions sets Firefox 130, and color-mix() in oklch with a grey or transparent side sets Safari 18. That puts us level with Bootstrap on Safari and below it on Chrome and Firefox, so a few more of your users stay supported.

A themed checkbox stays neutral until it is checked

Bootstrap’s themed checkbox paints the unchecked box in the full theme colour. Measured on its compiled stylesheet, a .check.theme-success that is unchecked has the same background and border colour as one that is checked; only the tick tells them apart. A solid green square reads as “on” at a glance. Bootstrap’s own source marks that line as something to revisit.

In CoreUI, a theme class on a control means “this colour when it is on”. The unchecked box stays neutral, and the checked state carries both the fill and the tick.

A close button you can hit

Bootstrap 6 sizes .btn-close at 1.25rem with no padding, a 20 px target at the default font size. That is below the 24 px in the WCAG 2.2 AA target size criterion, so it passes only when there is enough space around it. CoreUI’s close button is the icon plus padding, 24 px at the default font size, and it scales with the font.

Card body alignment

Bootstrap 6 sets align-items: stretch on .card-body. We tried it and measured it in Chromium, on Bootstrap’s alpha and on ours. A logo with height="32" went from 80×32 to 278×32 px, an avatar in a row went from 64×26 to 64×105 px, chips and links stretched to the full width of the card, and a button in .card-body.align-items-center lost its centering. We left it out.

Components we did not port

  • Toggler. It toggles classes or attributes on arbitrary elements from data attributes. That fits vanilla JavaScript, but CoreUI also ships React, Vue and Angular editions, where state lives in the component, and the plugin has no sensible counterpart there.
  • Datepicker. Bootstrap’s wraps Vanilla Calendar Pro. CoreUI has its own Calendar, Date Picker, Date Range Picker, Date Input and Time Picker, with no third-party dependency; the only peer dependency of the package is Floating UI.
  • Stepper. Bootstrap’s is a static, CSS-only progress indicator. Ours is an interactive wizard with validation between steps.
  • Not in this alpha: the .btn-text and .btn-styled button variants, the accent theme colour, .prose and NavOverflow. If you rely on one of them coming from Bootstrap 6, it does not exist in CoreUI v6 yet.

Same name, different implementation

These are the cases our users never see in their markup, because nothing about the API changed.

Each element knows its own direction

Bootstrap 6 decides whether a component is right-to-left by reading the dir attribute of <html>. CoreUI reads the computed direction where the component sits in the page. A left-to-right widget inside an Arabic page, or a right-to-left section inside an English one, positions its menus and tooltips the right way.

Tooltip opacity that does not fade the text

Both libraries have the same --tooltip-opacity token with the same default, .95. Bootstrap applies it to the whole element, which also fades the text and lowers its contrast. CoreUI mixes it into the background colour only, so the tooltip is just as translucent and the text keeps full contrast.

Accordion animation in every supported browser

Animating <details> with CSS alone needs interpolate-size, which not every browser in either library’s support range has. Bootstrap’s own migration guide says a collapse opens and closes instantly there, and names Firefox as the one to watch. CoreUI’s Accordion checks for interpolate-size and animates with JavaScript where it is missing, so the transition looks the same everywhere. Collapse goes one step further with an option for hidden="until-found", so the browser’s find-in-page opens the section that contains the match.

A palette with one knob per colour

Bootstrap’s palette is keyed by hue (--bs-blue-500), and each tint and shade is mixed from a value fixed at build time. CoreUI’s palette is keyed by role, and each stop mixes from the base custom property:

--cui-primary-200: color-mix(in oklch, var(--cui-white) 60%, var(--cui-primary-500));

Set --cui-primary-500 at runtime, and the whole primary ramp, every component that uses it and every theme slot built on it follows.

Sanitizing every component that renders HTML

In Bootstrap, the sanitize, allowList and sanitizeFn options belong to Tooltip (and Popover, which extends it), and Tooltip makes sure they cannot be set through data attributes. In CoreUI, close to twenty components accept HTML you pass in and carry the same three options, from Autocomplete and Calendar to Toaster and Transfer. So the filter lives in the shared configuration code, and every one of them gets it.

Tooltips you can reach with the pointer

Both libraries place a tooltip a few pixels away from its trigger, and both keep it open while the pointer moves onto it. In Bootstrap the pointer has to cross that gap over the arrow. In CoreUI an invisible strip covers the whole edge, so the pointer can cross anywhere.

What we have not synced yet

Bootstrap will publish more alphas, and we follow each one. A few things from the first alpha are not in ours yet, swipe-to-dismiss on the Drawer among them. Each difference we keep on purpose is written down with its reason, and it changes only when that reason does.

Moving from Bootstrap 6 to CoreUI v6

If you already use the Bootstrap 6 alpha, most of the move is mechanical:

  • Replace the prefix: --bs- with --cui-, data-bs- with data-coreui-, and .bs. with .coreui. in event names.
  • Turn responsive and state prefixes back into suffixes: .md:d-none becomes .d-md-none.
  • Move palette overrides from hue names to role names: --bs-blue-500 becomes --cui-primary-500.
  • Rename the few component classes that differ, for example .form-adorn to .form-control-group and .chip-dismiss to .chip-remove.
  • Keep .dialog, .drawer, .menu, the theme classes and your component token overrides as they are.

The CoreUI package also ships an Agent Skill for exactly this move, coreui-from-bootstrap. It lists the classes and options that differ, so a coding agent can do the mechanical part for you. The v6 documentation and the migration guide cover the rest.

About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.