ASP.NET Core 5.0 - Migrate To Bootstrap v5
This article will describe how to migrate an ASP.NET Core 5.0 Razor Pages project from Bootstrap v4 to v5. I will assume you have downloaded the ASP.NET Core 5.0 - Users Without Passwords Project or created a new ASP.NET Core 5.0 Razor Pages project. See Tutorial: Get started with Razor Pages in ASP.NET Core.
Users Without Passwords Project and Article Series
I have developed two separate projects in the Users Without Passwords Project (UWPP) solution. The Users Without Passwords v4 project supports Bootstrap v4 and the new Users Without Passwords project supports Bootstrap v5. The new version is published at Fido.KenHaggerty.Com. You can register a new user with Windows Hello or a FIDO2 security key. Details, screenshots, and related articles can be found at ASP.NET Core 5.0 - Users Without Passwords Project. The details page includes the version change log.
- ASP.NET Core 5.0 - Users Without Passwords
- ASP.NET Core 5.0 - Migrate To Bootstrap v5
- ASP.NET Core 5.0 - The TempData Challenge
- ASP.NET Core 5.0 - FIDO2 Challenge Options
- ASP.NET Core 5.0 - FIDO2 Credential Devices
- ASP.NET Core 5.0 - FIDO2 Credential Create
- ASP.NET Core 5.0 - FIDO2 Credential Get
- ASP.NET Core 5.0 - FIDO2 Attestation Trust
- ASP.NET Core 5.0 - Multiple FIDO2 Credentials
Update 09/14/2021
I updated the Twitter Bootstrap CDN link and integrity hash to version 5.1.1.
I have migrated KenHaggerty.Com to Bootstrap v5. KenHaggerty.Com implements Native JavaScript for Bootstrap. Bootstrap's bootstrap.bundle.min.js @ v5.0.1 is 76.9 KB (78,748 bytes). Bootstrap Native's bootstrap-native.min.js @ v4.0.0 is 38.7 KB (39,729 bytes). Since v4.0.0, bootstrap-native.js supports Bootstrap v5 and bootstrap-native-v4.js supports Bootstrap v4. I have developed two separate projects in the Users Without Passwords Project (UWPP). The Users Without Passwords v4 project supports Bootstrap v4 and the new Users Without Passwords project supports Bootstrap v5.
KenHaggerty.Com and the Users Without Passwords projects implement the Cloudflare CDN service for bootstrap.min.css and bootstrap-native.min.js. For the integrity attribute to work correctly, the local file must be exactly the same as the CDN version. Update the project's libman.json to match current versions. See ASP.NET Core 2.2 - Manage Client-Side Libraries.
Bootstrap v5 libman.json:
{ "version": "1.0", "defaultProvider": "cdnjs", "libraries": [ { "destination": "wwwroot/lib/bootstrap/dist/", "files": [ "css/bootstrap.css", "css/bootstrap.css.map", "css/bootstrap.min.css", "css/bootstrap.min.css.map" ], "library": "twitter-bootstrap@5.1.1" }, { "destination": "wwwroot/lib/bootstrap/dist/js/", "files": [ "bootstrap-native.esm.js", "bootstrap-native.esm.min.js", "bootstrap-native.js", "bootstrap-native.min.js", "polyfill.js", "polyfill.min.js" ], "library": "bootstrap.native@4.0.6" } ] }
Bootstrap v5 Pages > Shared > _Layout.cshtml:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.1.1/css/bootstrap.min.css" asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css" asp-suppress-fallback-integrity="true" asp-fallback-test-class="visually-hidden" asp-fallback-test-property="position" asp-fallback-test-value="absolute" integrity="sha512-6KY5s6UI5J7SVYuZB4S/CZMyPylqyyNZco376NM2Z8Sb8OxEdp02e1jkKk/wZxIEmjQ6DRCEBhni+gpr9c4tvA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap.native/4.0.6/bootstrap-native.min.js" asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap-native.min.js" asp-fallback-test="window.BSN" integrity="sha512-os4qxPq5Rf7xni4mEhIUr9TwzB+ta+8kGm7wt0H6fYcLRyVsB5111QiB341xtld35GsDFVU78k1SAswDghR2yQ==" crossorigin="anonymous" referrerpolicy="no-referrer"> </script>
Notice the asp-fallback-test-class for bootstrap.min.css is visually-hidden rather than sr-only. This article attempts to add value to many articles and blogs about migrating to Bootstrap v5. I found Abi Rana's blog Cheatsheet on converting Bootstrap v4 project to Bootstrap v5 which helped to quickly mitigate most issues. I enhance and expand his Find and Replace list for the new class names. The list addresses most classes but not all. You should review Bootstrap v5.0 - Migrating to v5.
“Screen reader” classes are now “visually hidden” classes. Bootstrap v5.0 - Migrating to v5 - Helpers
Find | Replace With |
---|---|
sr-only | visually-hidden |
Horizontal direction specific variables, utilities, and mixins have all been renamed to use logical properties like those found in flexbox layouts—e.g., start and end in lieu of left and right. Bootstrap v5.0 - Migrating to v5 - RTL Renamed several utilities to use logical property names instead of directional names with the addition of RTL support: Bootstrap v5.0 - Migrating to v5 - Utilities
Find | Replace With |
---|---|
left- | start- |
right- | end- |
-left | -start |
-right | -end |
ml- | ms- |
mr- | me- |
pl- | ps- |
pr- | pe- |
Dropped form-specific layout classes for our grid system. Use our grid and utilities instead of .form-group, .form-row, or .form-inline. Bootstrap v5.0 - Migrating to v5 - Forms
Find | Replace With |
---|---|
form-group | mb-3 |
form-row | row |
Added .fs-* utilities for font-size utilities (with RFS enabled). These use the same scale as HTML’s default headings (1-6, large to small), and can be modified via Sass map. Bootstrap v5.0 - Migrating to v5 - Utilities
Find | Replace With |
---|---|
font-weight- | fw- |
font-style- | fst- |
Miscellaneous from Abi Rana's blog Cheatsheet on converting Bootstrap v4 project to Bootstrap v5
Find | Replace With |
---|---|
no-gutters | g-0 |
embed-responsive | ratio |
embed-responsive-16by9 | ratio-16x9 |
badge-primary | bg-primary |
badge-pill | rounded-pill |
rounded-lg & rounded-sm | rounded-1, rounded-2 & rounded-3 |
btn-block | d-block w-100 (as alternative) |
Dropped native .form-control-file and .form-control-range. Dropped .input-group-append and .input-group-prepend. You can now just add buttons and .input-group-text as direct children of the input groups. .custom-file and .form-file have been replaced by custom styles on top of .form-control. Dropped form-specific layout classes for our grid system. Use our grid and utilities instead of .form-group, .form-row, or .form-inline. Bootstrap v5.0 - Migrating to v5 - Forms
Find | Replace With |
---|---|
form-control-file | As Required |
form-control-range | As Required |
input-group-append | As Required |
input-group-prepend | As Required |
form-inline | As Required |
custom-file | As Required |
form-file | As Required |
Consolidated native and custom form elements. Checkboxes, radios, selects, and other inputs that had native and custom classes in v4 have been consolidated. Now nearly all our form elements are entirely custom, most without the need for custom HTML. Bootstrap v5.0 - Migrating to v5 - Forms
Find | Replace With |
---|---|
custom-check | form-check |
custom-switch | form-switch |
custom-select | form-select |
custom-range | form-range |
KenHaggerty.Com and the Users Without Passwords projects implement the new checkbox and radio classes. See Bootstrap-Razor-Model Checkboxes and Radio Button Groups.
Ensure the input element for all checkboxes and radios have the type attribute set. (type="checkbox" or type="radio")
Find | Replace With |
---|---|
custom-control custom-checkbox | form-check |
custom-control custom-radio | form-check |
custom-control-inline | form-check-inline |
custom-control-input | form-check-input |
custom-control-label | form-check-label |
Bootstrap v4 Checkbox:
<div class="custom-control custom-checkbox custom-control-inline"> <input class="custom-control-input" id="V4CheckboxId" /> <label class="custom-control-label" for="V4CheckboxId"> V4 Checkbox </label> </div>
Bootstrap v5 Checkboxes:
<div class="col-12 mb-2"> <div class="form-check form-check-inline"> <input type="checkbox" class="form-check-input" id="CheckboxSelectAll" /> <label class="form-check-label" for="CheckboxSelectAll"> Select All </label> </div> <div class="form-check form-check-inline"> <input type="checkbox" class="form-check-input demo" checked id="V5DebugCheckboxId" /> <label class="form-check-label" for="V5DebugCheckboxId"> Debug </label> </div> <div class="form-check form-check-inline"> <input type="checkbox" class="form-check-input demo" id="V5InformationCheckboxId" /> <label class="form-check-label" for="V5InformationCheckboxId"> Information </label> </div> <div class="form-check form-check-inline"> <input type="checkbox" class="form-check-input demo" checked id="V5WarningCheckboxId" /> <label class="form-check-label" for="V5WarningCheckboxId"> Warning </label> </div> <div class="form-check form-check-inline"> <input type="checkbox" class="form-check-input demo" id="V5ErrorCheckboxId" /> <label class="form-check-label" for="V5ErrorCheckboxId"> Error </label> </div> <div class="form-check form-check-inline"> <input type="checkbox" class="form-check-input demo" id="V5CriticalCheckboxId" /> <label class="form-check-label" for="V5CriticalCheckboxId"> Critical </label> </div> </div>
Bootstrap v4 Radio Button:
<div class="custom-control custom-radio custom-control-inline"> <input type="radio" class="custom-control-input" name="V4RadioButtonGroup" value="Debug" checked id="DebugV4RadioButtonId" /> <label class="custom-control-label" for="DebugV4RadioButtonId"> Debug </label> </div>
Bootstrap v5 Radio Button Group:
<div class="col-12"> <div class="form-check form-check-inline"> <input type="radio" class="form-check-input" name="V5RadioButtonGroup" value="Debug" checked id="DebugV5RadioButtonId" /> <label class="form-check-label" for="DebugV5RadioButtonId"> Debug </label> </div> <div class="form-check form-check-inline"> <input type="radio" class="form-check-input" name="V5RadioButtonGroup" value="Information" id="InformationV5RadioButtonId" /> <label class="form-check-label" for="InformationV5RadioButtonId"> Information </label> </div> <div class="form-check form-check-inline"> <input type="radio" class="form-check-input" name="V5RadioButtonGroup" value="Warning" id="WarningV5RadioButtonId" /> <label class="form-check-label" for="WarningV5RadioButtonId"> Warning </label> </div> <div class="form-check form-check-inline"> <input type="radio" class="form-check-input" name="V5RadioButtonGroup" value="Error" id="ErrorV5RadioButtonId" /> <label class="form-check-label" for="ErrorV5RadioButtonId"> Error </label> </div> <div class="form-check form-check-inline"> <input type="radio" class="form-check-input" name="V5RadioButtonGroup" value="Critical" id="CriticalV5RadioButtonId" /> <label class="form-check-label" for="CriticalV5RadioButtonId"> Critical </label> </div> </div>
Form labels now require .form-label. Bootstrap v5.0 - Migrating to v5 - Forms
Find All | Ensure |
---|---|
<label | form-label OR form-check-label |
Select elements require the .form-select class.
Find All | Ensure |
---|---|
<select | form-select |
Select without form-select class.
Select with form-select class.
Renamed .close to .btn-close for a less generic name. Bootstrap v5.0 - Migrating to v5 - Close button
Find | Replace With |
---|---|
close | btn-close |
Close buttons now use a background-image (embedded SVG) instead of a × in the HTML, allowing for easier customization without the need to touch your markup. Bootstrap v5.0 - Migrating to v5 - Close button
Find | Remove |
---|---|
× | Parent span |
Data attributes for all JavaScript plugins are now namespaced to help distinguish Bootstrap functionality from third parties and your own code. For example, we use data-bs-toggle instead of data-toggle. Bootstrap v5.0 - Migrating to v5 - JavaScript
Find | Replace With |
---|---|
data-dismiss | data-bs-dismiss |
data-ride | data-bs-ride |
data-interval | data-bs-interval |
data-slide | data-bs-slide |
data-target | data-bs-target |
data-toggle | data-bs-toggle |
KenHaggerty.Com and the Users Without Passwords projects implement message-modal.js which dynamically creates a modal. The dataset attributes with the bs namespace required updating. For example, messageDismissButton. dataset. dismiss = 'modal'; needs to be messageDismissButton. dataset. bsDismiss = 'modal';.
Bootstrap v4 Modal
<!-- Button trigger modal --> <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal"> Launch demo modal </button> <!-- Modal --> <div class="modal" tabindex="-1"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">Modal title</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <p>Modal body text goes here.</p> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> <button type="button" class="btn btn-primary">Save changes</button> </div> </div> </div> </div>
Bootstrap v5 Modal
<!-- Button trigger modal --> <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal"> Launch demo modal </button> <!-- Modal --> <div class="modal" tabindex="-1"> <div class="modal-dialog top-5"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">Modal title</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> <p>Modal body text goes here.</p> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button> <button type="button" class="btn btn-primary">Save changes</button> </div> </div> </div> </div>
KenHaggerty.Com overrides the modal-footer class to center buttons with a declaration in site.css.
.modal-footer { justify-content: center; }
The Users Without Passwords v4 project implements a modal-dialog.top-50 and a modal-dialog.top-100 with declarations in site.css.
.modal-dialog.top-50 { top: 50px; } .modal-dialog.top-100 { top: 100px; }
Bootstrap v5 implements a top-50 and a top-100 which override the declarations in site.css.
.top-0 { top: 0 !important; } .top-50 { top: 50% !important; } .top-100 { top: 100% !important; } .bottom-0 { bottom: 0 !important; } .bottom-50 { bottom: 50% !important; } .bottom-100 { bottom: 100% !important; } .start-0 { left: 0 !important; } .start-50 { left: 50% !important; } .start-100 { left: 100% !important; } .end-0 { right: 0 !important; } .end-50 { right: 50% !important; } .end-100 { right: 100% !important; }
KenHaggerty.Com and the Users Without Passwords projects implement a new top-5 class for modal-dialog classes with a declaration in site.css.
.modal-dialog.top-5 { top: 5%; }
KenHaggerty.Com and the Users Without Passwords projects implement Bootstrap css root variables. The variable declaration added the bs namespace. For example, --bs-primary: #0d6efd; instead of --primary: #007bff;.
Find | Replace With |
---|---|
var(-- | var(--bs- |
Bootstrap v5 root variable
<style> circle { fill: var(--bs-primary); } </style>
Dropped .text-justify class.
Bootstrap v5.0 - Migrating to v5 - Content, Reboot, etc
See
GitHub Pull - #29793 and
GitHub Issues - #29679
Find | Remove |
---|---|
text-justify | As Required |
KenHaggerty.Com and the Users Without Passwords projects implement the text-justify class for p tags with a declaration in site.css.
p.text-justify { font-size: 1.2rem; text-align: justify; }
Bootstrap v5 New breakpoint!
Added new xxl breakpoint for 1400px and up. No changes to all other breakpoints. Bootstrap v5.0 - Migrating to v5 - Grid updates
Comments(0)