Upgrading from Bootstrap v3 to v5¶
With the release of Nautobot v3.0, the UI has undergone significant improvements to enhance usability, flexibility, and maintainability. This version introduces an upgrade from Bootstrap v3.4 to Bootstrap v5.3. This transition brings modern UI enhancements, improved accessibility, and better responsiveness. While these changes provide a more consistent and intuitive user experience, they also introduce necessary modifications that may impact existing custom UI components and templates.
The following is a detailed migration guide outlining the steps to help app authors update their app's UI for compatibility with the Bootstrap upgrade. Additional changes that are needed and might not be captured here can be found in the Bootstrap 5.x migration guide.
Note
This document does not cover all the UI/UX changes brought to Bootstrap and Nautobot components. Instead, this guide scope is narrowed down to only the technicalities concerning HTML element structures and attributes, and CSS class names.
Tip
You are strongly encouraged to adopt the UI component framework. Migration can be performed incrementally on your 2.4 instance, making future upgrades easier. New features will be added exclusively to this framework. For example, the Data Compliance tab, automatic "copy" buttons in detail views, and collapsible cards or panels are already only available for models using the new UI component framework. The feature set will continue to expand over time.
Dependency management¶
Bootstrap v5.x JavaScript now uses vanilla JavaScript and jQuery dependency has been removed. For now, Nautobot will keep supporting jQuery for backward compatibility, but consider it marked as deprecated. Ensure that your custom scripts do not rely on jQuery and jQuery-based Bootstrap v3.4.1 functions.
In case you were not using any plugins and had not maintained your own custom CSS or JS code dependent on jQuery or Bootstrap v3.4.1, you don't need to do anything related to dependency management.
Otherwise, you will need to individually review whether the packages and/or modules you are using, are still compatible with Bootstrap 5.x and in case they are not, update them accordingly.
Migration Script¶
When Nautobot v3.x is installed, in addition to the nautobot-server CLI command, it now also provides a nautobot-migrate-bootstrap-v3-to-v5 CLI command. This command can be run against your App's templates directory in order to autocorrect and/or flag for manual correction many of the below-documented required changes to your CSS and HTML.
The --resize flag
The first time you run nautobot-migrate-bootstrap-v3-to-v5, you should use the --resize optional parameter, which will resize all Bootstrap column breakpoints in your templates to use the next larger breakpoint. (See Columns below for the details of why this is recommended.) This is the only part of the script that is not idempotent and should not be rerun repeatedly, as each time the script is run with --resize, it will adjust the breakpoints upward again. Therefore, on all subsequent runs of the script against your app, you should omit this parameter. Besides this special case, it is otherwise safe to run the script multiple times if desired.
You can also run the script against a single template file if desired:
When run, the script will produce verbose output documenting the files that it is changing, any files that it cannot fix up automatically in full that will need manual review, and finally a summary of the overall results:
→ object_new_team.html: 2 class replacements, 6 panel replacements,
→ metadatatype_create.html: 3 class replacements, 9 panel replacements,
→ graphqlquery_retrieve.html: 4 class replacements, 7 panel replacements,
→ role_retrieve.html: 23 class replacements, 36 panel replacements,
→ approvalworkflowdefinition_update.html: 2 class replacements, 6 panel replacements,
→ inc/configcontext_format.html: 1 class replacements,
!!! Manual review needed for nav-item fixes at:
- nautobot/extras/templates/extras/inc/configcontext_format.html - Please review manually 'btn {% if format == 'json' %}btn-primary{% else %}btn-default{% endif %}'
...
=== Global Summary ===
Total issues fixed: 417
- Class replacements: 149
- Extra-breadcrumb fixes: 0
- <li> in <ol.breadcrumb>: 5
- <li> in <ul.nav-tabs>: 6
- Panel class replacements: 257
- Resizing breakpoint xs: 0
-------------------------------------
- Resizing other breakpoints: 0
In the case of the above output snippet, you can see that while the script fixed 417 migration issues automatically, it encountered some uncertainty in nautobot/extras/templates/extras/inc/configcontext_format.html, likely due to the Django template logic wrapping the btn-primary and btn-default classes. In this case you'd (as documented below in Buttons) likely want to manually replace the btn-default case with btn-secondary.
Note
The nautobot-migrate-bootstrap-v3-to-v5 also, by default, calls the nautobot-migrate-deprecated-templates script to replace deprecated template references found in your HTML files. You can skip this additional step by using the --skip-template-replacement flag. For more details on the deprecated template script, see Deprecated Templates.
Note
The nautobot-migrate-bootstrap-v3-to-v5 also, by default, does not check HTML in Python files. You can enable this check with --check-python-files flag.
Full table of Bootstrap v3 to v5 and Nautobot UI API changes
| Bootstrap v3 | Bootstrap v5 | Search Regex |
|---|---|---|
| btn-default | btn-secondary | ("|')([^"']*)(?<=\s|"|')btn-default(?=\s|"|')([^"']*)("|') |
| btn-lg | btn | ("|')([^"']*)(?<=\s|"|')btn-lg(?=\s|"|')([^"']*)("|') |
| btn-xs | btn-sm | ("|')([^"']*)(?<=\s|"|')btn-xs(?=\s|"|')([^"']*)("|') |
| caret | mdi mdi-chevron-down | ("|')([^"']*)(?<=\s|"|')caret(?=\s|"|')([^"']*)("|') |
| center-block | d-block mx-auto | ("|')([^"']*)(?<=\s|"|')center-block(?=\s|"|')([^"']*)("|') |
| checkbox | form-check | (?<!type=)("|')([^"']*)(?<=\s|"|')checkbox(?=\s|"|')([^"']*)("|') |
| checkbox-inline | form-check-input | ("|')([^"']*)(?<=\s|"|')checkbox-inline(?=\s|"|')([^"']*)("|') |
| close | btn-close | (?<=class=)("|')([^"']*)(?<=\s|"|')close(?=\s|"|')([^"']*)("|') |
| col--offset- | offset-- | ("|')([^"']*)(?<=\s|"|')col-(xs|sm|md|lg|x?xl)-offset-\d{1,2}(?=\s|"|')([^"']*)("|') |
| control-label | col-form-label | ("|')([^"']*)(?<=\s|"|')control-label(?=\s|"|')([^"']*)("|') |
| dropdown-menu-left | dropdown-menu-start | ("|')([^"']*)(?<=\s|"|')dropdown-menu-left(?=\s|"|')([^"']*)("|') |
| dropdown-menu-right | dropdown-menu-end | ("|')([^"']*)(?<=\s|"|')dropdown-menu-right(?=\s|"|')([^"']*)("|') |
| form-control-static | form-control-plaintext | ("|')([^"']*)(?<=\s|"|')form-control-static(?=\s|"|')([^"']*)("|') |
| form-group | mb-10 d-flex justify-content-center | ("|')([^"']*)(?<=\s|"|')form-group(?=\s|"|')([^"']*)("|') |
| help-block | form-text | ("|')([^"']*)(?<=\s|"|')help-block(?=\s|"|')([^"']*)("|') |
| hidden | d-none | (?<!type=)("|')([^"']*)(?<=\s|"|')hidden(?=\s|"|')([^"']*)("|') |
| label | badge | (?<=class=)("|')([^"']*)(?<=\s|"|')label(?=\s|"|')([^"']*)("|') |
| label-default | bg-default | ("|')([^"']*)(?<=\s|"|')label-default(?=\s|"|')([^"']*)("|') |
| label-danger | bg-danger | ("|')([^"']*)(?<=\s|"|')label-danger(?=\s|"|')([^"']*)("|') |
| label-info | bg-info | ("|')([^"']*)(?<=\s|"|')label-info(?=\s|"|')([^"']*)("|') |
| label-primary | bg-primary | ("|')([^"']*)(?<=\s|"|')label-primary(?=\s|"|')([^"']*)("|') |
| label-success | bg-success | ("|')([^"']*)(?<=\s|"|')label-success(?=\s|"|')([^"']*)("|') |
| label-transparent | bg-transparent | ("|')([^"']*)(?<=\s|"|')label-transparent(?=\s|"|')([^"']*)("|') |
| label-warning | bg-warning | ("|')([^"']*)(?<=\s|"|')label-warning(?=\s|"|')([^"']*)("|') |
| noprint | d-print-none | ("|')([^"']*)(?<=\s|"|')noprint(?=\s|"|')([^"']*)("|') |
| panel | card | ("|')([^"']*)(?<=\s|"|')panel(?=\s|"|')([^"']*)("|') |
| panel-body | card-body | ("|')([^"']*)(?<=\s|"|')panel-body(?=\s|"|')([^"']*)("|') |
| panel-footer | card-footer | ("|')([^"']*)(?<=\s|"|')panel-footer(?=\s|"|')([^"']*)("|') |
| panel-heading | card-header | ("|')([^"']*)(?<=\s|"|')panel-heading(?=\s|"|')([^"']*)("|') |
| pull-left | float-start | ("|')([^"']*)(?<=\s|"|')pull-left(?=\s|"|')([^"']*)("|') |
| pull-right | float-end | ("|')([^"']*)(?<=\s|"|')pull-right(?=\s|"|')([^"']*)("|') |
| sr-only | visually-hidden | ("|')([^"']*)(?<=\s|"|')sr-only(?=\s|"|')([^"']*)("|') |
| sr-only-focusable | visually-hidden-focusable | ("|')([^"']*)(?<=\s|"|')sr-only-focusable(?=\s|"|')([^"']*)("|') |
| text-left | text-start | ("|')([^"']*)(?<=\s|"|')text-left(?=\s|"|')([^"']*)("|') |
| text-muted | text-secondary | ("|')([^"']*)(?<=\s|"|')text-muted(?=\s|"|')([^"']*)("|') |
| text-right | text-end | ("|')([^"']*)(?<=\s|"|')text-right(?=\s|"|')([^"']*)("|') |
| accordion-toggle | nb-collapse-toggle | ("|')([^"']*)(?<=\s|"|')accordion-toggle(?=\s|"|')([^"']*)("|') |
| accordion-toggle-all | data-nb-toggle | ("|')([^"']*)(?<=\s|"|')accordion-toggle-all(?=\s|"|')([^"']*)("|') |
| banner-bottom | nb-banner-bottom | ("|')([^"']*)(?<=\s|"|')banner-bottom(?=\s|"|')([^"']*)("|') |
| btn-inline | nb-btn-inline-hover | ("|')([^"']*)(?<=\s|"|')btn-inline(?=\s|"|')([^"']*)("|') |
| color-block | nb-color-block | ("|')([^"']*)(?<=\s|"|')color-block(?=\s|"|')([^"']*)("|') |
| description | nb-description | (?<=class=)("|')([^"']*)(?<=\s|"|')description(?=\s|"|')([^"']*)("|') |
| editor-container | nb-editor-container | ("|')([^"']*)(?<=\s|"|')editor-container(?=\s|"|')([^"']*)("|') |
| loading | nb-loading | ("|')([^"']*)(?<=\s|"|')loading(?=\s|"|')([^"']*)("|') |
| report-stats | nb-report-stats | ("|')([^"']*)(?<=\s|"|')report-stats(?=\s|"|')([^"']*)("|') |
| required | nb-required | ("|')([^"']*)(?<=\s|"|')required(?=\s|"|')([^"']*)("|') |
| right-side-panel | nb-right-side-panel | ("|')([^"']*)(?<=\s|"|')right-side-panel(?=\s|"|')([^"']*)("|') |
| software-image-hierarchy | nb-software-image-hierarchy | ("|')([^"']*)(?<=\s|"|')software-image-hierarchy(?=\s|"|')([^"']*)("|') |
| style-line | nb-style-line | ("|')([^"']*)(?<=\s|"|')style-line(?=\s|"|')([^"']*)("|') |
| table-headings | nb-table-headings | ("|')([^"']*)(?<=\s|"|')table-headings(?=\s|"|')([^"']*)("|') |
| tile | nb-tile | ("|')([^"']*)(?<=\s|"|')tile(?=\s|"|')([^"']*)("|') |
| tile-description | nb-tile-description | ("|')([^"']*)(?<=\s|"|')tile-description(?=\s|"|')([^"']*)("|') |
| tile-footer | nb-tile-footer | ("|')([^"']*)(?<=\s|"|')tile-footer(?=\s|"|')([^"']*)("|') |
| tile-header | nb-tile-header | ("|')([^"']*)(?<=\s|"|')tile-header(?=\s|"|')([^"']*)("|') |
| tiles | nb-tiles | ("|')([^"']*)(?<=\s|"|')tiles(?=\s|"|')([^"']*)("|') |
| tree-hierarchy | nb-tree-hierarchy | ("|')([^"']*)(?<=\s|"|')tree-hierarchy(?=\s|"|')([^"']*)("|') |
| filter-container | removed | ("|')([^"']*)(?<=\s|"|')filter-container(?=\s|"|')([^"']*)("|') |
| data-backdrop | data-bs-backdrop | data-backdrop |
| data-dismiss | data-bs-dismiss | data-dismiss |
| data-target | data-bs-target | data-target |
| data-title | data-bs-title | data-title |
| data-toggle | data-bs-toggle | data-toggle |
| Breadcrumbs, Dropdowns, Tabs | breadcrumb-item, dropdown-item, nav-item, nav-link | (?s)<li((?!<li|</li>|breadcrumb-item).)*(?=<a|<button)((?!<li|</li>|breadcrumb-item|dropdown-item|nav-item|nav-link).)*</li> |
Overview of High-Level Changes¶
Bootstrap data-* attributes¶
In Bootstrap v5.x, some reused native HTML attributes became data-* attributes for less ambiguity. In addition to that, all custom Bootstrap data-* attributes are prefixed with an additional bs- for even more clarity. For example, data-toggle="collapse" is now data-bs-toggle="collapse", and Tooltip's title attribute has been changed to data-bs-title.
| Bootstrap v3 | Bootstrap v5 |
|---|---|
data-backdrop |
data-bs-backdrop |
data-dismiss |
data-bs-dismiss |
data-target |
data-bs-target |
data-title |
data-bs-title |
data-toggle |
data-bs-toggle |
<a class="btn btn-primary" data-toggle="collapse" href="#collapse" role="button" aria-expanded="false" aria-controls="collapse">Toggle collapse</a>
<button type="button" class="btn btn-default" data-toggle="tooltip" title="Custom tooltip">Custom tooltip</button>
<button data-toggle="modal" data-target="#myModal">Open Modal</button>
<button class="close" data-dismiss="alert">×</button>
<a class="btn btn-primary" data-bs-toggle="collapse" href="#collapse" role="button" aria-expanded="false" aria-controls="collapse">Toggle collapse</a>
<button type="button" class="btn btn-secondary" data-bs-toggle="tooltip" data-bs-title="Custom tooltip">Custom tooltip</button>
<button data-bs-toggle="modal" data-bs-target="#myModal">Open Modal</button>
<button class="btn-close" data-bs-dismiss="alert"></button>
Helper classes / Helpers and Utilities¶
One major difference between Bootstrap v3 and v5 is that Helper classes no longer exist. Instead, they were replaced with Helpers and Utilities which offer far more comprehensive set of CSS classes for styling elements on the page without having to write custom CSS. Below is a table with helpers and utilities that correspond to former helper classes for a quick search-and-replace reference. Items not listed here did not change and can be left as-is.
| Helper class | Utility |
|---|---|
text-muted |
text-secondary |
text-left |
text-start |
text-right |
text-end |
close |
btn-close (technically speaking, close button is a component now, not a helper or utility) |
caret |
removed, use an icon from icon library instead |
pull-left |
float-start |
pull-right |
float-end |
center-block |
d-block mx-auto (consider using flexbox for content centering) |
show |
d-block |
hidden |
d-none |
sr-only |
visually-hidden |
sr-only-focusable |
visually-hidden-focusable (must not be used in combination with the visually-hidden class) |
text-hide |
removed, as per Bootstrap v5.0 documentation: "it’s an antiquated method for hiding text that shouldn’t be used anymore" |
It is highly encouraged to at least briefly familiarize with Bootstrap v5.x documentation on Helpers and Utilities and the array of possibilities they provide, because in many cases they can relieve developers from the burden of writing custom CSS code. At the same time, mind that not all default Bootstrap maps can be treated as source of truth, there are several Nautobot overwrites which, most notably, include spacing.
Spacing (i.e. margins and paddings)¶
To avoid unnecessary mapping of abstract to pixel values, Nautobot defines spacing sizes in straightforward concrete pixel values. On one hand it requires developers to think about pixels rather than semantic meaning of a particular spacing but on the other, there really are no spacing guidelines for Bootstrap nor Nautobot, so these abstract names would be arbitrary and made up anyway. Available sizes are:
0: 0
1: 1px
2: 2px
4: 4px
6: 6px
8: 8px
10: 10px
12: 12px
14: 14px
16: 16px
20: 20px
24: 24px
auto: auto
Negative margins are also supported. They require preceding requested size with an n.
Example:
<div class="p-4"></div> <!-- padding: 4px; -->
<div class="px-10"></div> <!-- padding-left: 10px; padding-right: 10px; -->
<div class="my-n8"></div> <!-- margin-bottom: -8px; margin-top: -8px; -->
Note
Everything presented in this section was simplified for the default font size equal to 16px. Were this value overwritten, for accessibility concerns Bootstrap and Nautobot define all sizes in rem units, which scale in relation to document root font size, a practice also recommended for app developers.
Grid¶
Note
It is recommended that instead of using float-start and float-end classes, you should use the grid system in Bootstrap v5.x for a more structured approach to positioning elements and layout.
- Bootstrap v5.x now has
position-relative,position-absolute, etc. to help you to position elements on the page. - Bootstrap v3.4.1 grid system:
- Uses 12-column grid system.
- Requires explicit breakpoint prefixes (
xs,sm,md,lg). - Column widths are fixed per breakpoint.
col-*-offset-*classes control horizontal positioning.
- Bootstrap v5.x grid system:
- No more
xsbreakpoint. - Uses
col-*auto-sizing if not specified (no need for exact column width). - Specifies
gutterwidth viag-*classes. - Specifies column horizontal offset with
offset-*, though other new utilities are available to control positioning as well and may be preferable.
- No more
Above is a short summary for the positioning and layout changes in Bootstrap v5.x, see more details in the Bootstrap v5.x documentation about columns, float, and position.
Grid - best practices¶
- Use
col-lg-*instead ofcol-md-*to have better support for narrow view ports. On larger screens it will fill page with defined size, but belowlgit will fill the 100% width. - You can use
nb-lg-max-widthto limit the max width to the size oflgviewport. Then you don't need to specifycol-xl-*orcol-xxl-*sizes to limit the width on 4k or wide screens. - For non-full-width boxes like error information, some confirmation site, that should be in "modal" format please use fine-grained col sizes. For example
col-sm-12 col-md-9 col-lg-7along withnb-lg-max-width. - Use
justify-content-centerclass on the<div class="row">container, instead of specifyingoffset-lg-*to center the columns. This may lead to centering issues or overflowing columns when offset is miscalculated or set to the different viewport thancol-*-*definition.
Responsive utilities¶
Bootstrap v3.4.1 shipped with Responsive utilities which provided simple mechanisms to display and hide elements on various screen sizes and for print. Bootstrap v5.x takes this idea a step further and delivers media breakpoints for all Helpers and Utilities, no longer constraining responsive utility classes to an arbitrary set.
- Breakpoint values and names have changed, refer to Bootstrap v3.4.1 breakpoints and Bootstrap v5.x breakpoints for more detail.
xsbreakpoint no longer exists (at least not in CSS class names). It is a result of Bootstrap v5.x (and web, in general) mobile-first approach which defaults layouts to the smallest breakpoint available and goes up from there. Do not worry, it does not mean you have to support mobile layouts. But in case you do, see how isxsmigrated in examples below.hidden-xsis replaced byd-block d-sm-none(hide on extra small). Note the change fromxstosmdue to the change in layout breakpoint sizes in Bootstrap v5.visible-xsis replaced byd-none d-sm-block(show on extra small).
Guidance on Specific Cases¶
Breadcrumbs¶
In general you may want to migrate to defining your breadcrumbs in the Python view code instead of defining them directly in an HTML template. If your breadcrumbs are still defined in HTML, the following changes are needed:
- Breadcrumb item is changed from
<li>to<li class="breadcrumb-item">. - Active breadcrumb item is changed from
<li class="active">Data</li>to<li class="breadcrumb-item active" aria-current="page">Data</li>.
Buttons¶
btn-defaultis replaced bybtn-secondary. Nautobot will keep supportingbtn-defaultclass, nevertheless it is recommended to replace oldbtn-defaultclass name withbtn-secondary.btn-xs(extra small) is removed; usebtn-smas the smallest size. Similarly tobtn-defaultandbtn-secondary, Nautobot will keep supportingbtn-xsclass but despite its name, it looks and behaves exactly the same asbtn-sm.closeis replaced bybtn-closeas mentioned above in Helper classes / Helpers and Utilities.
Columns¶
See more details in the Bootstrap v5.x documentation about columns, but generally speaking you'll need to make two types of changes to your column definitions:
- Increase to the next larger breakpoint (see note below).
- Replace
col-<breakpoint>-offset-<amount>withoffset-<breakpoint>-<amount>.
Generally increase column breakpoints by one stage when migrating
A subtle change between Bootstrap v3 and v5 columns, in addition to the removal of xs, is that the other grid breakpoints have generally changed. For example, in v3, a col-sm-4 would apply to windows up to 768px in size, but in v5, col-sm-4 applies only up to 576px in size while col-md-4 applies to windows between 577px and 768px. The net result of this change is that in general you will want to adjust all size-specific column definitions "up" one size increment, so col-sm-* becomes col-md-*, col-md-* becomes col-lg-*, etc.
That said, you may also want to refer to the Bootstrap v5 docs linked above to see if you can simplify your HTML/CSS classes to achieve the desired results more simply with the new grid features in Bootstrap v5.
Dropdowns¶
Complete Bootstrap 5.x dropdowns documentation can be found at: https://getbootstrap.com/docs/5.3/components/dropdowns/.
In Bootstrap v3.4.1, dropdowns were kind of second class citizens, missing out much on configurability mainly due to just a handful of dedicated classes. Bootstrap v5.x amends that and to some extent redefines dropdown HTML structure and attributes, and CSS classes.
Differences include:
- Dropdown wrapper component is no longer of class
btn-groupbutdropdowninstead. - Dropdown toggle button
data-toggleattribute has been renamed todata-bs-toggle, andaria-haspopupattribute is no longer recommended. - As already mentioned in Helper classes / Helpers and Utilities section above, if dropdown toggle button used
caretelement, it must be replaced by an icon from available icon library. - Likewise, if dropdown toggle button used a descriptive text of class
sr-only, it should be changed tovisually-hidden. - List items do not expect any particular CSS class but elements within them do. This is especially relevant for separators (dividers).
- Clickable items (mainly
buttonandaelements) should be ofdropdown-itemclass. - Separators (dividers) should be
hrelements withdropdown-dividerclass.
Let's take a look at this example from Bootstrap v3.4.1 Single button dropdowns documentation and how to migrate it over to Bootstrap v5.x:
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Action <span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</div>
<div class="dropdown">
<button type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
Action <span class="mdi mdi-chevron-down"></span>
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><a href="#" class="dropdown-item">Action</a></li>
<li><a href="#" class="dropdown-item">Another action</a></li>
<li><a href="#" class="dropdown-item">Something else here</a></li>
<li><hr class="dropdown-divider"></li>
<li><a href="#" class="dropdown-item">Separated link</a></li>
</ul>
</div>
Forms¶
- Class
form-groupis removed; in most Nautobot model forms it should be replaced bymb-10 d-flex justify-content-center.- In the specific case of "drawer" forms (filter forms, table config, etc.), where limited horizontal space is available, you can use class
nb-form-groupinstead.
- In the specific case of "drawer" forms (filter forms, table config, etc.), where limited horizontal space is available, you can use class
- Class
control-labelis removed; in most Nautobot model forms it should be replaced bycol-form-label(https://getbootstrap.com/docs/5.3/forms/layout/#horizontal-form).- In the specific case of "drawer" forms using
nb-form-group, you should use classform-labelinstead (https://getbootstrap.com/docs/5.3/migration/#forms-1).
- In the specific case of "drawer" forms using
- Class
form-control-staticis replaced byform-control-plaintext. - Class
help-blockis replaced byform-text. - Classes
checkboxandcheckbox-inlineare removed; useform-checkandform-check-inputinstead: https://getbootstrap.com/docs/5.3/forms/checks-radios/#checks. - Required form fields should use class
nb-requiredon theirlabelelement.
Labels / Badges¶
labelis replaced withbadge.- The contextual classes (e.g.
label-primary,label-success) now use the general-purpose classes (bg-primary,bg-success, etc.).
Horizontal rules¶
By default, Horizontal rules inherit their color from text. To draw a line with standard Nautobot border color, use border-top CSS class on the <hr> element.
<!-- Inherit color from text. -->
<hr>
<!-- Set color to standard Nautobot border color. -->
<hr class="border-top">
Paginators¶
page-itemclass needs to be applied to<li>elements.page-linkclass needs to be applied to<a>elements.activeanddisabledclasses are now applied to outerpage-itemelement (<li>) instead of innerpage-link(<a>).- Replace icons with HTML character entities:
<i class="mdi mdi-chevron-double-left"></i>with<span aria-hidden="true">«</span>.<i class="mdi mdi-chevron-double-right"></i>with<span aria-hidden="true">»</span>.
<ul class="pagination">
<li class="page-item disabled"><a class="page-link" href="#" aria-disabled="true"><span aria-hidden="true">«</span></a></li>
<li class="page-item active" aria-current="page"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item"><a class="page-link" href="#"><span aria-hidden="true">»</span></a></li>
</ul>
Panels / Cards¶
panelclass is no longer available, usecardinstead.panel-headingclass is replaced bycard-header.panel-bodyclass is replaced bycard-body. Note thatcard-bodyis not required ascardchild and does not have any functional nor semantic meaning on its own, use it whenever you need a padded section within a card.panel-footerclass is replaced bycard-footer.panel-defaultandpanel-primaryclasses are replaced by a combination ofborder-*andbg-*applied tocardandcard-header.<div class="panel panel-default">is replaced by<div class="card">without additional classes.
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Panel Title</h3>
</div>
<div class="panel-body">
Panel content goes here.
</div>
<div class="panel-footer">Panel Footer</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Panel Title</h3>
</div>
<div class="panel-body">
Panel content goes here.
</div>
<div class="panel-footer">Panel Footer</div>
</div>
<div class="card">
<div class="card-header">
<h5 class="card-title">Panel Title</h5>
</div>
<div class="card-body">
Panel content goes here.
</div>
<div class="card-footer">Panel Footer</div>
</div>
<div class="card border-primary">
<div class="card-header bg-primary text-white">
<h5 class="card-title">Panel Title</h5>
</div>
<div class="card-body">
Panel content goes here.
</div>
<div class="card-footer">Panel Footer</div>
</div>
Tabs¶
nav-itemclass is now required for each<li>.nav-linkclass must be applied to clickable<a>and<button> elements.activeclass must be applied to the innernav-linkelement (<a>,<button>) instead ofnav-item(<li>).
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item" role="presentation">
<a class="nav-link active" href="#home">Home</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" href="#profile">Profile</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" href="#messages">Messages</a>
</li>
</ul>
Additional Considerations¶
We have covered in detail the common patterns leveraged within the Nautobot ecosystem. While most implementations will follow these patterns, some may have take a more custom approach. Although we cannot address every possible scenario, here are a few additional considerations:
- JavaScript or custom CSS selectors may have changed and could require updates.
- Some Bootstrap primitives or components used in your scripts may no longer exist or have been renamed.
- Review any custom integrations or third-party plugins for compatibility with Bootstrap v5.
- Test your UI thoroughly to ensure all interactive elements and styles function as expected after migration.