Compare commits

...

9 Commits

Author SHA1 Message Date
Mark Otto 7f61dceb0a Bump version number, fix extra deps 2025-09-26 14:55:20 -07:00
Mark Otto 166d5e7a13 Update v6 to Floating UI 2025-09-26 14:55:20 -07:00
Mark Otto 4fecde40b8 v6: New lg, xl, and 2xl breakpoints, plus some renaming (#41770)
* Update xxl breakpoint and container, rename xxl to 2xl for better scaling

Co-Authored-By: mdo <98681+mdo@users.noreply.github.com>

* note for lg

* bump bundlewatch

---------

Co-authored-by: mdo <98681+mdo@users.noreply.github.com>
2025-09-26 14:52:16 -07:00
Mark Otto 5a54f29ae3 Start to redo generate-utility() (#41769)
* Start to redo generate-utility()

* fixes

* bundlewatch
2025-09-26 14:52:06 -07:00
Mark Otto f9c8e96f70 WIP: New form controls (#41740)
* New form controls

* Split Sass, update docs

* More migration docs

* basic migration, update changelog

* Bring back btn-check for now, but move to button stylesheet

* note

* Fix link

* lint
2025-09-24 11:54:21 -07:00
Mark Otto f0c163b917 Use @forward instead of @use for proper customization (#41762)
* Use `@forward` instead of `@use` for proper customization

* linty linterson

* woof
2025-09-23 23:10:02 -07:00
Mark Otto 956de4bbaf v6 Migration guide (#41683)
* wip

* More updates
2025-09-22 21:54:18 -07:00
Mark Otto c8e8d28d29 v6: Add sub-groups to Utilities docs (#41758)
* Split the flex.mdx file into separate pages

* Add subgroups to docs utils nav

* More new groups, split pages

* Update MDX linter

* fixes
2025-09-22 11:55:12 -07:00
Mark Otto 482b0eb333 v6: justify-items and place-items utilities (#41757)
* Add utilities for place-items and justify-items

* bump
2025-09-22 10:12:07 -07:00
96 changed files with 3894 additions and 3127 deletions
+4 -4
View File
@@ -2,11 +2,11 @@
"files": [
{
"path": "./dist/css/bootstrap-grid.css",
"maxSize": "7.5 kB"
"maxSize": "7.75 kB"
},
{
"path": "./dist/css/bootstrap-grid.min.css",
"maxSize": "6.75 kB"
"maxSize": "7.00 kB"
},
{
"path": "./dist/css/bootstrap-reboot.css",
@@ -26,11 +26,11 @@
},
{
"path": "./dist/css/bootstrap.css",
"maxSize": "35.75 kB"
"maxSize": "36.0 kB"
},
{
"path": "./dist/css/bootstrap.min.css",
"maxSize": "31.5 kB"
"maxSize": "32.0 kB"
},
{
"path": "./dist/js/bootstrap.bundle.js",
+1
View File
@@ -21,6 +21,7 @@
"callout",
"callouts",
"camelCase",
"checkgroup",
"clearfix",
"Codesniffer",
"combinator",
+2 -1
View File
@@ -1,6 +1,7 @@
{
"default": true,
"MD004": { "style": "dash" },
"MD011": false,
"MD013": false,
"MD024": false,
"MD025": false,
@@ -14,4 +15,4 @@
"MD046": false,
"line-length": false,
"no-inline-html": false
}
}
+2 -2
View File
@@ -42,8 +42,8 @@ const files = [
configPropertyName: 'js_bundle_hash'
},
{
file: 'node_modules/@popperjs/core/dist/umd/popper.min.js',
configPropertyName: 'popper_hash'
file: 'node_modules/@floating-ui/dom/dist/floating-ui.dom.umd.min.js',
configPropertyName: 'floating_ui_hash'
}
]
+4 -4
View File
@@ -12,7 +12,7 @@ const BUNDLE = process.env.BUNDLE === 'true'
const ESM = process.env.ESM === 'true'
let destinationFile = `bootstrap${ESM ? '.esm' : ''}`
const external = ['@popperjs/core']
const external = ['@floating-ui/dom']
const plugins = [
babel({
// Only transpile our source code
@@ -22,14 +22,14 @@ const plugins = [
})
]
const globals = {
'@popperjs/core': 'Popper'
'@floating-ui/dom': 'FloatingUIDOM'
}
if (BUNDLE) {
destinationFile += '.bundle'
// Remove last entry in external array to bundle Popper
// Remove last entry in external array to bundle FloatingUI
external.pop()
delete globals['@popperjs/core']
delete globals['@floating-ui/dom']
plugins.push(
replace({
'process.env.NODE_ENV': '"production"',
+3 -3
View File
@@ -42,9 +42,9 @@ cdn:
js_hash: "sha384-G/EV+4j2dNv+tEPo3++6LCgdCROaejBqfUeNjuKAiuXbjrxilcCdDz6ZAVfHWe1Y"
js_bundle: "https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"
js_bundle_hash: "sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI"
popper: "https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js"
popper_hash: "sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r"
popper_esm: "https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/esm/popper.min.js"
floating_ui: "https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.6.12/dist/floating-ui.dom.umd.min.js"
floating_ui_hash: "sha384-Os8n9bzoYJ/ESbGD7cW0VOTLk0hO++SO+Y4swXBE2dHrxiZkjADEr5ZGOcc9CorD"
floating_ui_esm: "https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.6.12/dist/floating-ui.dom.min.js"
anchors:
min: 2
+35 -121
View File
@@ -5,21 +5,18 @@
* --------------------------------------------------------------------------
*/
import * as Popper from '@popperjs/core'
import { inline, offset, shift } from '@floating-ui/dom'
import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler.js'
import Manipulator from './dom/manipulator.js'
import SelectorEngine from './dom/selector-engine.js'
import {
execute,
getElement,
getNextActiveElement,
isDisabled,
isElement,
isRTL,
isVisible,
noop
} from './util/index.js'
import FloatingUi from './util/floating-ui.js'
/**
* Constants
@@ -58,30 +55,28 @@ const SELECTOR_NAVBAR = '.navbar'
const SELECTOR_NAVBAR_NAV = '.navbar-nav'
const SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'
const PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start'
const PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end'
const PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start'
const PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end'
const PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start'
const PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start'
const PLACEMENT_TOPCENTER = 'top'
const PLACEMENT_TOPEND = 'top-end'
const PLACEMENT_TOP = 'top-start'
const PLACEMENT_BOTTOMCENTER = 'bottom'
const PLACEMENT_BOTTOMEND = 'bottom-end'
const PLACEMENT_BOTTOM = 'bottom-start'
const PLACEMENT_RIGHT = 'right-start'
const PLACEMENT_LEFT = 'left-start'
const Default = {
autoClose: true,
boundary: 'clippingParents',
display: 'dynamic',
offset: [0, 2],
popperConfig: null,
offset: 10,
positionConfig: null,
reference: 'toggle'
}
const DefaultType = {
autoClose: '(boolean|string)',
boundary: '(string|element)',
display: 'string',
offset: '(array|string|function)',
popperConfig: '(null|object|function)',
offset: '(number|array|string|function)',
positionConfig: '(null|object|function)',
reference: '(string|element|object)'
}
@@ -93,13 +88,12 @@ class Dropdown extends BaseComponent {
constructor(element, config) {
super(element, config)
this._popper = null
this._parent = this._element.parentNode // dropdown wrapper
// TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/
this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] ||
SelectorEngine.prev(this._element, SELECTOR_MENU)[0] ||
SelectorEngine.findOne(SELECTOR_MENU, this._parent)
this._inNavbar = this._detectNavbar()
this._positionHelper = new FloatingUi(this._element)
}
// Getters
@@ -135,7 +129,7 @@ class Dropdown extends BaseComponent {
return
}
this._createPopper()
this.update()
// If this is a touch-enabled device we add extra
// empty mouseover listeners to the body's immediate children;
@@ -167,19 +161,9 @@ class Dropdown extends BaseComponent {
this._completeHide(relatedTarget)
}
dispose() {
if (this._popper) {
this._popper.destroy()
}
super.dispose()
}
update() {
this._inNavbar = this._detectNavbar()
if (this._popper) {
this._popper.update()
}
const reference = this._positionHelper.getReferenceElement(this._config.reference, this._parent, NAME)
this._positionHelper.calculate(reference, this._menu, this._getFloatingUiConfig())
}
// Private
@@ -197,47 +181,28 @@ class Dropdown extends BaseComponent {
}
}
if (this._popper) {
this._popper.destroy()
}
this._menu.classList.remove(CLASS_NAME_SHOW)
this._element.classList.remove(CLASS_NAME_SHOW)
this._element.setAttribute('aria-expanded', 'false')
Manipulator.removeDataAttribute(this._menu, 'popper')
this._positionHelper.stop()
EventHandler.trigger(this._element, EVENT_HIDDEN, relatedTarget)
}
_getConfig(config) {
config = super._getConfig(config)
if (typeof config.reference === 'object' && !isElement(config.reference) &&
typeof config.reference.getBoundingClientRect !== 'function'
) {
// Popper virtual elements require a getBoundingClientRect method
throw new TypeError(`${NAME.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`)
_getFloatingUiConfig() {
const defaultBsConfig = {
placement: this._getPlacement(),
middleware: [offset(this._positionHelper.parseOffset(this._config.offset)), shift()]
}
return config
}
_createPopper() {
if (typeof Popper === 'undefined') {
throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org/docs/v2/)')
// Disable positioning if we have a static display or Dropdown is in Navbar
if (this._detectNavbar() || this._config.display === 'static') {
defaultBsConfig.middleware.push(inline())
}
let referenceElement = this._element
if (this._config.reference === 'parent') {
referenceElement = this._parent
} else if (isElement(this._config.reference)) {
referenceElement = getElement(this._config.reference)
} else if (typeof this._config.reference === 'object') {
referenceElement = this._config.reference
return {
...defaultBsConfig,
...execute(this._config.positionConfig, [undefined, defaultBsConfig])
}
const popperConfig = this._getPopperConfig()
this._popper = Popper.createPopper(referenceElement, this._menu, popperConfig)
}
_isShown() {
@@ -247,20 +212,15 @@ class Dropdown extends BaseComponent {
_getPlacement() {
const parentDropdown = this._parent
if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) {
return PLACEMENT_RIGHT
const matches = {
[CLASS_NAME_DROPEND]: PLACEMENT_RIGHT,
[CLASS_NAME_DROPSTART]: PLACEMENT_LEFT,
[CLASS_NAME_DROPUP_CENTER]: PLACEMENT_TOPCENTER,
[CLASS_NAME_DROPDOWN_CENTER]: PLACEMENT_BOTTOMCENTER
}
if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) {
return PLACEMENT_LEFT
}
if (parentDropdown.classList.contains(CLASS_NAME_DROPUP_CENTER)) {
return PLACEMENT_TOPCENTER
}
if (parentDropdown.classList.contains(CLASS_NAME_DROPDOWN_CENTER)) {
return PLACEMENT_BOTTOMCENTER
const match = Object.keys(matches).find(keyClass => parentDropdown.classList.contains(keyClass))
if (match) {
return matches[match]
}
// We need to trim the value because custom properties can also include spaces
@@ -277,52 +237,6 @@ class Dropdown extends BaseComponent {
return this._element.closest(SELECTOR_NAVBAR) !== null
}
_getOffset() {
const { offset } = this._config
if (typeof offset === 'string') {
return offset.split(',').map(value => Number.parseInt(value, 10))
}
if (typeof offset === 'function') {
return popperData => offset(popperData, this._element)
}
return offset
}
_getPopperConfig() {
const defaultBsPopperConfig = {
placement: this._getPlacement(),
modifiers: [{
name: 'preventOverflow',
options: {
boundary: this._config.boundary
}
},
{
name: 'offset',
options: {
offset: this._getOffset()
}
}]
}
// Disable Popper if we have a static display or Dropdown is in Navbar
if (this._inNavbar || this._config.display === 'static') {
Manipulator.setDataAttribute(this._menu, 'popper', 'static') // TODO: v6 remove
defaultBsPopperConfig.modifiers = [{
name: 'applyStyles',
enabled: false
}]
}
return {
...defaultBsPopperConfig,
...execute(this._config.popperConfig, [undefined, defaultBsPopperConfig])
}
}
_selectMenuItem({ key, target }) {
const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => isVisible(element))
+2 -1
View File
@@ -22,9 +22,10 @@ const Default = {
offset: [0, 8],
placement: 'right',
template: '<div class="popover" role="tooltip">' +
'<div class="popover-arrow"></div>' +
'<div class="popover-inner">' +
'<h3 class="popover-header"></h3>' +
'<div class="popover-body"></div>' +
'</div>' +
'</div>',
trigger: 'click'
}
+53 -116
View File
@@ -5,15 +5,18 @@
* --------------------------------------------------------------------------
*/
import * as Popper from '@popperjs/core'
import {
flip, hide, offset, shift
} from '@floating-ui/dom'
import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler.js'
import Manipulator from './dom/manipulator.js'
import {
execute, findShadowRoot, getElement, getUID, isRTL, noop
execute, findShadowRoot, getElement, getUID, isVisible, noop
} from './util/index.js'
import Manipulator from './dom/manipulator.js'
import { DefaultAllowlist } from './util/sanitizer.js'
import TemplateFactory from './util/template-factory.js'
import FloatingUi from './util/floating-ui.js'
/**
* Constants
@@ -50,30 +53,28 @@ const EVENT_MOUSELEAVE = 'mouseleave'
const AttachmentMap = {
AUTO: 'auto',
TOP: 'top',
RIGHT: isRTL() ? 'left' : 'right',
RIGHT: 'right',
BOTTOM: 'bottom',
LEFT: isRTL() ? 'right' : 'left'
LEFT: 'left'
}
const Default = {
allowList: DefaultAllowlist,
animation: true,
boundary: 'clippingParents',
container: false,
customClass: '',
delay: 0,
fallbackPlacements: ['top', 'right', 'bottom', 'left'],
html: false,
offset: [0, 6],
offset: 0,
placement: 'top',
popperConfig: null,
positionConfig: null,
sanitize: true,
sanitizeFn: null,
selector: false,
template: '<div class="tooltip" role="tooltip">' +
'<div class="tooltip-arrow"></div>' +
'<div class="tooltip-inner"></div>' +
'</div>',
'<div class="tooltip-inner"></div>' +
'</div>',
title: '',
trigger: 'hover focus'
}
@@ -81,15 +82,14 @@ const Default = {
const DefaultType = {
allowList: 'object',
animation: 'boolean',
boundary: '(string|element)',
container: '(string|element|boolean)',
customClass: '(string|function)',
delay: '(number|object)',
fallbackPlacements: 'array',
html: 'boolean',
offset: '(array|string|function)',
offset: '(number|array|string|function)',
placement: '(string|function)',
popperConfig: '(null|object|function)',
positionConfig: '(null|object|function)',
sanitize: 'boolean',
sanitizeFn: '(null|function)',
selector: '(string|boolean)',
@@ -104,10 +104,6 @@ const DefaultType = {
class Tooltip extends BaseComponent {
constructor(element, config) {
if (typeof Popper === 'undefined') {
throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org/docs/v2/)')
}
super(element, config)
// Private
@@ -115,7 +111,7 @@ class Tooltip extends BaseComponent {
this._timeout = 0
this._isHovered = null
this._activeTrigger = {}
this._popper = null
this._positionHelper = new FloatingUi(this._element)
this._templateFactory = null
this._newContent = null
@@ -182,7 +178,7 @@ class Tooltip extends BaseComponent {
}
show() {
if (this._element.style.display === 'none') {
if (!isVisible(this._element)) {
throw new Error('Please use show on visible elements')
}
@@ -199,22 +195,14 @@ class Tooltip extends BaseComponent {
}
// TODO: v6 remove this or make it optional
this._disposePopper()
const tip = this._getTipElement()
this._element.setAttribute('aria-describedby', tip.getAttribute('id'))
const { container } = this._config
if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
container.append(tip)
EventHandler.trigger(this._element, this.constructor.eventName(EVENT_INSERTED))
if (this.tip) {
this.tip.remove()
this.tip = null
}
this._popper = this._createPopper(tip)
this.update()
tip.classList.add(CLASS_NAME_SHOW)
this.tip.classList.add(CLASS_NAME_SHOW)
// If this is a touch-enabled device we add extra
// empty mouseover listeners to the body's immediate children;
@@ -271,7 +259,8 @@ class Tooltip extends BaseComponent {
}
if (!this._isHovered) {
this._disposePopper()
this._positionHelper.stop()
this.tip.remove()
}
this._element.removeAttribute('aria-describedby')
@@ -282,9 +271,7 @@ class Tooltip extends BaseComponent {
}
update() {
if (this._popper) {
this._popper.update()
}
this._positionHelper.calculate(this._element, this._getTipElement(), this._getFloatingUiConfig(), { position: 'fixed' })
}
// Protected
@@ -295,6 +282,14 @@ class Tooltip extends BaseComponent {
_getTipElement() {
if (!this.tip) {
this.tip = this._createTipElement(this._newContent || this._getContentForTemplate())
this._element.setAttribute('aria-describedby', this.tip.getAttribute('id'))
}
const { container } = this._config
if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
container.append(this.tip)
EventHandler.trigger(this._element, this.constructor.eventName(EVENT_INSERTED))
}
return this.tip
@@ -309,8 +304,6 @@ class Tooltip extends BaseComponent {
}
tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW)
// TODO: v6 the following can be achieved with CSS only
tip.classList.add(`bs-${this.constructor.NAME}-auto`)
const tipId = getUID(this.constructor.NAME).toString()
@@ -326,7 +319,7 @@ class Tooltip extends BaseComponent {
setContent(content) {
this._newContent = content
if (this._isShown()) {
this._disposePopper()
this._positionHelper.stop()
this.show()
}
}
@@ -370,77 +363,33 @@ class Tooltip extends BaseComponent {
return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW)
}
_createPopper(tip) {
const placement = execute(this._config.placement, [this, tip, this._element])
const attachment = AttachmentMap[placement.toUpperCase()]
return Popper.createPopper(this._element, tip, this._getPopperConfig(attachment))
}
_getOffset() {
const { offset } = this._config
if (typeof offset === 'string') {
return offset.split(',').map(value => Number.parseInt(value, 10))
}
if (typeof offset === 'function') {
return popperData => offset(popperData, this._element)
}
return offset
}
_resolvePossibleFunction(arg) {
return execute(arg, [this._element, this._element])
}
_getPopperConfig(attachment) {
const defaultBsPopperConfig = {
placement: attachment,
modifiers: [
{
name: 'flip',
options: {
fallbackPlacements: this._config.fallbackPlacements
}
},
{
name: 'offset',
options: {
offset: this._getOffset()
}
},
{
name: 'preventOverflow',
options: {
boundary: this._config.boundary
}
},
{
name: 'arrow',
options: {
element: `.${this.constructor.NAME}-arrow`
}
},
{
name: 'preSetPlacement',
enabled: true,
phase: 'beforeMain',
fn: data => {
// Pre-set Popper's placement attribute in order to read the arrow sizes properly.
// Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement
this._getTipElement().setAttribute('data-popper-placement', data.state.placement)
}
}
_getFloatingUiConfig() {
const defaultBsConfig = {
strategy: 'fixed',
placement: this._getPlacement(),
middleware: [
offset(this._positionHelper.parseOffset(this._config.offset)),
flip({ fallbackPlacements: this._config.fallbackPlacements }),
shift(),
hide()
]
}
return {
...defaultBsPopperConfig,
...execute(this._config.popperConfig, [undefined, defaultBsPopperConfig])
...defaultBsConfig,
...execute(this._config.positionConfig, [undefined, defaultBsConfig])
}
}
_getPlacement() {
const placement = execute(this._config.placement, [this, this.tip, this._element])
return AttachmentMap[placement.toUpperCase()]
}
_resolvePossibleFunction(arg) {
return execute(arg, [this._element, this._element])
}
_setListeners() {
const triggers = this._config.trigger.split(' ')
@@ -593,17 +542,5 @@ class Tooltip extends BaseComponent {
// `Object.fromEntries(keysWithDifferentValues)`
return config
}
_disposePopper() {
if (this._popper) {
this._popper.destroy()
this._popper = null
}
if (this.tip) {
this.tip.remove()
this.tip = null
}
}
}
export default Tooltip
+98
View File
@@ -0,0 +1,98 @@
/**
* --------------------------------------------------------------------------
* Bootstrap floating-ui.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
import { autoUpdate, computePosition } from '@floating-ui/dom'
import Manipulator from '../dom/manipulator.js'
import { getElement, isElement } from './index.js'
/**
* Class definition
*/
class FloatingUi {
constructor(element) {
if (typeof computePosition === 'undefined') {
throw new TypeError('Bootstrap\'s tooltips and dropdowns require Floating UI (https://floating-ui.com/)')
}
this._element = element
this._cleanup = null
}
calculate(reference, floatingEl, config, extraCss = {}) {
this._cleanup = autoUpdate(reference, floatingEl, () => {
computePosition(reference, floatingEl, config)
.then(({ x, y, placement, middlewareData }) => {
const positionCss = {
left: `${x}px`,
top: `${y}px`
}
if (middlewareData.hide) {
const { referenceHidden } = middlewareData.hide
Object.assign(floatingEl.style, {
visibility: referenceHidden ? 'hidden' : 'visible'
})
}
Object.assign(floatingEl.style, { ...positionCss, ...extraCss })
Manipulator.setDataAttribute(floatingEl, 'placement', placement)
})
})
}
stop() {
if (this._cleanup) {
this._cleanup()
}
}
getReferenceElement(reference, parent, PluginName) {
if (reference === 'parent') {
return parent
}
if (isElement(reference)) {
return getElement(reference)
}
if (typeof reference === 'object') {
if (typeof reference.getBoundingClientRect !== 'function') {
throw new TypeError(`${PluginName.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`)
}
return reference
}
return this._element
}
parseOffset(value) {
if (typeof value === 'function') {
return popperData => value(popperData, this._element)
}
if (typeof value === 'string') {
const values = value.split(',')
value = [
Number.parseInt(values[0], 10),
Number.parseInt(values[1] || 0, 10)
]
}
if (Array.isArray(value)) {
return {
mainAxis: value[0],
crossAxis: value[1] || 0
}
}
return value
}
}
export default FloatingUi
+27 -13
View File
@@ -28,7 +28,7 @@
"@babel/core": "^7.28.4",
"@babel/preset-env": "^7.28.3",
"@docsearch/js": "^3.9.0",
"@popperjs/core": "^2.11.8",
"@floating-ui/dom": "^1.7.4",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^28.0.6",
"@rollup/plugin-node-resolve": "^16.0.1",
@@ -94,7 +94,7 @@
"zod": "^4.1.9"
},
"peerDependencies": {
"@popperjs/core": "^2.11.8"
"@floating-ui/dom": "^1.7.4"
}
},
"node_modules/@adobe/css-tools": {
@@ -2971,6 +2971,31 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@floating-ui/core": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz",
"integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
"dev": true,
"dependencies": {
"@floating-ui/utils": "^0.2.10"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz",
"integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==",
"dev": true,
"dependencies": {
"@floating-ui/core": "^1.7.3",
"@floating-ui/utils": "^0.2.10"
}
},
"node_modules/@floating-ui/utils": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
"integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
"dev": true
},
"node_modules/@humanwhocodes/config-array": {
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
@@ -4099,17 +4124,6 @@
"node": ">=14"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"dev": true,
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@rollup/plugin-babel": {
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-6.0.4.tgz",
+12 -12
View File
@@ -105,7 +105,7 @@
"astro-preview": "astro preview --root site --port 9001"
},
"peerDependencies": {
"@popperjs/core": "^2.11.8"
"@floating-ui/dom": "^1.7.4"
},
"devDependencies": {
"@astrojs/check": "^0.9.4",
@@ -117,7 +117,7 @@
"@babel/core": "^7.28.4",
"@babel/preset-env": "^7.28.3",
"@docsearch/js": "^3.9.0",
"@popperjs/core": "^2.11.8",
"@floating-ui/dom": "^1.7.4",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^28.0.6",
"@rollup/plugin-node-resolve": "^16.0.1",
@@ -195,16 +195,16 @@
"directories": {
"lib": "dist"
},
"shim": {
"js/bootstrap": {
"deps": [
"@popperjs/core"
]
}
},
"shim": {
"js/bootstrap": {
"deps": [
"@floating-ui/dom"
]
}
},
"dependencies": {},
"peerDependencies": {
"@popperjs/core": "^2.11.8"
}
"peerDependencies": {
"@floating-ui/dom": "^1.7.4"
}
}
}
+5 -5
View File
@@ -52,9 +52,9 @@ $grid-breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px,
xxl: 1400px
lg: 1024px,
xl: 1280px,
2xl: 1536px
) !default;
// scss-docs-end grid-breakpoints
@@ -80,8 +80,8 @@ $container-max-widths: (
sm: 540px,
md: 720px,
lg: 960px,
xl: 1140px,
xxl: 1320px
xl: 1200px,
2xl: 1440px
) !default;
// scss-docs-end container-max-widths
+1 -38
View File
@@ -123,11 +123,6 @@ $dropdown-dark-header-color: $gray-500 !default;
@include border-radius(var(--#{$prefix}dropdown-border-radius));
@include box-shadow(var(--#{$prefix}dropdown-box-shadow));
&[data-bs-popper] {
top: 100%;
left: 0;
margin-top: var(--#{$prefix}dropdown-spacer);
}
@if $dropdown-padding-y == 0 {
> .dropdown-item:first-child,
@@ -144,7 +139,7 @@ $dropdown-dark-header-color: $gray-500 !default;
// scss-docs-start responsive-breakpoints
// We deliberately hardcode the `bs-` prefix because we check
// this custom property in JS to determine Popper's positioning
// this custom property in JS to determine positioning
@each $breakpoint in map.keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
@@ -152,20 +147,10 @@ $dropdown-dark-header-color: $gray-500 !default;
.dropdown-menu#{$infix}-start {
--bs-position: start;
&[data-bs-popper] {
right: auto;
left: 0;
}
}
.dropdown-menu#{$infix}-end {
--bs-position: end;
&[data-bs-popper] {
right: 0;
left: auto;
}
}
}
}
@@ -174,26 +159,12 @@ $dropdown-dark-header-color: $gray-500 !default;
// Allow for dropdowns to go bottom up (aka, dropup-menu)
// Just add .dropup after the standard .dropdown class and you're set.
.dropup {
.dropdown-menu[data-bs-popper] {
top: auto;
bottom: 100%;
margin-top: 0;
margin-bottom: var(--#{$prefix}dropdown-spacer);
}
.dropdown-toggle {
@include caret(up);
}
}
.dropend {
.dropdown-menu[data-bs-popper] {
top: 0;
right: auto;
left: 100%;
margin-top: 0;
margin-left: var(--#{$prefix}dropdown-spacer);
}
.dropdown-toggle {
@include caret(end);
@@ -204,14 +175,6 @@ $dropdown-dark-header-color: $gray-500 !default;
}
.dropstart {
.dropdown-menu[data-bs-popper] {
top: 0;
right: 100%;
left: auto;
margin-top: 0;
margin-right: var(--#{$prefix}dropdown-spacer);
}
.dropdown-toggle {
@include caret(start);
&::before {
+96 -122
View File
@@ -54,6 +54,9 @@ $popover-arrow-height: .5rem !default;
--#{$prefix}popover-arrow-border: var(--#{$prefix}popover-border-color);
// scss-docs-end popover-css-vars
position: absolute;
top: 0;
left: 0;
z-index: var(--#{$prefix}popover-zindex);
display: block;
max-width: var(--#{$prefix}popover-max-width);
@@ -63,148 +66,119 @@ $popover-arrow-height: .5rem !default;
@include font-size(var(--#{$prefix}popover-font-size));
// Allow breaking very long words so they don't overflow the popover's bounds
word-wrap: break-word;
&::before,
&::after {
position: absolute;
display: block;
content: "";
border-color: transparent;
border-style: solid;
border-width: 0;
transform: translateX(-50%);
}
}
.popover-inner {
margin: var(--#{$prefix}popover-arrow-height);
background-color: var(--#{$prefix}popover-bg);
background-clip: padding-box;
border: var(--#{$prefix}popover-border-width) solid var(--#{$prefix}popover-border-color);
@include border-radius(var(--#{$prefix}popover-border-radius));
@include box-shadow(var(--#{$prefix}popover-box-shadow));
.popover-arrow {
display: block;
width: var(--#{$prefix}popover-arrow-width);
height: var(--#{$prefix}popover-arrow-height);
&::before,
&::after {
position: absolute;
display: block;
content: "";
border-color: transparent;
border-style: solid;
border-width: 0;
}
}
}
.bs-popover-top {
> .popover-arrow {
bottom: calc(-1 * (var(--#{$prefix}popover-arrow-height)) - var(--#{$prefix}popover-border-width));
&::before,
&::after {
border-width: var(--#{$prefix}popover-arrow-height) calc(var(--#{$prefix}popover-arrow-width) * .5) 0;
}
&::before {
bottom: 0;
border-top-color: var(--#{$prefix}popover-arrow-border);
}
&::after {
bottom: var(--#{$prefix}popover-border-width);
border-top-color: var(--#{$prefix}popover-bg);
}
}
}
/* rtl:begin:ignore */
.bs-popover-end {
> .popover-arrow {
left: calc(-1 * (var(--#{$prefix}popover-arrow-height)) - var(--#{$prefix}popover-border-width));
width: var(--#{$prefix}popover-arrow-height);
height: var(--#{$prefix}popover-arrow-width);
&::before,
&::after {
border-width: calc(var(--#{$prefix}popover-arrow-width) * .5) var(--#{$prefix}popover-arrow-height) calc(var(--#{$prefix}popover-arrow-width) * .5) 0;
}
&::before {
left: 0;
border-right-color: var(--#{$prefix}popover-arrow-border);
}
&::after {
left: var(--#{$prefix}popover-border-width);
border-right-color: var(--#{$prefix}popover-bg);
}
}
}
/* rtl:end:ignore */
.bs-popover-bottom {
> .popover-arrow {
top: calc(-1 * (var(--#{$prefix}popover-arrow-height)) - var(--#{$prefix}popover-border-width));
&::before,
&::after {
border-width: 0 calc(var(--#{$prefix}popover-arrow-width) * .5) var(--#{$prefix}popover-arrow-height);
}
&::before {
top: 0;
border-bottom-color: var(--#{$prefix}popover-arrow-border);
}
&::after {
top: var(--#{$prefix}popover-border-width);
border-bottom-color: var(--#{$prefix}popover-bg);
}
}
// This will remove the popover-header's border just below the arrow
.popover-header::before {
position: absolute;
top: 0;
.popover[data-bs-placement="top"] {
&::before,
&::after {
left: 50%;
display: block;
width: var(--#{$prefix}popover-arrow-width);
margin-left: calc(-.5 * var(--#{$prefix}popover-arrow-width));
content: "";
border-bottom: var(--#{$prefix}popover-border-width) solid var(--#{$prefix}popover-header-bg);
border-width: var(--#{$prefix}popover-arrow-height) calc(var(--#{$prefix}popover-arrow-width) * .5) 0;
}
&::before {
bottom: 0;
border-top-color: var(--#{$prefix}popover-arrow-border);
}
&::after {
bottom: var(--#{$prefix}popover-border-width);
border-top-color: var(--#{$prefix}popover-bg);
}
}
.popover[data-bs-placement="bottom"] {
&::before,
&::after {
left: 50%;
border-width: 0 calc(var(--#{$prefix}popover-arrow-width) * .5) var(--#{$prefix}popover-arrow-height);
}
&::before {
top: 0;
border-bottom-color: var(--#{$prefix}popover-arrow-border);
}
&::after {
top: var(--#{$prefix}popover-border-width);
border-bottom-color: var(--#{$prefix}popover-bg);
}
}
/* rtl:begin:ignore */
.bs-popover-start {
> .popover-arrow {
right: calc(-1 * (var(--#{$prefix}popover-arrow-height)) - var(--#{$prefix}popover-border-width));
width: var(--#{$prefix}popover-arrow-height);
height: var(--#{$prefix}popover-arrow-width);
&::before,
&::after {
border-width: calc(var(--#{$prefix}popover-arrow-width) * .5) 0 calc(var(--#{$prefix}popover-arrow-width) * .5) var(--#{$prefix}popover-arrow-height);
}
.popover[data-bs-placement="right"] {
&::before,
&::after {
top: 50%;
border-width: calc(var(--#{$prefix}popover-arrow-width) * .5) var(--#{$prefix}popover-arrow-height) calc(var(--#{$prefix}popover-arrow-width) * .5) 0;
transform: translateY(-50%);
}
&::before {
right: 0;
border-left-color: var(--#{$prefix}popover-arrow-border);
}
&::before {
left: 0;
border-right-color: var(--#{$prefix}popover-arrow-border);
}
&::after {
right: var(--#{$prefix}popover-border-width);
border-left-color: var(--#{$prefix}popover-bg);
}
&::after {
left: var(--#{$prefix}popover-border-width);
border-right-color: var(--#{$prefix}popover-bg);
}
}
.popover[data-bs-placement="left"] {
&::before,
&::after {
top: 50%;
border-width: calc(var(--#{$prefix}popover-arrow-width) * .5) 0 calc(var(--#{$prefix}popover-arrow-width) * .5) var(--#{$prefix}popover-arrow-height);
transform: translateY(-50%);
}
&::before {
right: 0;
border-left-color: var(--#{$prefix}popover-arrow-border);
}
&::after {
right: var(--#{$prefix}popover-border-width);
border-left-color: var(--#{$prefix}popover-bg);
}
}
/* rtl:end:ignore */
.bs-popover-auto {
&[data-popper-placement^="top"] {
@extend .bs-popover-top;
}
&[data-popper-placement^="right"] {
@extend .bs-popover-end;
}
&[data-popper-placement^="bottom"] {
@extend .bs-popover-bottom;
}
&[data-popper-placement^="left"] {
@extend .bs-popover-start;
}
// This will remove the popover-header's border just below the arrow
.popover-header::before {
position: absolute;
top: 0;
left: 50%;
display: block;
width: var(--#{$prefix}popover-arrow-width);
margin-left: calc(var(--#{$prefix}popover-arrow-width) * -.5);
content: "";
border-bottom: var(--#{$prefix}popover-border-width) solid var(--#{$prefix}popover-header-bg);
}
// Offset the popover to account for the popover arrow
+8 -3
View File
@@ -9,7 +9,7 @@
@use "forms/form-variables" as *;
// mdo-do: do we need theme?
@layer colors, theme, config, root, reboot, layout, content, forms, components, helpers, custom, utilities;
@layer colors, theme, config, root, reboot, layout, content, forms, components, custom, helpers, utilities;
:root {
color-scheme: light dark;
@@ -91,6 +91,11 @@
--#{$prefix}root-font-size: #{$font-size-root};
}
--#{$prefix}body-font-family: #{meta.inspect($font-family-base)};
--#{$prefix}font-size-base: #{$font-size-base}; // 14px
--#{$prefix}font-size-sm: calc(#{$font-size-base} * .9285);
--#{$prefix}font-size-lg: calc(#{$font-size-base} * 1.285);
@include rfs($font-size-base, --#{$prefix}body-font-size);
--#{$prefix}body-font-weight: #{$font-weight-base};
--#{$prefix}body-line-height: #{$line-height-base};
@@ -165,7 +170,7 @@
--#{$prefix}border-radius-sm: #{$border-radius-sm};
--#{$prefix}border-radius-lg: #{$border-radius-lg};
--#{$prefix}border-radius-xl: #{$border-radius-xl};
--#{$prefix}border-radius-xxl: #{$border-radius-xxl};
--#{$prefix}border-radius-2xl: #{$border-radius-2xl};
--#{$prefix}border-radius-pill: #{$border-radius-pill};
// scss-docs-end root-border-radius-var
@@ -237,7 +242,7 @@
--#{$prefix}link-color-rgb: #{to-rgb($link-color-dark)};
--#{$prefix}link-hover-color-rgb: #{to-rgb($link-hover-color-dark)};
--#{$prefix}code-color: #{$code-color-dark};
// --#{$prefix}code-color: #{$code-color-dark}; // removed in v6
--#{$prefix}highlight-color: #{$mark-color-dark};
--#{$prefix}highlight-bg: #{$mark-bg-dark};
+31 -71
View File
@@ -14,7 +14,6 @@ $tooltip-border-radius: var(--#{$prefix}border-radius) !default;
$tooltip-opacity: .9 !default;
$tooltip-padding-y: $spacer * .25 !default;
$tooltip-padding-x: $spacer * .5 !default;
$tooltip-margin: null !default; // TODO: remove this in v6
$tooltip-arrow-width: .8rem !default;
$tooltip-arrow-height: .4rem !default;
@@ -38,7 +37,6 @@ $form-feedback-tooltip-border-radius: $tooltip-border-radius !default;
--#{$prefix}tooltip-max-width: #{$tooltip-max-width};
--#{$prefix}tooltip-padding-x: #{$tooltip-padding-x};
--#{$prefix}tooltip-padding-y: #{$tooltip-padding-y};
--#{$prefix}tooltip-margin: #{$tooltip-margin};
@include rfs($tooltip-font-size, --#{$prefix}tooltip-font-size);
--#{$prefix}tooltip-color: #{$tooltip-color};
--#{$prefix}tooltip-bg: #{$tooltip-bg};
@@ -48,10 +46,12 @@ $form-feedback-tooltip-border-radius: $tooltip-border-radius !default;
--#{$prefix}tooltip-arrow-height: #{$tooltip-arrow-height};
// scss-docs-end tooltip-css-vars
position: absolute;
top: 0;
left: 0;
z-index: var(--#{$prefix}tooltip-zindex);
display: block;
margin: var(--#{$prefix}tooltip-margin);
@include deprecate("`$tooltip-margin`", "v5", "v5.x", true);
padding: var(--#{$prefix}tooltip-arrow-height);
// Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.
// So reset our font and text properties to avoid inheriting weird values.
@include reset-text();
@@ -62,83 +62,43 @@ $form-feedback-tooltip-border-radius: $tooltip-border-radius !default;
&.show { opacity: var(--#{$prefix}tooltip-opacity); }
.tooltip-arrow {
display: block;
width: var(--#{$prefix}tooltip-arrow-width);
height: var(--#{$prefix}tooltip-arrow-height);
&::before {
position: absolute;
content: "";
border-color: transparent;
border-style: solid;
}
}
}
.bs-tooltip-top .tooltip-arrow {
bottom: calc(-1 * var(--#{$prefix}tooltip-arrow-height));
&::before {
top: -1px;
border-width: var(--#{$prefix}tooltip-arrow-height) calc(var(--#{$prefix}tooltip-arrow-width) * .5) 0;
border-top-color: var(--#{$prefix}tooltip-bg);
position: absolute;
content: "";
border-color: transparent;
border-style: solid;
transform: translateX(-50%);
}
}
/* rtl:begin:ignore */
.bs-tooltip-end .tooltip-arrow {
left: calc(-1 * var(--#{$prefix}tooltip-arrow-height));
width: var(--#{$prefix}tooltip-arrow-height);
height: var(--#{$prefix}tooltip-arrow-width);
&::before {
right: -1px;
border-width: calc(var(--#{$prefix}tooltip-arrow-width) * .5) var(--#{$prefix}tooltip-arrow-height) calc(var(--#{$prefix}tooltip-arrow-width) * .5) 0;
border-right-color: var(--#{$prefix}tooltip-bg);
}
.tooltip[data-bs-placement="top"]::before {
bottom: 0;
left: 50%;
border-width: var(--#{$prefix}tooltip-arrow-height) calc(var(--#{$prefix}tooltip-arrow-width) * .5) 0;
border-top-color: var(--#{$prefix}tooltip-bg);
}
/* rtl:end:ignore */
.bs-tooltip-bottom .tooltip-arrow {
top: calc(-1 * var(--#{$prefix}tooltip-arrow-height));
&::before {
bottom: -1px;
border-width: 0 calc(var(--#{$prefix}tooltip-arrow-width) * .5) var(--#{$prefix}tooltip-arrow-height);
border-bottom-color: var(--#{$prefix}tooltip-bg);
}
.tooltip[data-bs-placement="bottom"]::before {
top: 0;
left: 50%;
border-width: 0 calc(var(--#{$prefix}tooltip-arrow-width) * .5) var(--#{$prefix}tooltip-arrow-height);
border-bottom-color: var(--#{$prefix}tooltip-bg);
}
/* rtl:begin:ignore */
.bs-tooltip-start .tooltip-arrow {
right: calc(-1 * var(--#{$prefix}tooltip-arrow-height));
width: var(--#{$prefix}tooltip-arrow-height);
height: var(--#{$prefix}tooltip-arrow-width);
&::before {
left: -1px;
border-width: calc(var(--#{$prefix}tooltip-arrow-width) * .5) 0 calc(var(--#{$prefix}tooltip-arrow-width) * .5) var(--#{$prefix}tooltip-arrow-height);
border-left-color: var(--#{$prefix}tooltip-bg);
}
.tooltip[data-bs-placement="right"]::before {
top: 50%;
left: 0;
border-width: calc(var(--#{$prefix}tooltip-arrow-width) * .5) var(--#{$prefix}tooltip-arrow-height) calc(var(--#{$prefix}tooltip-arrow-width) * .5) 0;
border-right-color: var(--#{$prefix}tooltip-bg);
transform: translateY(-50%);
}
/* rtl:end:ignore */
.bs-tooltip-auto {
&[data-popper-placement^="top"] {
@extend .bs-tooltip-top;
}
&[data-popper-placement^="right"] {
@extend .bs-tooltip-end;
}
&[data-popper-placement^="bottom"] {
@extend .bs-tooltip-bottom;
}
&[data-popper-placement^="left"] {
@extend .bs-tooltip-start;
}
.tooltip[data-bs-placement="left"]::before {
top: 50%;
right: 0;
border-width: calc(var(--#{$prefix}tooltip-arrow-width) * .5) 0 calc(var(--#{$prefix}tooltip-arrow-width) * .5) var(--#{$prefix}tooltip-arrow-height);
border-left-color: var(--#{$prefix}tooltip-bg);
transform: translateY(-50%);
}
// Wrapper for the tooltip content
+20
View File
@@ -355,6 +355,16 @@ $utilities: map.merge(
evenly: space-evenly,
)
),
"justify-items": (
responsive: true,
property: justify-items,
values: (
start: start,
end: end,
center: center,
stretch: stretch,
)
),
"justify-self": (
responsive: true,
property: justify-self,
@@ -399,6 +409,16 @@ $utilities: map.merge(
stretch: stretch,
)
),
"place-items": (
responsive: true,
property: place-items,
values: (
start: start,
end: end,
center: center,
stretch: stretch,
)
),
"order": (
responsive: true,
property: order,
+10 -15
View File
@@ -10,7 +10,7 @@
// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.
// scss-docs-start theme-color-variables
$primary: $purple-500 !default;
$primary: $blue-500 !default;
$secondary: $gray-600 !default;
$success: $green-500 !default;
$info: $cyan-500 !default;
@@ -167,6 +167,7 @@ $body-emphasis-color: $black !default;
$link-color: $primary !default;
$link-decoration: underline !default;
$link-underline-offset: .2em !default;
$link-shade-percentage: 20% !default;
$link-hover-color: shift-color($link-color, $link-shade-percentage) !default;
$link-hover-decoration: null !default;
@@ -204,7 +205,7 @@ $border-widths: (
5: 5px
) !default;
$border-style: solid !default;
$border-color: $gray-300 !default;
$border-color: color.mix($gray-300, $gray-400) !default;
$border-color-translucent: rgba($black, .175) !default;
// scss-docs-end border-variables
@@ -213,7 +214,7 @@ $border-radius: .375rem !default;
$border-radius-sm: .25rem !default;
$border-radius-lg: .5rem !default;
$border-radius-xl: 1rem !default;
$border-radius-xxl: 2rem !default;
$border-radius-2xl: 2rem !default;
$border-radius-pill: 50rem !default;
// scss-docs-end border-radius-variables
@@ -266,8 +267,8 @@ $font-family-code: var(--#{$prefix}font-monospace) !default;
// $font-size-root affects the value of `rem`, which is used for as well font sizes, paddings, and margins
// $font-size-base affects the font size of the body text
$font-size-root: null !default;
$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`
$font-size-root: 16px !default;
$font-size-base: 14px !default; // Assumes the browser default, typically `16px`
$font-size-sm: $font-size-base * .875 !default;
$font-size-lg: $font-size-base * 1.25 !default;
@@ -518,7 +519,7 @@ $modal-footer-border-width: $modal-header-border-width !default;
$modal-sm: 300px !default;
$modal-md: 500px !default;
$modal-lg: 800px !default;
$modal-xl: 1140px !default;
$modal-xl: 1200px !default;
$modal-fade-transform: translate(0, -50px) !default;
$modal-show-transform: none !default;
@@ -546,8 +547,8 @@ $offcanvas-backdrop-opacity: $modal-backdrop-opacity !default;
// Code
$code-font-size: $small-font-size !default;
$code-color: $pink !default;
$code-font-size: 95% !default;
$code-color: var(--#{$prefix}secondary-text) !default;
$kbd-padding-y: .1875rem !default;
$kbd-padding-x: .375rem !default;
@@ -578,7 +579,7 @@ $border-color-translucent-dark: rgba($white, .15) !default;
$headings-color-dark: inherit !default;
$link-color-dark: tint-color($primary, 40%) !default;
$link-hover-color-dark: shift-color($link-color-dark, -$link-shade-percentage) !default;
$code-color-dark: tint-color($code-color, 40%) !default;
// $code-color-dark: tint-color($code-color, 40%) !default;
$mark-color-dark: $body-color-dark !default;
$mark-bg-dark: $yellow-800 !default;
@@ -587,12 +588,6 @@ $mark-bg-dark: $yellow-800 !default;
// Forms
//
$form-select-indicator-color-dark: $body-color-dark !default;
$form-select-indicator-dark: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path fill='none' stroke='#{$form-select-indicator-color-dark}' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/></svg>") !default;
$form-switch-color-dark: rgba($white, .25) !default;
$form-switch-bg-image-dark: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$form-switch-color-dark}'/></svg>") !default;
// scss-docs-start form-validation-colors-dark
$form-valid-color-dark: $green-300 !default;
$form-valid-border-color-dark: $green-300 !default;
+2
View File
@@ -27,9 +27,11 @@ $utilities: map-get-multiple(
"flex-shrink",
"flex-wrap",
"justify-content",
"justify-items",
"align-items",
"align-content",
"align-self",
"place-items",
"margin",
"margin-x",
"margin-y",
+3 -3
View File
@@ -6,11 +6,11 @@
// @forward "variables";
// Layout & components
@use "root" as *;
@forward "root";
// Helpers
@forward "helpers";
// Utilities
@use "utilities" as *;
@use "utilities/api";
@forward "utilities";
@forward "utilities/api";
+28 -28
View File
@@ -1,40 +1,40 @@
@use "banner";
@forward "banner";
// scss-docs-start import-stack
// Global CSS variables, layer definitions, and configuration
@use "root";
@forward "root";
// Subdir imports
@use "content";
@use "layout";
@use "forms";
@use "buttons";
@forward "content";
@forward "layout";
@forward "forms";
@forward "buttons";
// Components
@use "accordion";
@use "alert";
@use "badge";
@use "breadcrumb";
@use "card";
@use "carousel";
@use "dropdown";
@use "list-group";
@use "modal";
@use "nav";
@use "navbar";
@use "offcanvas";
@use "pagination";
@use "placeholders";
@use "popover";
@use "progress";
@use "spinners";
@use "toasts";
@use "tooltip";
@use "transitions";
@forward "accordion";
@forward "alert";
@forward "badge";
@forward "breadcrumb";
@forward "card";
@forward "carousel";
@forward "dropdown";
@forward "list-group";
@forward "modal";
@forward "nav";
@forward "navbar";
@forward "offcanvas";
@forward "pagination";
@forward "placeholders";
@forward "popover";
@forward "progress";
@forward "spinners";
@forward "toasts";
@forward "tooltip";
@forward "transitions";
// Helpers
@use "helpers";
@forward "helpers";
// Utilities
@use "utilities/api";
@forward "utilities/api";
// scss-docs-end import-stack
+15
View File
@@ -279,4 +279,19 @@
.btn-sm {
@include button-size($btn-padding-y-sm, $btn-padding-x-sm, $btn-font-size-sm, $btn-border-radius-sm);
}
.btn-check {
position: absolute;
clip: rect(0, 0, 0, 0);
pointer-events: none;
&[disabled],
&:disabled {
+ .btn {
pointer-events: none;
filter: none;
opacity: .65;
}
}
}
}
+7 -5
View File
@@ -33,7 +33,8 @@
:root {
@if $font-size-root != null {
@include font-size(var(--#{$prefix}root-font-size));
font-size: var(--#{$prefix}root-font-size);
// @include font-size(var(--#{$prefix}root-font-size));
}
@if $enable-smooth-scroll {
@@ -256,12 +257,13 @@
// Links
a {
color: rgba(var(--#{$prefix}link-color-rgb), var(--#{$prefix}link-opacity, 1));
text-decoration: $link-decoration;
color: var(--#{$prefix}link-color);
text-decoration: var(--#{$prefix}link-decoration);
text-underline-offset: $link-underline-offset;
&:hover {
--#{$prefix}link-color-rgb: var(--#{$prefix}link-hover-color-rgb);
text-decoration: $link-hover-decoration;
color: var(--#{$prefix}link-hover-color);
text-decoration: var(--#{$prefix}link-hover-decoration);
}
}
+102
View File
@@ -0,0 +1,102 @@
@use "../config" as *;
@use "../colors" as *;
@use "../variables" as *;
@use "../functions" as *;
@use "../vendor/rfs" as *;
@use "../mixins/border-radius" as *;
@use "../mixins/box-shadow" as *;
@use "../mixins/color-mode" as *;
@use "../mixins/focus-ring" as *;
@use "../mixins/transition" as *;
@use "form-variables" as *;
// scss-docs-start check-variables
$check-border-color: var(--#{$prefix}border-color) !default;
$check-checked-bg: var(--#{$prefix}primary-base) !default;
$check-checked-border-color: $check-checked-bg !default;
$check-indeterminate-bg: var(--#{$prefix}primary-base) !default;
$check-indeterminate-border-color: $check-indeterminate-bg !default;
$check-disabled-bg: var(--#{$prefix}secondary-bg) !default;
$check-disabled-border-color: $check-disabled-bg !default;
$check-disabled-opacity: .65 !default;
// scss-docs-end check-variables
@layer forms {
b-checkgroup {
display: flex;
gap: var(--#{$prefix}gap, .5rem);
align-items: var(--#{$prefix}align-items, start);
.description {
color: var(--#{$prefix}secondary-text);
}
}
.check {
// scss-docs-start check-css-variables
--#{$prefix}check-bg: transparent;
--#{$prefix}check-border-color: #{$check-border-color};
--#{$prefix}check-checked-bg: #{$check-checked-bg};
--#{$prefix}check-checked-border-color: #{$check-checked-border-color};
--#{$prefix}check-indeterminate-bg: #{$check-indeterminate-bg};
--#{$prefix}check-indeterminate-border-color: #{$check-indeterminate-border-color};
--#{$prefix}check-disabled-bg: #{$check-disabled-bg};
--#{$prefix}check-disabled-border-color: #{$check-disabled-border-color};
--#{$prefix}check-disabled-opacity: #{$check-disabled-opacity};
// scss-docs-end check-css-variables
display: grid;
grid-template-columns: repeat(1, minmax(0, 1fr));
margin-block: .125rem;
:where(svg, input) {
flex-shrink: 0;
grid-row-start: 1;
grid-column-start: 1;
width: 1rem;
height: 1rem;
}
:where(input) {
appearance: none;
// later: maybe set a tertiary bg color?
background-color: var(--#{$prefix}check-bg);
border: 1px solid var(--#{$prefix}check-border-color);
// stylelint-disable-next-line property-disallowed-list
border-radius: .25em;
}
:where(input:checked, input:indeterminate) {
background-color: var(--#{$prefix}check-checked-bg);
border-color: var(--#{$prefix}check-checked-border-color);
}
&:has(input:checked) .checked,
&:has(input:indeterminate) .indeterminate {
display: block;
color: var(--#{$prefix}primary-contrast);
stroke: currentcolor;
}
&:has(input:disabled) {
--#{$prefix}check-bg: var(--#{$prefix}check-disabled-bg);
~ label {
color: var(--#{$prefix}secondary-text);
cursor: default;
}
}
&:has(input:disabled:checked) {
opacity: var(--#{$prefix}check-disabled-opacity);
}
:where(svg) {
pointer-events: none;
}
:where(svg path) {
display: none;
}
}
}
-252
View File
@@ -1,252 +0,0 @@
@use "../config" as *;
@use "../colors" as *;
@use "../variables" as *;
@use "../functions" as *;
@use "../vendor/rfs" as *;
@use "../mixins/border-radius" as *;
@use "../mixins/box-shadow" as *;
@use "../mixins/color-mode" as *;
@use "../mixins/focus-ring" as *;
@use "../mixins/transition" as *;
@use "form-variables" as *;
// scss-docs-start form-check-variables
$form-check-input-width: 1em !default;
$form-check-min-height: $font-size-base * $line-height-base !default;
$form-check-padding-start: $form-check-input-width + .5em !default;
$form-check-margin-bottom: .125rem !default;
$form-check-label-color: null !default;
$form-check-label-cursor: null !default;
$form-check-transition: null !default;
$form-check-input-active-filter: brightness(90%) !default;
$form-check-input-bg: $input-bg !default;
$form-check-input-border: var(--#{$prefix}border-width) solid var(--#{$prefix}border-color) !default;
$form-check-input-border-radius: .25em !default;
$form-check-radio-border-radius: 50% !default;
$form-check-input-focus-border: $input-focus-border-color !default;
$form-check-input-focus-box-shadow: $focus-ring-box-shadow !default;
$form-check-input-checked-color: $component-active-color !default;
$form-check-input-checked-bg-color: $component-active-bg !default;
$form-check-input-checked-border-color: $form-check-input-checked-bg-color !default;
$form-check-input-checked-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'><path fill='none' stroke='#{$form-check-input-checked-color}' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/></svg>") !default;
$form-check-radio-checked-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='2' fill='#{$form-check-input-checked-color}'/></svg>") !default;
$form-check-input-indeterminate-color: $component-active-color !default;
$form-check-input-indeterminate-bg-color: $component-active-bg !default;
$form-check-input-indeterminate-border-color: $form-check-input-indeterminate-bg-color !default;
$form-check-input-indeterminate-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'><path fill='none' stroke='#{$form-check-input-indeterminate-color}' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/></svg>") !default;
$form-check-input-disabled-opacity: .5 !default;
$form-check-label-disabled-opacity: $form-check-input-disabled-opacity !default;
$form-check-btn-check-disabled-opacity: $btn-disabled-opacity !default;
$form-check-inline-margin-end: 1rem !default;
// scss-docs-end form-check-variables
// scss-docs-start form-switch-variables
$form-switch-color: rgba($black, .25) !default;
$form-switch-width: 1.5em !default;
$form-switch-padding-start: $form-switch-width + .5em !default;
$form-switch-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$form-switch-color}'/></svg>") !default;
$form-switch-border-radius: $form-switch-width !default;
$form-switch-transition: background-position .15s ease-in-out !default;
$form-switch-focus-color: $input-focus-border-color !default;
$form-switch-focus-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$form-switch-focus-color}'/></svg>") !default;
$form-switch-checked-color: $component-active-color !default;
$form-switch-checked-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$form-switch-checked-color}'/></svg>") !default;
$form-switch-checked-bg-position: right center !default;
// scss-docs-end form-switch-variables
@layer forms {
.form-check {
display: block;
min-height: $form-check-min-height;
padding-left: $form-check-padding-start;
margin-bottom: $form-check-margin-bottom;
.form-check-input {
float: left;
margin-left: $form-check-padding-start * -1;
}
}
.form-check-reverse {
padding-right: $form-check-padding-start;
padding-left: 0;
text-align: right;
.form-check-input {
float: right;
margin-right: $form-check-padding-start * -1;
margin-left: 0;
}
}
.form-check-input {
--#{$prefix}form-check-bg: #{$form-check-input-bg};
flex-shrink: 0;
width: $form-check-input-width;
height: $form-check-input-width;
margin-top: ($line-height-base - $form-check-input-width) * .5; // line-height minus check height
vertical-align: top;
appearance: none;
background-color: var(--#{$prefix}form-check-bg);
background-image: var(--#{$prefix}form-check-bg-image);
background-repeat: no-repeat;
background-position: center;
background-size: contain;
border: $form-check-input-border;
print-color-adjust: exact; // Keep themed appearance for print
@include transition($form-check-transition);
&[type="checkbox"] {
@include border-radius($form-check-input-border-radius);
}
&[type="radio"] {
// stylelint-disable-next-line property-disallowed-list
border-radius: $form-check-radio-border-radius;
}
&:active {
filter: $form-check-input-active-filter;
}
&:focus-visible {
border-color: $form-check-input-focus-border;
@include focus-ring(true);
--#{$prefix}focus-ring-offset: 1px;
// box-shadow: $form-check-input-focus-box-shadow;
}
&:checked {
background-color: $form-check-input-checked-bg-color;
border-color: $form-check-input-checked-border-color;
&[type="checkbox"] {
@if $enable-gradients {
--#{$prefix}form-check-bg-image: #{escape-svg($form-check-input-checked-bg-image)}, var(--#{$prefix}gradient);
} @else {
--#{$prefix}form-check-bg-image: #{escape-svg($form-check-input-checked-bg-image)};
}
}
&[type="radio"] {
@if $enable-gradients {
--#{$prefix}form-check-bg-image: #{escape-svg($form-check-radio-checked-bg-image)}, var(--#{$prefix}gradient);
} @else {
--#{$prefix}form-check-bg-image: #{escape-svg($form-check-radio-checked-bg-image)};
}
}
}
&[type="checkbox"]:indeterminate {
background-color: $form-check-input-indeterminate-bg-color;
border-color: $form-check-input-indeterminate-border-color;
@if $enable-gradients {
--#{$prefix}form-check-bg-image: #{escape-svg($form-check-input-indeterminate-bg-image)}, var(--#{$prefix}gradient);
} @else {
--#{$prefix}form-check-bg-image: #{escape-svg($form-check-input-indeterminate-bg-image)};
}
}
&:disabled {
pointer-events: none;
filter: none;
opacity: $form-check-input-disabled-opacity;
}
// Use disabled attribute in addition of :disabled pseudo-class
// See: https://github.com/twbs/bootstrap/issues/28247
&[disabled],
&:disabled {
~ .form-check-label {
cursor: default;
opacity: $form-check-label-disabled-opacity;
}
}
}
.form-check-label {
color: $form-check-label-color;
cursor: $form-check-label-cursor;
}
//
// Switch
//
.form-switch {
padding-left: $form-switch-padding-start;
.form-check-input {
--#{$prefix}form-switch-bg: #{escape-svg($form-switch-bg-image)};
width: $form-switch-width;
margin-left: $form-switch-padding-start * -1;
background-image: var(--#{$prefix}form-switch-bg);
background-position: left center;
@include border-radius($form-switch-border-radius, 0);
@include transition($form-switch-transition);
&:focus {
--#{$prefix}form-switch-bg: #{escape-svg($form-switch-focus-bg-image)};
}
&:checked {
background-position: $form-switch-checked-bg-position;
@if $enable-gradients {
--#{$prefix}form-switch-bg: #{escape-svg($form-switch-checked-bg-image)}, var(--#{$prefix}gradient);
} @else {
--#{$prefix}form-switch-bg: #{escape-svg($form-switch-checked-bg-image)};
}
}
}
&.form-check-reverse {
padding-right: $form-switch-padding-start;
padding-left: 0;
.form-check-input {
margin-right: $form-switch-padding-start * -1;
margin-left: 0;
}
}
}
.form-check-inline {
display: inline-block;
margin-right: $form-check-inline-margin-end;
}
.btn-check {
position: absolute;
clip: rect(0, 0, 0, 0);
pointer-events: none;
&[disabled],
&:disabled {
+ .btn {
pointer-events: none;
filter: none;
opacity: $form-check-btn-check-disabled-opacity;
}
}
}
@if $enable-dark-mode {
@include color-mode(dark) {
.form-switch .form-check-input:not(:checked):not(:focus) {
--#{$prefix}form-switch-bg: #{escape-svg($form-switch-bg-image-dark)};
}
}
}
}
+80 -56
View File
@@ -1,36 +1,45 @@
@use "sass:math";
@use "../config" as *;
@use "../variables" as *;
@use "../functions" as *;
@use "../vendor/rfs" as *;
@use "../mixins/border-radius" as *;
@use "../mixins/box-shadow" as *;
@use "../mixins/color-mode" as *;
@use "../mixins/focus-ring" as *;
@use "../mixins/gradients" as *;
@use "../mixins/transition" as *;
@use "form-variables" as *;
//
// General form controls (plus a few specific high-level interventions)
//
@layer forms {
.form-control {
--#{$prefix}control-min-height: #{$control-min-height};
--#{$prefix}control-padding-y: #{$control-padding-y};
--#{$prefix}control-padding-x: #{$control-padding-x};
--#{$prefix}control-font-size: #{$control-font-size};
--#{$prefix}control-line-height: #{$control-line-height};
--#{$prefix}control-color: #{$control-color};
--#{$prefix}control-bg: #{$control-bg};
--#{$prefix}control-border-width: #{$control-border-width};
--#{$prefix}control-border-color: #{$control-border-color};
--#{$prefix}control-border-radius: #{$control-border-radius};
--#{$prefix}control-select-bg-color: #{$control-select-indicator-color};
--#{$prefix}control-select-bg: #{escape-svg($control-select-indicator)};
--#{$prefix}control-select-bg-position: #{$control-select-bg-position};
--#{$prefix}control-select-bg-size: #{$control-select-bg-size};
display: block;
width: 100%;
padding: $input-padding-y $input-padding-x;
font-family: $input-font-family;
@include font-size($input-font-size);
font-weight: $input-font-weight;
line-height: $input-line-height;
color: $input-color;
appearance: none; // Fix appearance for date inputs in Safari
background-color: $input-bg;
min-height: var(--#{$prefix}control-min-height);
padding: var(--#{$prefix}control-padding-y) var(--#{$prefix}control-padding-x);
font-size: var(--#{$prefix}control-font-size);
line-height: var(--#{$prefix}control-line-height);
color: var(--#{$prefix}control-color);
appearance: none;
background-color: var(--#{$prefix}control-bg);
background-clip: padding-box;
border: $input-border-width solid $input-border-color;
// Note: This has no effect on <select>s in some browsers, due to the limited stylability of `<select>`s in CSS.
@include border-radius($input-border-radius, 0);
border: var(--#{$prefix}control-border-width) solid var(--#{$prefix}control-border-color);
@include border-radius(var(--#{$prefix}control-border-radius), 0);
@include box-shadow($input-box-shadow);
@include transition($input-transition);
@@ -99,16 +108,17 @@
// File input buttons theming
&::file-selector-button {
padding: $input-padding-y $input-padding-x;
margin: (-$input-padding-y) (-$input-padding-x);
margin-inline-end: $input-padding-x;
min-height: var(--#{$prefix}control-min-height);
padding: var(--#{$prefix}control-padding-y) var(--#{$prefix}control-padding-x);
margin: calc(var(--#{$prefix}control-padding-y) * -1) calc(var(--#{$prefix}control-padding-x) * -1);
margin-inline-end: var(--#{$prefix}control-padding-x);
color: $form-file-button-color;
@include gradient-bg($form-file-button-bg);
pointer-events: none;
border-color: inherit;
border-style: solid;
border-width: 0;
border-inline-end-width: $input-border-width;
border-inline-end-width: var(--#{$prefix}control-border-width);
border-radius: 0; // stylelint-disable-line property-disallowed-list
@include transition($btn-transition);
}
@@ -145,6 +155,28 @@
}
}
// stylelint-disable selector-no-qualifying-type
select.form-control {
padding-right: calc(var(--#{$prefix}control-padding-x) * 3);
background-image: var(--#{$prefix}control-select-bg);
background-repeat: no-repeat;
background-position: var(--#{$prefix}control-select-bg-position);
background-size: var(--#{$prefix}control-select-bg-size);
&[multiple],
&[size]:not([size="1"]) {
padding-right: var(--#{$prefix}control-padding-x);
background-image: none;
}
@if $enable-dark-mode {
@include color-mode(dark) {
--#{$prefix}control-select-indicator: #{escape-svg($control-select-indicator-dark)};
}
}
}
// stylelint-enable selector-no-qualifying-type
// Form control sizing
//
// Build on `.form-control` with modifier classes to decrease or increase the
@@ -153,48 +185,40 @@
// Repeated in `_input_group.scss` to avoid Sass extend issues.
.form-control-sm {
min-height: $input-height-sm;
padding: $input-padding-y-sm $input-padding-x-sm;
@include font-size($input-font-size-sm);
@include border-radius($input-border-radius-sm);
&::file-selector-button {
padding: $input-padding-y-sm $input-padding-x-sm;
margin: (-$input-padding-y-sm) (-$input-padding-x-sm);
margin-inline-end: $input-padding-x-sm;
}
--#{$prefix}control-min-height: #{$control-min-height-sm};
--#{$prefix}control-padding-y: #{$control-padding-y-sm};
--#{$prefix}control-padding-x: #{$control-padding-x-sm};
--#{$prefix}control-font-size: #{$control-font-size-sm};
--#{$prefix}control-line-height: #{$control-line-height-sm};
--#{$prefix}control-border-radius: #{$control-border-radius-sm};
}
.form-control-lg {
min-height: $input-height-lg;
padding: $input-padding-y-lg $input-padding-x-lg;
@include font-size($input-font-size-lg);
@include border-radius($input-border-radius-lg);
&::file-selector-button {
padding: $input-padding-y-lg $input-padding-x-lg;
margin: (-$input-padding-y-lg) (-$input-padding-x-lg);
margin-inline-end: $input-padding-x-lg;
}
--#{$prefix}control-min-height: #{$control-min-height-lg};
--#{$prefix}control-padding-y: #{$control-padding-y-lg};
--#{$prefix}control-padding-x: #{$control-padding-x-lg};
--#{$prefix}control-font-size: #{$control-font-size-lg};
--#{$prefix}control-line-height: #{$control-line-height-lg};
--#{$prefix}control-border-radius: #{$control-border-radius-lg};
}
// Make sure textareas don't shrink too much when resized
// https://github.com/twbs/bootstrap/pull/29124
// stylelint-disable selector-no-qualifying-type
textarea {
&.form-control {
min-height: $input-height;
}
// // Make sure textareas don't shrink too much when resized
// // https://github.com/twbs/bootstrap/pull/29124
// // stylelint-disable selector-no-qualifying-type
// textarea {
// &.form-control {
// min-height: $input-height;
// }
&.form-control-sm {
min-height: $input-height-sm;
}
// &.form-control-sm {
// min-height: $input-height-sm;
// }
&.form-control-lg {
min-height: $input-height-lg;
}
}
// stylelint-enable selector-no-qualifying-type
// &.form-control-lg {
// min-height: $input-height-lg;
// }
// }
// // stylelint-enable selector-no-qualifying-type
.form-control-color {
width: $form-color-width;
-127
View File
@@ -1,127 +0,0 @@
@use "../config" as *;
@use "../colors" as *;
@use "../variables" as *;
@use "../functions" as *;
@use "../vendor/rfs" as *;
@use "../mixins/border-radius" as *;
@use "../mixins/box-shadow" as *;
@use "../mixins/color-mode" as *;
@use "../mixins/focus-ring" as *;
@use "../mixins/transition" as *;
@use "form-variables" as *;
// scss-docs-start form-select-variables
$form-select-padding-y: $input-padding-y !default;
$form-select-padding-x: $input-padding-x !default;
$form-select-font-family: $input-font-family !default;
$form-select-font-size: $input-font-size !default;
$form-select-indicator-padding: $form-select-padding-x * 3 !default; // Extra padding for background-image
$form-select-font-weight: $input-font-weight !default;
$form-select-line-height: $input-line-height !default;
$form-select-color: $input-color !default;
$form-select-bg: $input-bg !default;
$form-select-disabled-color: null !default;
$form-select-disabled-bg: $input-disabled-bg !default;
$form-select-disabled-border-color: $input-disabled-border-color !default;
$form-select-bg-position: right $form-select-padding-x center !default;
$form-select-bg-size: 16px 12px !default; // In pixels because image dimensions
$form-select-indicator-color: $gray-800 !default;
$form-select-indicator: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path fill='none' stroke='#{$form-select-indicator-color}' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/></svg>") !default;
$form-select-feedback-icon-padding-end: $form-select-padding-x * 2.5 + $form-select-indicator-padding !default;
$form-select-feedback-icon-position: center right $form-select-indicator-padding !default;
$form-select-feedback-icon-size: $input-height-inner-half $input-height-inner-half !default;
$form-select-border-width: $input-border-width !default;
$form-select-border-color: $input-border-color !default;
$form-select-border-radius: $input-border-radius !default;
$form-select-box-shadow: var(--#{$prefix}box-shadow-inset) !default;
$form-select-focus-border-color: $input-focus-border-color !default;
$form-select-focus-width: $input-focus-width !default;
// $form-select-focus-box-shadow: 0 0 0 $form-select-focus-width $input-btn-focus-color !default;
$form-select-padding-y-sm: $input-padding-y-sm !default;
$form-select-padding-x-sm: $input-padding-x-sm !default;
$form-select-font-size-sm: $input-font-size-sm !default;
$form-select-border-radius-sm: $input-border-radius-sm !default;
$form-select-padding-y-lg: $input-padding-y-lg !default;
$form-select-padding-x-lg: $input-padding-x-lg !default;
$form-select-font-size-lg: $input-font-size-lg !default;
$form-select-border-radius-lg: $input-border-radius-lg !default;
$form-select-transition: $input-transition !default;
// scss-docs-end form-select-variables
@layer forms {
.form-select {
--#{$prefix}form-select-bg-img: #{escape-svg($form-select-indicator)};
display: block;
width: 100%;
padding: $form-select-padding-y $form-select-indicator-padding $form-select-padding-y $form-select-padding-x;
font-family: $form-select-font-family;
@include font-size($form-select-font-size);
font-weight: $form-select-font-weight;
line-height: $form-select-line-height;
color: $form-select-color;
appearance: none;
background-color: $form-select-bg;
background-image: var(--#{$prefix}form-select-bg-img), var(--#{$prefix}form-select-bg-icon, none);
background-repeat: no-repeat;
background-position: $form-select-bg-position;
background-size: $form-select-bg-size;
border: $form-select-border-width solid $form-select-border-color;
@include border-radius($form-select-border-radius, 0);
@include box-shadow($form-select-box-shadow);
@include transition($form-select-transition);
&:focus-visible {
border-color: $form-select-focus-border-color;
@include focus-ring(true);
}
&[multiple],
&[size]:not([size="1"]) {
padding-right: $form-select-padding-x;
background-image: none;
}
&:disabled {
color: $form-select-disabled-color;
background-color: $form-select-disabled-bg;
border-color: $form-select-disabled-border-color;
}
// Remove outline from select box in FF
&:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 $form-select-color;
}
}
.form-select-sm {
padding-top: $form-select-padding-y-sm;
padding-bottom: $form-select-padding-y-sm;
padding-left: $form-select-padding-x-sm;
@include font-size($form-select-font-size-sm);
@include border-radius($form-select-border-radius-sm);
}
.form-select-lg {
padding-top: $form-select-padding-y-lg;
padding-bottom: $form-select-padding-y-lg;
padding-left: $form-select-padding-x-lg;
@include font-size($form-select-font-size-lg);
@include border-radius($form-select-border-radius-lg);
}
@if $enable-dark-mode {
@include color-mode(dark) {
.form-select {
--#{$prefix}form-select-bg-img: #{escape-svg($form-select-indicator-dark)};
}
}
}
}
+51 -13
View File
@@ -1,18 +1,53 @@
@use "../config" as *;
@use "../colors" as *;
@use "../variables" as *;
$control-min-height: 2.5rem !default;
$control-min-height-sm: 2rem !default;
$control-min-height-lg: 3rem !default;
$control-padding-y: .375rem !default;
$control-padding-x: .75rem !default;
$control-font-size: $font-size-base !default;
$control-line-height: $line-height-base !default;
$control-color: var(--#{$prefix}body-color) !default;
$control-bg: var(--#{$prefix}body-bg) !default;
$control-border-width: var(--#{$prefix}border-width) !default;
$control-border-color: var(--#{$prefix}border-color) !default;
$control-border-radius: var(--#{$prefix}border-radius) !default;
$control-padding-y-sm: .25rem !default;
$control-padding-x-sm: .5rem !default;
$control-font-size-sm: $font-size-sm !default;
$control-line-height-sm: $line-height-sm !default;
$control-border-radius-sm: var(--#{$prefix}border-radius-sm) !default;
$control-padding-y-lg: .5rem !default;
$control-padding-x-lg: 1rem !default;
$control-font-size-lg: $font-size-lg !default;
$control-line-height-lg: $line-height-lg !default;
$control-border-radius-lg: var(--#{$prefix}border-radius-lg) !default;
$control-select-indicator-color: $gray-600 !default;
$control-select-indicator: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path fill='none' stroke='#{$control-select-indicator-color}' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/></svg>") !default;
$control-select-bg-position: right $control-padding-x center !default;
$control-select-bg-size: 16px 12px !default;
$control-select-indicator-color-dark: $body-color-dark !default;
$control-select-indicator-dark: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path fill='none' stroke='#{$control-select-indicator-color-dark}' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/></svg>") !default;
// scss-docs-start input-btn-variables
$input-btn-padding-y: .375rem !default;
$input-btn-padding-x: .75rem !default;
$input-btn-font-family: null !default;
// $input-btn-font-family: null !default;
$input-btn-font-size: $font-size-base !default;
$input-btn-line-height: $line-height-base !default;
$input-btn-focus-width: $focus-ring-width !default;
$input-btn-focus-color-opacity: $focus-ring-opacity !default;
$input-btn-focus-color: $focus-ring-color !default;
$input-btn-focus-blur: $focus-ring-blur !default;
$input-btn-focus-box-shadow: $focus-ring-box-shadow !default;
// $input-btn-focus-width: $focus-ring-width !default;
// $input-btn-focus-color-opacity: $focus-ring-opacity !default;
// $input-btn-focus-color: $focus-ring-color !default;
// $input-btn-focus-blur: $focus-ring-blur !default;
// $input-btn-focus-box-shadow: $focus-ring-box-shadow !default;
$input-btn-padding-y-sm: .25rem !default;
$input-btn-padding-x-sm: .5rem !default;
@@ -22,15 +57,15 @@ $input-btn-padding-y-lg: .5rem !default;
$input-btn-padding-x-lg: 1rem !default;
$input-btn-font-size-lg: $font-size-lg !default;
$input-btn-border-width: var(--#{$prefix}border-width) !default;
// $input-btn-border-width: var(--#{$prefix}border-width) !default;
// scss-docs-end input-btn-variables
// scss-docs-start form-input-variables
$input-padding-y: $input-btn-padding-y !default;
$input-padding-x: $input-btn-padding-x !default;
$input-font-family: $input-btn-font-family !default;
// $input-font-family: $input-btn-font-family !default;
$input-font-size: $input-btn-font-size !default;
$input-font-weight: $font-weight-base !default;
// $input-font-weight: $font-weight-base !default;
$input-line-height: $input-btn-line-height !default;
$input-padding-y-sm: $input-btn-padding-y-sm !default;
@@ -48,7 +83,7 @@ $input-disabled-border-color: null !default;
$input-color: var(--#{$prefix}body-color) !default;
$input-border-color: var(--#{$prefix}border-color) !default;
$input-border-width: $input-btn-border-width !default;
$input-border-width: var(--#{$prefix}border-width) !default;
$input-box-shadow: var(--#{$prefix}box-shadow-inset) !default;
$input-border-radius: var(--#{$prefix}border-radius) !default;
@@ -70,9 +105,12 @@ $input-height-inner: add($input-line-height * 1em, $input-pad
$input-height-inner-half: add($input-line-height * .5em, $input-padding-y) !default;
$input-height-inner-quarter: add($input-line-height * .25em, $input-padding-y * .5) !default;
$input-height: add($input-line-height * 1em, add($input-padding-y * 2, $input-height-border, false)) !default;
$input-height-sm: add($input-line-height * 1em, add($input-padding-y-sm * 2, $input-height-border, false)) !default;
$input-height-lg: add($input-line-height * 1em, add($input-padding-y-lg * 2, $input-height-border, false)) !default;
// $input-height: add($input-line-height * 1em, add($input-padding-y * 2, $input-height-border, false)) !default;
// $input-height-sm: add($input-line-height * 1em, add($input-padding-y-sm * 2, $input-height-border, false)) !default;
// $input-height-lg: add($input-line-height * 1em, add($input-padding-y-lg * 2, $input-height-border, false)) !default;
$input-height: 2.5rem !default;
$input-height-sm: 2rem !default;
$input-height-lg: 3rem !default;
$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
+2 -2
View File
@@ -10,7 +10,7 @@
// scss-docs-start input-group-variables
$input-group-addon-padding-y: $input-padding-y !default;
$input-group-addon-padding-x: $input-padding-x !default;
$input-group-addon-font-weight: $input-font-weight !default;
// $input-group-addon-font-weight: $input-font-weight !default;
$input-group-addon-color: $input-color !default;
$input-group-addon-bg: var(--#{$prefix}tertiary-bg) !default;
$input-group-addon-border-color: $input-border-color !default;
@@ -64,7 +64,7 @@ $input-group-addon-border-color: $input-border-color !default;
align-items: center;
padding: $input-group-addon-padding-y $input-group-addon-padding-x;
@include font-size($input-font-size); // Match inputs
font-weight: $input-group-addon-font-weight;
// font-weight: $input-group-addon-font-weight;
line-height: $input-line-height;
color: $input-group-addon-color;
text-align: center;
+79
View File
@@ -0,0 +1,79 @@
@use "../config" as *;
@use "../colors" as *;
@use "../variables" as *;
@use "../functions" as *;
@use "../vendor/rfs" as *;
@use "../mixins/border-radius" as *;
@use "../mixins/box-shadow" as *;
@use "../mixins/color-mode" as *;
@use "../mixins/focus-ring" as *;
@use "../mixins/transition" as *;
@use "form-variables" as *;
// scss-docs-start radio-variables
$radio-border-color: var(--#{$prefix}border-color) !default;
$radio-checked-bg: var(--#{$prefix}primary-base) !default;
$radio-checked-border-color: $radio-checked-bg !default;
$radio-disabled-bg: var(--#{$prefix}secondary-bg) !default;
$radio-disabled-border-color: $radio-disabled-bg !default;
$radio-disabled-opacity: .65 !default;
// scss-docs-end radio-variables
@layer forms {
b-radiogroup {
display: flex;
gap: var(--#{$prefix}gap, .5rem);
align-items: var(--#{$prefix}align-items, start);
.description {
color: var(--#{$prefix}secondary-text);
}
}
.radio {
// scss-docs-start radio-css-variables
--#{$prefix}radio-bg: transparent;
--#{$prefix}radio-border-color: #{$radio-border-color};
--#{$prefix}radio-checked-bg: #{$radio-checked-bg};
--#{$prefix}radio-checked-border-color: #{$radio-checked-border-color};
--#{$prefix}radio-disabled-bg: #{$radio-disabled-bg};
--#{$prefix}radio-disabled-border-color: #{$radio-disabled-border-color};
--#{$prefix}radio-disabled-opacity: #{$radio-disabled-opacity};
// scss-docs-end radio-css-variables
position: relative;
flex-shrink: 0;
width: 1rem;
height: 1rem;
margin-block: .125rem;
appearance: none;
background-color: var(--#{$prefix}radio-bg);
border: 1px solid var(--#{$prefix}radio-border-color);
// stylelint-disable-next-line property-disallowed-list
border-radius: 50%;
&:checked {
color: var(--#{$prefix}primary-contrast);
background-color: var(--#{$prefix}radio-checked-bg);
border-color: var(--#{$prefix}radio-checked-border-color);
&::before {
position: absolute;
inset: .25rem;
content: "";
background-color: currentcolor;
// stylelint-disable-next-line property-disallowed-list
border-radius: 50%;
}
}
&:disabled {
--#{$prefix}radio-bg: var(--#{$prefix}radio-disabled-bg);
~ label {
color: var(--#{$prefix}secondary-text);
cursor: default;
}
}
}
}
+89
View File
@@ -0,0 +1,89 @@
@use "../config" as *;
@use "../colors" as *;
@use "../variables" as *;
@use "../functions" as *;
@use "../vendor/rfs" as *;
@use "../mixins/border-radius" as *;
@use "../mixins/box-shadow" as *;
@use "../mixins/color-mode" as *;
@use "../mixins/focus-ring" as *;
@use "../mixins/transition" as *;
@use "form-variables" as *;
@layer forms {
.switch {
// scss-docs-start switch-css-variables
--#{$prefix}switch-height: 1.25rem;
--#{$prefix}switch-width: calc(var(--#{$prefix}switch-height) * 1.5);
--#{$prefix}switch-padding: .0625rem;
--#{$prefix}switch-bg: var(--#{$prefix}secondary-bg);
--#{$prefix}switch-border-width: var(--#{$prefix}border-width);
--#{$prefix}switch-border-color: var(--#{$prefix}border-color);
--#{$prefix}switch-indicator-bg: var(--#{$prefix}white);
--#{$prefix}switch-checked-bg: var(--#{$prefix}primary-base);
--#{$prefix}switch-checked-indicator-bg: var(--#{$prefix}white);
--#{$prefix}switch-disabled-bg: var(--#{$prefix}secondary-bg);
--#{$prefix}switch-disabled-indicator-bg: var(--#{$prefix}secondary-text);
// scss-docs-end switch-css-variables
position: relative;
display: flex;
flex-shrink: 0;
align-items: stretch;
justify-content: flex-start;
width: var(--#{$prefix}switch-width);
height: var(--#{$prefix}switch-height);
padding: var(--#{$prefix}switch-padding);
background-color: var(--#{$prefix}switch-bg);
border: var(--#{$prefix}switch-border-width) solid var(--#{$prefix}switch-border-color);
// stylelint-disable-next-line property-disallowed-list
border-radius: 10rem;
box-shadow: inset 0 1px 2px rgba($black, .05);
// stylelint-disable-next-line property-disallowed-list
transition: .15s ease-in-out;
transition-property: padding-inline-start, background-color;
&::before {
flex-shrink: 0;
width: calc(var(--#{$prefix}switch-height) - calc(var(--#{$prefix}switch-padding) * 2) - var(--#{$prefix}switch-border-width) * 2);
height: calc(var(--#{$prefix}switch-height) - calc(var(--#{$prefix}switch-padding) * 2) - var(--#{$prefix}switch-border-width) * 2);
// width: calc(var(--#{$prefix}switch-height) - calc(var(--#{$prefix}switch-padding) * 2));
// height: calc(var(--#{$prefix}switch-height) - calc(var(--#{$prefix}switch-padding) * 2));
content: "";
background-color: var(--#{$prefix}switch-indicator-bg);
// stylelint-disable-next-line property-disallowed-list
border-radius: 50%;
box-shadow: 0 1px 2px rgba($black, .1);
}
input {
position: absolute;
inset: 0;
appearance: none;
background-color: transparent;
}
&:has(input:checked) {
padding-inline-start: calc(var(--#{$prefix}switch-height) / 2 + var(--#{$prefix}switch-padding));
background-color: var(--#{$prefix}primary-base);
}
&:has(input:disabled) {
--#{$prefix}switch-bg: var(--#{$prefix}switch-disabled-bg);
--#{$prefix}switch-indicator-bg: var(--#{$prefix}switch-disabled-indicator-bg);
&::before { opacity: .4; }
~ label {
color: var(--#{$prefix}secondary-text);
cursor: default;
}
}
}
.switch-sm {
--#{$prefix}switch-height: 1em;
}
.switch-lg {
--#{$prefix}switch-height: 2em;
}
}
+3 -2
View File
@@ -1,8 +1,9 @@
@forward "labels";
@forward "form-text";
@forward "form-control";
@forward "form-select";
@forward "form-check";
@forward "check";
@forward "radio";
@forward "switch";
@forward "form-range";
@forward "floating-labels";
@forward "input-group";
+13 -2
View File
@@ -1,13 +1,24 @@
// stylelint-disable selector-no-qualifying-type
@layer helpers {
// scss-docs-start stacks
.hstack {
.hstack,
b-hstack {
display: flex;
flex-direction: row;
align-items: center;
align-self: stretch;
}
.hstack-start,
b-hstack[align="start"] {
display: flex;
flex-direction: row;
align-items: flex-start;
align-self: stretch;
}
.vstack {
.vstack,
b-vstack {
display: flex;
flex: 1 1 auto;
flex-direction: column;
+7 -7
View File
@@ -6,7 +6,7 @@
//
// Breakpoints are defined as a map of (name: minimum width), order from small to large:
//
// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1400px)
// (xs: 0, sm: 576px, md: 768px, lg: 1024px, xl: 1280px, 2xl: 1536px)
//
// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.
@@ -14,9 +14,9 @@
//
// >> breakpoint-next(sm)
// md
// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1400px))
// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 1024px, xl: 1280px, 2xl: 1536px))
// md
// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl xxl))
// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl 2xl))
// md
@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map.keys($breakpoints)) {
$n: list.index($breakpoint-names, $name);
@@ -28,7 +28,7 @@
// Minimum breakpoint width. Null for the smallest (first) breakpoint.
//
// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1400px))
// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 1024px, xl: 1280px, 2xl: 1536px))
// 576px
@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
$min: map.get($breakpoints, $name);
@@ -42,7 +42,7 @@
// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.
// See https://bugs.webkit.org/show_bug.cgi?id=178261
//
// >> breakpoint-max(md, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1400px))
// >> breakpoint-max(md, (xs: 0, sm: 576px, md: 768px, lg: 1024px, xl: 1280px, 2xl: 1536px))
// 767.98px
@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {
$max: map.get($breakpoints, $name);
@@ -52,9 +52,9 @@
// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.
// Useful for making responsive utilities.
//
// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1400px))
// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 1024px, xl: 1280px, 2xl: 1536px))
// "" (Returns a blank string)
// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1400px))
// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 1024px, xl: 1280px, 2xl: 1536px))
// "-sm"
@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {
@return if(breakpoint-min($name, $breakpoints) == null, "", "-#{$name}");
+118 -66
View File
@@ -3,22 +3,43 @@
@use "sass:meta";
@use "sass:string";
@use "../config" as *;
@use "../vendor/rfs" as *;
// stylelint-disable scss/dollar-variable-pattern
// Utility generator
// Used to generate utilities & print utilities
@mixin generate-utility($utility, $infix: "", $is-rfs-media-query: false) {
$values: map.get($utility, values);
// If the values are a list or string, convert it into a map
@if meta.type-of($values) == "string" or meta.type-of(list.nth($values, 1)) != "list" {
// A single value is converted to a map with a null key.
@if list.length($values) == 1 {
$values: (null: list.nth($values, 1));
// - Utilities can three different types of selectors:
// - class: .class
// - attr-starts: [class^="class"]
// - attr-includes: [class*="class"]
// - Utilities can generate a regular CSS property or a CSS custom property
// - Utilities can be responsive or not
// - Utilities can have a state (e.g., :hover, :focus, :active, etc.)
@mixin generate-utility($utility, $infix: "", $is-rfs-media-query: false) {
// Determine if we're generating a class, or an attribute selector
$selectorType: if(map.has-key($utility, selector), map.get($utility, selector), "class");
// Then get the class name to use in a class (e.g., .class) or in a attribute selector (e.g., [class^="class"])
$selectorClass: map.get($utility, class);
// Get the list or map of values and ensure it's a map
$values: map.get($utility, values);
@if meta.type-of($values) != "map" {
@if meta.type-of($values) == "list" {
$list: ();
@each $value in $values {
$list: map.merge($list, ($value: $value));
}
$values: $list;
} @else {
$values: list.zip($values, $values);
$values: (null: $values);
}
}
// Calculate infix once, before the loop
$infix: if($infix == "", "", "-" + $infix);
@each $key, $value in $values {
$properties: map.get($utility, property);
@@ -27,83 +48,114 @@
$properties: list.append((), $properties);
}
// Use custom class if present
$property-class: if(map.has-key($utility, class), map.get($utility, class), list.nth($properties, 1));
$property-class: if($property-class == null, "", $property-class);
// Use custom class if present, otherwise use the first value from the list of properties
$customClass: if(map.has-key($utility, class), map.get($utility, class), list.nth($properties, 1));
$customClass: if($customClass == null, "", $customClass);
// Use custom CSS variable name if present, otherwise default to `class`
$css-variable-name: if(map.has-key($utility, css-variable-name), map.get($utility, css-variable-name), map.get($utility, class));
// mdo-do: restore?
// $css-variable-name: if(map.has-key($utility, css-variable-name), map.get($utility, css-variable-name), map.get($utility, class));
// State params to generate pseudo-classes
$state: if(map.has-key($utility, state), map.get($utility, state), ());
$infix: if($property-class == "" and string.slice($infix, 1, 1) == "-", string.slice($infix, 2), $infix);
// $infix: if($customClass == "" and str-slice($infix, 1, 1) == "-", str-slice($infix, 2), $infix);
// Don't prefix if value key is null (e.g. with shadow class)
$property-class-modifier: if($key, if($property-class == "" and $infix == "", "", "-") + $key, "");
$customClassModifier: if($key, if($customClass == "" and $infix == "", "", "-") + $key, "");
@if map.get($utility, rfs) {
// Inside the media query
@if $is-rfs-media-query {
$val: rfs-value($value);
// Do not render anything if fluid and non fluid values are the same
$value: if($val == rfs-fluid-value($value), null, $val);
}
@else {
$value: rfs-fluid-value($value);
$selector: "";
@if $selectorType == "class" {
// Use the fallback of the first property if no `class` key is used
@if $customClass != "" {
$selector: ".#{$customClass + $infix + $customClassModifier}";
} @else {
$selector: ".#{$selectorClass + $infix + $customClassModifier}";
}
} @else if $selectorType == "attr-starts" {
$selector: "[class^=\"#{$selectorClass}\"]";
} @else if $selectorType == "attr-includes" {
$selector: "[class*=\"#{$selectorClass}\"]";
}
$is-css-var: map.get($utility, css-var);
$is-local-vars: map.get($utility, local-vars);
$is-rtl: map.get($utility, rtl);
$is-important: map.get($utility, important);
// @debug $utility;
// @debug $selectorType;
// @debug $selector;
// @debug $properties;
// @debug $values;
@if $value != null {
@if $is-rtl == false {
/* rtl:begin:remove */
}
@if $is-css-var {
.#{$property-class + $infix + $property-class-modifier} {
--#{$prefix}#{$css-variable-name}: #{$value};
#{$selector} {
@if map.get($utility, rfs) {
@if map.get($utility, important) {
@warn "The `important` option is not compatible with `rfs`. The `important` declaration will be ignored.";
}
@each $pseudo in $state {
.#{$property-class + $infix + $property-class-modifier}-#{$pseudo}:#{$pseudo} {
--#{$prefix}#{$css-variable-name}: #{$value};
@if $is-rfs-media-query {
@each $property in $properties {
@include rfs($value, $property);
}
}
@else {
@each $property in $properties {
@include rfs($value, $property);
}
}
} @else {
.#{$property-class + $infix + $property-class-modifier} {
@each $property in $properties {
@if $is-local-vars {
@each $local-var, $variable in $is-local-vars {
--#{$prefix}#{$local-var}: #{$variable};
}
}
#{$property}: $value if($is-important, !important, null);
@each $property in $properties {
@if map.get($utility, important) {
#{$property}: $value !important; // stylelint-disable-line declaration-no-important
} @else {
#{$property}: $value;
}
}
@each $pseudo in $state {
.#{$property-class + $infix + $property-class-modifier}-#{$pseudo}:#{$pseudo} {
@each $property in $properties {
@if $is-local-vars {
@each $local-var, $variable in $is-local-vars {
--#{$prefix}#{$local-var}: #{$variable};
}
}
#{$property}: $value if($is-important, !important, null);
}
}
}
}
@if $is-rtl == false {
/* rtl:end:remove */
}
}
// @if $value != null {
// #{$selector} {
// @each $property in $properties {
// #{$property}: $value;
// }
// }
// @if $is-css-var {
// #{$selector} {
// --#{$prefix}#{$css-variable-name}: #{$value};
// }
// @each $pseudo in $state {
// #{$selector}-#{$pseudo}:#{$pseudo} {
// --#{$prefix}#{$css-variable-name}: #{$value};
// }
// }
// } @else {
// #{$selector} {
// @each $property in $properties {
// // @if $is-local-vars {
// // @each $local-var, $variable in $is-local-vars {
// // --#{$prefix}#{$local-var}: #{$variable};
// // }
// // }
// #{$property}: $value;
// }
// }
// // @each $pseudo in $state {
// // #{$selector}-#{$pseudo}:#{$pseudo} {
// // @each $property in $properties {
// // @if $is-local-vars {
// // @each $local-var, $variable in $is-local-vars {
// // --#{$prefix}#{$local-var}: #{$variable};
// // }
// // }
// // #{$property}: $value;
// // }
// // }
// // }
// }
// }
$is-css-var: map.get($utility, css-var);
$is-local-vars: map.get($utility, local-vars);
// $is-rtl: map.get($utility, rtl);
}
}
+1 -1
View File
@@ -8,7 +8,7 @@ module.exports = {
spec_dir: 'scss',
// Make Jasmine look for `.test.scss` files
// spec_files: ['**/*.{test,spec}.scss'],
spec_files: ['**/_utilities.test.scss'],
spec_files: ['**/_utilities.test.scss', '**/modules/_configuration.test.scss'],
// Compile them into JS scripts running `sass-true`
requires: [path.join(__dirname, 'sass-true/register')],
// Ensure we use `require` so that the require.extensions works
@@ -0,0 +1,52 @@
// Test @use with configuration syntax using a single module instance
@use "../../alert" as * with (
$alert-margin-bottom: 3rem,
$alert-link-font-weight: 800
);
@use "../../variables" as *;
$true-terminal-output: false;
@include describe("Bootstrap module configuration") {
@include describe("@use with configuration syntax") {
@include it("should allow configuring alert variables with @use ... with") {
@include assert() {
@include output() {
.test {
margin-bottom: $alert-margin-bottom;
font-weight: $alert-link-font-weight;
}
}
@include expect() {
.test {
margin-bottom: 3rem;
font-weight: 800;
}
}
}
}
@include it("should maintain other alert variables with default values") {
@include assert() {
@include output() {
.test {
padding-y: $alert-padding-y;
padding-x: $alert-padding-x;
// stylelint-disable-next-line property-disallowed-list
border-radius: $alert-border-radius;
}
}
@include expect() {
.test {
padding-y: 1rem;
padding-x: 1rem;
// stylelint-disable-next-line property-disallowed-list
border-radius: var(--bs-border-radius);
}
}
}
}
}
}
+8 -8
View File
@@ -19,17 +19,17 @@
- breakpoint: lg
abbr: -lg
name: Large
min-width: 992px
min-width: 1024px
container: 960px
- breakpoint: xl
abbr: -xl
name: X-Large
min-width: 1200px
container: 1140px
min-width: 1280px
container: 1200px
- breakpoint: xxl
abbr: -xxl
name: XX-Large
min-width: 1400px
container: 1320px
- breakpoint: 2xl
abbr: -2xl
name: 2X-Large
min-width: 1536px
container: 1440px
+45 -19
View File
@@ -60,8 +60,9 @@
pages:
- title: Overview
- title: Form control
- title: Select
- title: Checks & radios
- title: Checkbox
- title: Radio
- title: Switch
- title: Range
- title: Input group
- title: Floating labels
@@ -117,27 +118,52 @@
icon_color: red
pages:
- title: API
- title: Aspect ratio
- title: Background
- title: Border
- title: Border radius
- title: Colors
- title: Display
- title: Flex
- title: Float
- title: Interactions
- title: Link
- title: Object fit
- title: Opacity
- title: Overflow
- title: Position
- title: Shadows
- title: Sizing
- title: Spacing
- title: Text
- title: Vertical align
- title: Visibility
- title: Z-index
- group: Layout
pages:
- title: Aspect ratio
- title: Display
- title: Float
- title: Object fit
- title: Overflow
- title: Position
- title: Visibility
- title: Z-index
- group: Flex & Grid
pages:
- title: Align content
- title: Align items
- title: Align self
- title: Flex
- title: Justify content
- title: Justify items
- title: Place items
- group: Sizing
pages:
- title: Width
- title: Height
- group: Spacing
pages:
- title: Margin
- title: Padding
- group: Type
pages:
- title: Font style
- title: Text alignment
- title: Text decoration
- title: Text wrapping
- title: Vertical align
- group: Interactions
pages:
- title: Pointer events
- title: User select
- group: Effects
pages:
- title: Opacity
- title: Shadows
- title: Extend
icon: tools
+46 -4
View File
@@ -29,8 +29,50 @@ const sidebar = getData('sidebar')
{group.title}
</strong>
<ul class="list-unstyled fw-normal pb-2 small">
{group.pages?.map((page) => {
const docSlug = getSlug(page.title)
{group.pages?.map((item: any) => {
// Handle sub-groups
if (item.group && item.pages) {
return (
<li class="mb-2">
<div class="bd-links-subgroup fw-semibold mt-3">
{item.group}
</div>
<ul class="list-unstyled">
{item.pages.map((page: any) => {
const docSlug = getSlug(page.title)
const unversionedPageSlug = `${groupSlug}/${docSlug}`
const url = `/docs/${getConfig().docs_version}/${unversionedPageSlug}`
const active = Astro.params.slug === unversionedPageSlug
const generatedPage = docsPages.find((page) => page.slug === unversionedPageSlug)
// This test should not be necessary, see comments for `getSlug()` in `src/libs/utils.ts`.
if (!generatedPage) {
throw new Error(
`The page '${page.title}' referenced in 'site/data/sidebar.yml' does not exist at '${url}'.`
)
}
return (
<li>
<a
href={url}
class:list={['bd-links-link d-inline-block rounded', { active }]}
aria-current={active ? 'page' : undefined}
>
{page.title}
</a>
</li>
)
})}
</ul>
</li>
)
}
// Handle regular pages
const docSlug = getSlug(item.title)
const unversionedPageSlug = `${groupSlug}/${docSlug}`
const url = `/docs/${getConfig().docs_version}/${unversionedPageSlug}`
@@ -41,7 +83,7 @@ const sidebar = getData('sidebar')
// This test should not be necessary, see comments for `getSlug()` in `src/libs/utils.ts`.
if (!generatedPage) {
throw new Error(
`The page '${page.title}' referenced in 'site/data/sidebar.yml' does not exist at '${url}'.`
`The page '${item.title}' referenced in 'site/data/sidebar.yml' does not exist at '${url}'.`
)
}
@@ -52,7 +94,7 @@ const sidebar = getData('sidebar')
class:list={['bd-links-link d-inline-block rounded', { active }]}
aria-current={active ? 'page' : undefined}
>
{page.title}
{item.title}
</a>
</li>
)
@@ -44,7 +44,7 @@ These classes can also be added to groups of links, as an alternative to the [`.
## Checkbox and radio button groups
Combine button-like checkbox and radio [toggle buttons]([[docsref:/forms/checks-radios]]) into a seamless looking button group.
Combine button-like checkbox and radio toggle buttons into a seamless looking button group.
<Example code={`<div class="btn-group" role="group" aria-label="Basic checkbox toggle button group">
<input type="checkbox" class="btn-check" id="btncheck1" autocomplete="off">
+72 -2
View File
@@ -15,7 +15,7 @@ Bootstrap has a base `.btn` class that sets up basic styles such as padding and
The `.btn` class is intended to be used in conjunction with our button variants, or to serve as a basis for your own custom styles.
<Callout type="warning">
If you are using the `.btn` class on its own, remember to at least define some explicit `:focus` and/or `:focus-visible` styles.
When using `.btn` without a modifier, be sure to add some explicit `:focus-visible` styles.
</Callout>
## Variants
@@ -126,12 +126,82 @@ Additional utilities can be used to adjust the alignment of buttons when horizon
<button class="btn btn-primary" type="button">Button</button>
</div>`} />
## Toggle buttons
Create button-like checkboxes and radio buttons by using `.btn` styles rather than `.form-check-label` on the `<label>` elements. These toggle buttons can further be grouped in a [button group]([[docsref:/components/button-group]]) if needed.
### Checkbox toggle buttons
<Example code={`<input type="checkbox" class="btn-check" id="btn-check" autocomplete="off">
<label class="btn btn-primary" for="btn-check">Single toggle</label>
<input type="checkbox" class="btn-check" id="btn-check-2" checked autocomplete="off">
<label class="btn btn-primary" for="btn-check-2">Checked</label>
<input type="checkbox" class="btn-check" id="btn-check-3" autocomplete="off" disabled>
<label class="btn btn-primary" for="btn-check-3">Disabled</label>`} />
<Example code={`<input type="checkbox" class="btn-check" id="btn-check-4" autocomplete="off">
<label class="btn" for="btn-check-4">Single toggle</label>
<input type="checkbox" class="btn-check" id="btn-check-5" checked autocomplete="off">
<label class="btn" for="btn-check-5">Checked</label>
<input type="checkbox" class="btn-check" id="btn-check-6" autocomplete="off" disabled>
<label class="btn" for="btn-check-6">Disabled</label>`} />
<Callout>
Visually, these checkbox toggle buttons are identical to the [button plugin toggle buttons]([[docsref:/components/buttons#button-plugin]]). However, they are conveyed differently by assistive technologies: the checkbox toggles will be announced by screen readers as “checked“/“not checked“ (since, despite their appearance, they are fundamentally still checkboxes), whereas the button plugin toggle buttons will be announced as “button“/“button pressed“. The choice between these two approaches will depend on the type of toggle you are creating, and whether or not the toggle will make sense to users when announced as a checkbox or as an actual button.
</Callout>
### Radio toggle buttons
<Example code={`<input type="radio" class="btn-check" name="options" id="option1" autocomplete="off" checked>
<label class="btn btn-secondary" for="option1">Checked</label>
<input type="radio" class="btn-check" name="options" id="option2" autocomplete="off">
<label class="btn btn-secondary" for="option2">Radio</label>
<input type="radio" class="btn-check" name="options" id="option3" autocomplete="off" disabled>
<label class="btn btn-secondary" for="option3">Disabled</label>
<input type="radio" class="btn-check" name="options" id="option4" autocomplete="off">
<label class="btn btn-secondary" for="option4">Radio</label>`} />
<Example code={`<input type="radio" class="btn-check" name="options-base" id="option5" autocomplete="off" checked>
<label class="btn" for="option5">Checked</label>
<input type="radio" class="btn-check" name="options-base" id="option6" autocomplete="off">
<label class="btn" for="option6">Radio</label>
<input type="radio" class="btn-check" name="options-base" id="option7" autocomplete="off" disabled>
<label class="btn" for="option7">Disabled</label>
<input type="radio" class="btn-check" name="options-base" id="option8" autocomplete="off">
<label class="btn" for="option8">Radio</label>`} />
### Outlined styles
Different variants of `.btn`, such as the various outlined styles, are supported.
<Example code={`<input type="checkbox" class="btn-check" id="btn-check-outlined" autocomplete="off">
<label class="btn btn-outline-primary" for="btn-check-outlined">Single toggle</label><br>
<input type="checkbox" class="btn-check" id="btn-check-2-outlined" checked autocomplete="off">
<label class="btn btn-outline-secondary" for="btn-check-2-outlined">Checked</label><br>
<input type="radio" class="btn-check" name="options-outlined" id="success-outlined" autocomplete="off" checked>
<label class="btn btn-outline-success" for="success-outlined">Checked success radio</label>
<input type="radio" class="btn-check" name="options-outlined" id="danger-outlined" autocomplete="off">
<label class="btn btn-outline-danger" for="danger-outlined">Danger radio</label>`} />
## Button plugin
The button plugin allows you to create simple on/off toggle buttons.
<Callout>
Visually, these toggle buttons are identical to the [checkbox toggle buttons]([[docsref:/forms/checks-radios#checkbox-toggle-buttons]]). However, they are conveyed differently by assistive technologies: the checkbox toggles will be announced by screen readers as “checked”/“not checked” (since, despite their appearance, they are fundamentally still checkboxes), whereas these toggle buttons will be announced as “button”/“button pressed”. The choice between these two approaches will depend on the type of toggle you are creating, and whether or not the toggle will make sense to users when announced as a checkbox or as an actual button.
Visually, these toggle buttons are identical to the [checkbox toggle buttons]([[docsref:/forms/checkbox]]). However, they are conveyed differently by assistive technologies: the checkbox toggles will be announced by screen readers as “checked”/“not checked” (since, despite their appearance, they are fundamentally still checkboxes), whereas these toggle buttons will be announced as “button”/“button pressed”. The choice between these two approaches will depend on the type of toggle you are creating, and whether or not the toggle will make sense to users when announced as a checkbox or as an actual button.
</Callout>
### Toggle states
@@ -8,7 +8,7 @@ toc: true
Dropdowns are toggleable, contextual overlays for displaying lists of links and more. Theyre made interactive with the included Bootstrap dropdown JavaScript plugin. Theyre toggled by clicking, not by hovering; this is [an intentional design decision](https://markdotto.com/blog/bootstrap-explained-dropdowns/).
Dropdowns are built on a third party library, [Popper](https://popper.js.org/docs/v2/), which provides dynamic positioning and viewport detection. Be sure to include [popper.min.js]([[config:cdn.popper]]) before Bootstraps JavaScript or use `bootstrap.bundle.min.js` / `bootstrap.bundle.js` which contains Popper. Popper isnt used to position dropdowns in navbars though as dynamic positioning isnt required.
Dropdowns are built on a third party library, [Floating UI](https://floating-ui.com/), which provides dynamic positioning and viewport detection. Be sure to include [floating-ui.dom.umd.min.js]([[config:cdn.floating_ui]]) before Bootstrap's JavaScript or use `bootstrap.bundle.min.js` / `bootstrap.bundle.js` which contains Floating UI. Floating UI isn't used to position dropdowns in navbars though as dynamic positioning isn't required.
## Accessibility
@@ -645,7 +645,7 @@ Add `.dropdown-menu-end` to a `.dropdown-menu` to right align the dropdown menu.
If you want to use responsive alignment, disable dynamic positioning by adding the `data-bs-display="static"` attribute and use the responsive variation classes.
To align **right** the dropdown menu with the given breakpoint or larger, add `.dropdown-menu{-sm|-md|-lg|-xl|-xxl}-end`.
To align **right** the dropdown menu with the given breakpoint or larger, add `.dropdown-menu{-sm|-md|-lg|-xl|-2xl}-end`.
<Example code={`<div class="btn-group">
<button type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" data-bs-display="static" aria-expanded="false">
@@ -658,7 +658,7 @@ To align **right** the dropdown menu with the given breakpoint or larger, add `.
</ul>
</div>`} />
To align **left** the dropdown menu with the given breakpoint or larger, add `.dropdown-menu-end` and `.dropdown-menu{-sm|-md|-lg|-xl|-xxl}-start`.
To align **left** the dropdown menu with the given breakpoint or larger, add `.dropdown-menu-end` and `.dropdown-menu{-sm|-md|-lg|-xl|-2xl}-start`.
<Example code={`<div class="btn-group">
<button type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" data-bs-display="static" aria-expanded="false">
@@ -112,7 +112,7 @@ These work great with custom content as well.
## Horizontal
Add `.list-group-horizontal` to change the layout of list group items from vertical to horizontal across all breakpoints. Alternatively, choose a responsive variant `.list-group-horizontal-{sm|md|lg|xl|xxl}` to make a list group horizontal starting at that breakpoints `min-width`. Currently **horizontal list groups cannot be combined with flush list groups.**
Add `.list-group-horizontal` to change the layout of list group items from vertical to horizontal across all breakpoints. Alternatively, choose a responsive variant `.list-group-horizontal-{sm|md|lg|xl|2xl}` to make a list group horizontal starting at that breakpoints `min-width`. Currently **horizontal list groups cannot be combined with flush list groups.**
**ProTip:** Want equal-width list group items when horizontal? Add `.flex-fill` to each list group item.
+8 -8
View File
@@ -533,7 +533,7 @@ Modals have three optional sizes, available via modifier classes to be placed on
| Small | `.modal-sm` | `300px` |
| Default | <span class="text-body-secondary">None</span> | `500px` |
| Large | `.modal-lg` | `800px` |
| Extra large | `.modal-xl` | `1140px` |
| Extra large | `.modal-xl` | `1200px` |
</BsTable>
Our default modal without modifier class constitutes the “medium” size modal.
@@ -600,9 +600,9 @@ Another override is the option to pop up a modal that covers the user viewport,
| `.modal-fullscreen` | Always |
| `.modal-fullscreen-sm-down` | `576px` |
| `.modal-fullscreen-md-down` | `768px` |
| `.modal-fullscreen-lg-down` | `992px` |
| `.modal-fullscreen-xl-down` | `1200px` |
| `.modal-fullscreen-xxl-down` | `1400px` |
| `.modal-fullscreen-lg-down` | `1024px` |
| `.modal-fullscreen-xl-down` | `1280px` |
| `.modal-fullscreen-2xl-down` | `1536px` |
</BsTable>
<Example showMarkup={false} code={`<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModalFullscreen">Full screen</button>
@@ -610,7 +610,7 @@ Another override is the option to pop up a modal that covers the user viewport,
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModalFullscreenMd">Full screen below md</button>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModalFullscreenLg">Full screen below lg</button>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModalFullscreenXl">Full screen below xl</button>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModalFullscreenXxl">Full screen below xxl</button>`} />
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModalFullscreen2xl">Full screen below 2xl</button>`} />
```html
<!-- Full screen modal -->
@@ -704,11 +704,11 @@ Another override is the option to pop up a modal that covers the user viewport,
</div>
</div>
<div class="modal fade" id="exampleModalFullscreenXxl" tabindex="-1" aria-labelledby="exampleModalFullscreenXxlLabel" aria-hidden="true">
<div class="modal-dialog modal-fullscreen-xxl-down">
<div class="modal fade" id="exampleModalFullscreen2xl" tabindex="-1" aria-labelledby="exampleModalFullscreen2xlLabel" aria-hidden="true">
<div class="modal-dialog modal-fullscreen-2xl-down">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-4" id="exampleModalFullscreenXxlLabel">Full screen below xxl</h1>
<h1 class="modal-title fs-4" id="exampleModalFullscreen2xlLabel">Full screen below 2xl</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
+2 -2
View File
@@ -10,7 +10,7 @@ import { getConfig } from '@libs/config'
Heres what you need to know before getting started with the navbar:
- Navbars require a wrapping `.navbar` with `.navbar-expand{-sm|-md|-lg|-xl|-xxl}` for responsive collapsing and [color scheme](#color-schemes) classes.
- Navbars require a wrapping `.navbar` with `.navbar-expand{-sm|-md|-lg|-xl|-2xl}` for responsive collapsing and [color scheme](#color-schemes) classes.
- Navbars and their contents are fluid by default. Change the [container](#containers) to limit their horizontal width in different ways.
- Use our [spacing]([[docsref:/utilities/spacing]]) and [flex]([[docsref:/utilities/flex]]) utility classes for controlling spacing and alignment within navbars.
- Navbars are responsive by default, but you can easily modify them to change that. Responsive behavior depends on our Collapse JavaScript plugin.
@@ -499,7 +499,7 @@ Heres an example navbar using `.navbar-nav-scroll` with `style="--bs-scroll-h
## Responsive behaviors
Navbars can use `.navbar-toggler`, `.navbar-collapse`, and `.navbar-expand{-sm|-md|-lg|-xl|-xxl}` classes to determine when their content collapses behind a button. In combination with other utilities, you can easily choose when to show or hide particular elements.
Navbars can use `.navbar-toggler`, `.navbar-collapse`, and `.navbar-expand{-sm|-md|-lg|-xl|-2xl}` classes to determine when their content collapses behind a button. In combination with other utilities, you can easily choose when to show or hide particular elements.
For navbars that never collapse, add the `.navbar-expand` class on the navbar. For navbars that always collapse, dont add any `.navbar-expand` class.
@@ -146,7 +146,7 @@ Responsive offcanvas classes hide content outside the viewport from a specified
- `.offcanvas-md`
- `.offcanvas-lg`
- `.offcanvas-xl`
- `.offcanvas-xxl`
- `.offcanvas-2xl`
To make a responsive offcanvas, replace the `.offcanvas` base class with a responsive variant and ensure your close button has an explicit `data-bs-target`.
@@ -8,7 +8,7 @@ toc: true
Things to know when using the popover plugin:
- Popovers rely on the third party library [Popper](https://popper.js.org/docs/v2/) for positioning. You must include [popper.min.js]([[config:cdn.popper]]) before `bootstrap.js`, or use one `bootstrap.bundle.min.js` which contains Popper.
- Popovers rely on the third party library [Floating UI](https://floating-ui.com/) for positioning. You must include [floating-ui.dom.umd.min.js]([[config:cdn.floating_ui]]) before `bootstrap.js`, or use one `bootstrap.bundle.min.js` which contains Floating UI.
- Popovers require the [popover plugin]([[docsref:/components/popovers]]) as a dependency.
- Popovers are opt-in for performance reasons, so **you must initialize them yourself**.
- Zero-length `title` and `content` values will never show a popover.
@@ -8,7 +8,7 @@ toc: true
Things to know when using the tooltip plugin:
- Tooltips rely on the third party library [Popper](https://popper.js.org/docs/v2/) for positioning. You must include [popper.min.js]([[config:cdn.popper]]) before `bootstrap.js`, or use one `bootstrap.bundle.min.js` which contains Popper.
- Tooltips rely on the third party library [Floating UI](https://floating-ui.com/) for positioning. You must include [floating-ui.dom.umd.min.js]([[config:cdn.floating_ui]]) before `bootstrap.js`, or use one `bootstrap.bundle.min.js` which contains Floating UI.
- Tooltips are opt-in for performance reasons, so **you must initialize them yourself**.
- Tooltips with zero-length titles are never displayed.
- Specify `container: 'body'` to avoid rendering problems in more complex components (like our input groups, button groups, etc).
+2 -2
View File
@@ -653,7 +653,7 @@ You can also put the `<caption>` on the top of the table with `.caption-top`.
## Responsive tables
Responsive tables allow tables to be scrolled horizontally with ease. Make any table responsive across all viewports by wrapping a `.table` with `.table-responsive`. Or, pick a maximum breakpoint with which to have a responsive table up to by using `.table-responsive{-sm|-md|-lg|-xl|-xxl}`.
Responsive tables allow tables to be scrolled horizontally with ease. Make any table responsive across all viewports by wrapping a `.table` with `.table-responsive`. Or, pick a maximum breakpoint with which to have a responsive table up to by using `.table-responsive{-sm|-md|-lg|-xl|-2xl}`.
<Callout type="warning">
##### Vertical clipping/truncation
@@ -734,7 +734,7 @@ Across every breakpoint, use `.table-responsive` for horizontally scrolling tabl
### Breakpoint specific
Use `.table-responsive{-sm|-md|-lg|-xl|-xxl}` as needed to create responsive tables up to a particular breakpoint. From that breakpoint and up, the table will behave normally and not scroll horizontally.
Use `.table-responsive{-sm|-md|-lg|-xl|-2xl}` as needed to create responsive tables up to a particular breakpoint. From that breakpoint and up, the table will behave normally and not scroll horizontally.
**These tables may appear broken until their responsive styles apply at specific viewport widths.**
@@ -42,10 +42,7 @@ Several Bootstrap components include embedded SVGs in our CSS to style component
- [Accordion]([[docsref:/components/accordion]])
- [Carousel controls]([[docsref:/components/carousel#with-controls]])
- [Close button]([[docsref:/components/close-button]]) (used in alerts and modals)
- [Form checkboxes and radio buttons]([[docsref:/forms/checks-radios]])
- [Form switches]([[docsref:/forms/checks-radios#switches]])
- [Form validation icons]([[docsref:/forms/validation#server-side]])
- [Navbar toggle buttons]([[docsref:/components/navbar#responsive-behaviors]])
- [Select menus]([[docsref:/forms/select]])
Based on [community conversation](https://github.com/twbs/bootstrap/issues/25394), some options for addressing this in your own codebase include [replacing the URLs with locally hosted assets]([[docsref:/getting-started/webpack#extracting-svg-files]]), removing the images and using inline images (not possible in all components), and modifying your CSP. Our recommendation is to carefully review your own security policies and decide on the best path forward, if necessary.
+117
View File
@@ -0,0 +1,117 @@
---
title: Checkbox
description: Highly customizable, native checkbox `<input>` elements for presenting toggleable options.
toc: true
---
**Trialing new components with the following rules:**
- New components are purely components, they don't assume layout of any kind.
- New options for form layout:
- Use new form groups to lay out your forms: `.control-group`, `.check-group`, `.radio-group`.
- Use helpers to lay out your forms—`.hstack` and `.vstack`—with utilities.
## Basic checkbox
All checkbox styling is contained to a wrapper class, `.check`. This does the following:
- Adds a stacking grid layout for the checkbox and custom SVG icon.
- Overrides the default `<input>` appearance with themed colors.
- Handles the toggling of separate paths in our custom SVG for the `:checked` and indeterminate states. Two `<path>`s are included in the SVG, one for each state, and the appropriate `<path>` is shown based on the `<input>`s state.
For folks looking to replace our provided icons, you'll need to add the `.checked` and `.indeterminate` classes to the `<path>`s and use them in a single `<svg>` element.
Checkbox layout and labels are handled with additional HTML and CSS.
<Example code={`<div class="check">
<input type="checkbox" id="check" checked />
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'>
<path class="checked" fill='none' stroke='currentcolor' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/>
<path class="indeterminate" fill='none' stroke='currentcolor' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/>
</svg>
</div>`} />
## Indeterminate
Checkboxes can utilize the indeterminate pseudo class when manually set via JavaScript. There is no available HTML attribute for specifying it.
<Example addStackblitzJs class="bd-example-indeterminate" code={`<div class="check">
<input type="checkbox" id="checkIndeterminate" />
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'>
<path class="checked" fill='none' stroke='currentcolor' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/>
<path class="indeterminate" fill='none' stroke='currentcolor' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/>
</svg>
</div>`} />
## Label
Wrap the `.check` in a `<b-checkgroup>` layout component and add your label. We use a custom element for layout here that sets some basic flexbox styling.
Consider margin utilities for additional spacing, and flex utilities for alignment.
<Example code={`<b-checkgroup>
<div class="check">
<input type="checkbox" id="checkLabel" />
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'>
<path class="checked" fill='none' stroke='currentcolor' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/>
<path class="indeterminate" fill='none' stroke='currentcolor' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/>
</svg>
</div>
<label for="checkLabel">Example new checkbox</label>
</b-checkgroup>`} />
## Description
With this layout approach, you can easily add a description or other content after the label. Here we use another custom element, `<b-vstack>`, to stack the label and description.
<Example code={`<b-checkgroup>
<div class="check">
<input type="checkbox" id="checkDescription" />
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'>
<path class="checked" fill='none' stroke='currentcolor' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/>
<path class="indeterminate" fill='none' stroke='currentcolor' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/>
</svg>
</div>
<b-vstack>
<label for="checkDescription">Example new checkbox</label>
<small class="description">Supporting description for the above label.</small>
</b-vstack>
</b-checkgroup>`} />
## Disabled
Add the `disabled` attribute and the associated `<label>`s are automatically styled to match with a lighter color to help indicate the inputs state.
<Example code={`<b-checkgroup>
<div class="check">
<input type="checkbox" id="checkDisabled" disabled />
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'>
<path class="checked" fill='none' stroke='currentcolor' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/>
<path class="indeterminate" fill='none' stroke='currentcolor' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/>
</svg>
</div>
<label for="checkDisabled">Example new checkbox</label>
</b-checkgroup>`} />
<Example code={`<b-checkgroup>
<div class="check">
<input type="checkbox" id="checkDisabledChecked" checked disabled />
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'>
<path class="checked" fill='none' stroke='currentcolor' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/>
<path class="indeterminate" fill='none' stroke='currentcolor' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/>
</svg>
</div>
<label for="checkDisabledChecked">Example new checkbox</label>
</b-checkgroup>`} />
## CSS
### Variables
CSS variables for the checkbox component are built on the Sass variables.
<ScssDocs name="check-css-variables" file="scss/forms/_check.scss" />
### Sass variables
<ScssDocs name="check-variables" file="scss/forms/_check.scss" />
@@ -1,311 +0,0 @@
---
title: Checks and radios
description: Create consistent cross-browser and cross-device checkboxes and radios with our completely rewritten checks component.
aliases: "/docs/[[config:docs_version]]/forms/checks/"
toc: true
---
## Approach
Browser default checkboxes and radios are replaced with the help of `.form-check`, a series of classes for both input types that improves the layout and behavior of their HTML elements, that provide greater customization and cross browser consistency. Checkboxes are for selecting one or several options in a list, while radios are for selecting one option from many.
Structurally, our `<input>`s and `<label>`s are sibling elements as opposed to an `<input>` within a `<label>`. This is slightly more verbose as you must specify `id` and `for` attributes to relate the `<input>` and `<label>`. We use the sibling selector (`~`) for all our `<input>` states, like `:checked` or `:disabled`. When combined with the `.form-check-label` class, we can easily style the text for each item based on the `<input>`s state.
Our checks use custom Bootstrap icons to indicate checked or indeterminate states.
## Checks
<Example code={`<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="checkDefault">
<label class="form-check-label" for="checkDefault">
Default checkbox
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="checkChecked" checked>
<label class="form-check-label" for="checkChecked">
Checked checkbox
</label>
</div>`} />
### Indeterminate
Checkboxes can utilize the `:indeterminate` pseudo class when manually set via JavaScript (there is no available HTML attribute for specifying it).
<Example addStackblitzJs class="bd-example-indeterminate" code={`<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="checkIndeterminate">
<label class="form-check-label" for="checkIndeterminate">
Indeterminate checkbox
</label>
</div>`} />
### Disabled
Add the `disabled` attribute and the associated `<label>`s are automatically styled to match with a lighter color to help indicate the inputs state.
<Example addStackblitzJs class="bd-example-indeterminate" code={`<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="checkIndeterminateDisabled" disabled>
<label class="form-check-label" for="checkIndeterminateDisabled">
Disabled indeterminate checkbox
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="checkDisabled" disabled>
<label class="form-check-label" for="checkDisabled">
Disabled checkbox
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="checkCheckedDisabled" checked disabled>
<label class="form-check-label" for="checkCheckedDisabled">
Disabled checked checkbox
</label>
</div>`} />
## Radios
<Example code={`<div class="form-check">
<input class="form-check-input" type="radio" name="radioDefault" id="radioDefault1">
<label class="form-check-label" for="radioDefault1">
Default radio
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="radioDefault" id="radioDefault2" checked>
<label class="form-check-label" for="radioDefault2">
Default checked radio
</label>
</div>`} />
### Disabled
Add the `disabled` attribute and the associated `<label>`s are automatically styled to match with a lighter color to help indicate the inputs state.
<Example code={`<div class="form-check">
<input class="form-check-input" type="radio" name="radioDisabled" id="radioDisabled" disabled>
<label class="form-check-label" for="radioDisabled">
Disabled radio
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="radioDisabled" id="radioCheckedDisabled" checked disabled>
<label class="form-check-label" for="radioCheckedDisabled">
Disabled checked radio
</label>
</div>`} />
## Switches
A switch has the markup of a custom checkbox but uses the `.form-switch` class to render a toggle switch. Consider using `role="switch"` to more accurately convey the nature of the control to assistive technologies that support this role. In older assistive technologies, it will simply be announced as a regular checkbox as a fallback. Switches also support the `disabled` attribute.
<Example code={`<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="switchCheckDefault">
<label class="form-check-label" for="switchCheckDefault">Default switch checkbox input</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="switchCheckChecked" checked>
<label class="form-check-label" for="switchCheckChecked">Checked switch checkbox input</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="switchCheckDisabled" disabled>
<label class="form-check-label" for="switchCheckDisabled">Disabled switch checkbox input</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="switchCheckCheckedDisabled" checked disabled>
<label class="form-check-label" for="switchCheckCheckedDisabled">Disabled checked switch checkbox input</label>
</div>`} />
### Native switches
Progressively enhance your switches for mobile Safari (iOS 17.4+) by adding a `switch` attribute to your input to enable haptic feedback when toggling switches, just like native iOS switches. There are no style changes attached to using this attribute in Bootstrap as all our switches use custom styles.
<Example code={`<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" value="" id="checkNativeSwitch" switch>
<label class="form-check-label" for="checkNativeSwitch">
Native switch haptics
</label>
</div>`} />
Be sure to read more about [the switch attribute on the WebKit blog](https://webkit.org/blog/15054/an-html-switch-control/). Safari 17.4+ on macOS and iOS both have native-style switches in HTML while other browsers simply fall back to the standard checkbox appearance. Applying the attribute to a non-Bootstrap checkbox in more recent versions of Safari will render a native switch.
## Default (stacked)
By default, any number of checkboxes and radios that are immediate sibling will be vertically stacked and appropriately spaced with `.form-check`.
<Example code={`<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="defaultCheck1">
<label class="form-check-label" for="defaultCheck1">
Default checkbox
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="defaultCheck2" disabled>
<label class="form-check-label" for="defaultCheck2">
Disabled checkbox
</label>
</div>`} />
<Example code={`<div class="form-check">
<input class="form-check-input" type="radio" name="exampleRadios" id="exampleRadios1" value="option1" checked>
<label class="form-check-label" for="exampleRadios1">
Default radio
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="exampleRadios" id="exampleRadios2" value="option2">
<label class="form-check-label" for="exampleRadios2">
Second default radio
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="exampleRadios" id="exampleRadios3" value="option3" disabled>
<label class="form-check-label" for="exampleRadios3">
Disabled radio
</label>
</div>`} />
## Inline
Group checkboxes or radios on the same horizontal row by adding `.form-check-inline` to any `.form-check`.
<Example code={`<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="inlineCheckbox1" value="option1">
<label class="form-check-label" for="inlineCheckbox1">1</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="inlineCheckbox2" value="option2">
<label class="form-check-label" for="inlineCheckbox2">2</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="inlineCheckbox3" value="option3" disabled>
<label class="form-check-label" for="inlineCheckbox3">3 (disabled)</label>
</div>`} />
<Example code={`<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="inlineRadioOptions" id="inlineRadio1" value="option1">
<label class="form-check-label" for="inlineRadio1">1</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="inlineRadioOptions" id="inlineRadio2" value="option2">
<label class="form-check-label" for="inlineRadio2">2</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="inlineRadioOptions" id="inlineRadio3" value="option3" disabled>
<label class="form-check-label" for="inlineRadio3">3 (disabled)</label>
</div>`} />
## Reverse
Put your checkboxes, radios, and switches on the opposite side with the `.form-check-reverse` modifier class.
<Example code={`<div class="form-check form-check-reverse">
<input class="form-check-input" type="checkbox" value="" id="reverseCheck1">
<label class="form-check-label" for="reverseCheck1">
Reverse checkbox
</label>
</div>
<div class="form-check form-check-reverse">
<input class="form-check-input" type="checkbox" value="" id="reverseCheck2" disabled>
<label class="form-check-label" for="reverseCheck2">
Disabled reverse checkbox
</label>
</div>
<div class="form-check form-switch form-check-reverse">
<input class="form-check-input" type="checkbox" id="switchCheckReverse">
<label class="form-check-label" for="switchCheckReverse">Reverse switch checkbox input</label>
</div>`} />
## Without labels
Omit the wrapping `.form-check` for checkboxes and radios that have no label text. Remember to still provide some form of accessible name for assistive technologies (for instance, using `aria-label`). See the [forms overview accessibility]([[docsref:/forms/overview/#accessibility]]) section for details.
<Example code={`<div>
<input class="form-check-input" type="checkbox" id="checkboxNoLabel" value="" aria-label="...">
</div>
<div>
<input class="form-check-input" type="radio" name="radioNoLabel" id="radioNoLabel1" value="" aria-label="...">
</div>`} />
## Toggle buttons
Create button-like checkboxes and radio buttons by using `.btn` styles rather than `.form-check-label` on the `<label>` elements. These toggle buttons can further be grouped in a [button group]([[docsref:/components/button-group]]) if needed.
### Checkbox toggle buttons
<Example code={`<input type="checkbox" class="btn-check" id="btn-check" autocomplete="off">
<label class="btn btn-primary" for="btn-check">Single toggle</label>
<input type="checkbox" class="btn-check" id="btn-check-2" checked autocomplete="off">
<label class="btn btn-primary" for="btn-check-2">Checked</label>
<input type="checkbox" class="btn-check" id="btn-check-3" autocomplete="off" disabled>
<label class="btn btn-primary" for="btn-check-3">Disabled</label>`} />
<Example code={`<input type="checkbox" class="btn-check" id="btn-check-4" autocomplete="off">
<label class="btn" for="btn-check-4">Single toggle</label>
<input type="checkbox" class="btn-check" id="btn-check-5" checked autocomplete="off">
<label class="btn" for="btn-check-5">Checked</label>
<input type="checkbox" class="btn-check" id="btn-check-6" autocomplete="off" disabled>
<label class="btn" for="btn-check-6">Disabled</label>`} />
<Callout>
Visually, these checkbox toggle buttons are identical to the [button plugin toggle buttons]([[docsref:/components/buttons#button-plugin]]). However, they are conveyed differently by assistive technologies: the checkbox toggles will be announced by screen readers as “checked“/“not checked“ (since, despite their appearance, they are fundamentally still checkboxes), whereas the button plugin toggle buttons will be announced as “button“/“button pressed“. The choice between these two approaches will depend on the type of toggle you are creating, and whether or not the toggle will make sense to users when announced as a checkbox or as an actual button.
</Callout>
### Radio toggle buttons
<Example code={`<input type="radio" class="btn-check" name="options" id="option1" autocomplete="off" checked>
<label class="btn btn-secondary" for="option1">Checked</label>
<input type="radio" class="btn-check" name="options" id="option2" autocomplete="off">
<label class="btn btn-secondary" for="option2">Radio</label>
<input type="radio" class="btn-check" name="options" id="option3" autocomplete="off" disabled>
<label class="btn btn-secondary" for="option3">Disabled</label>
<input type="radio" class="btn-check" name="options" id="option4" autocomplete="off">
<label class="btn btn-secondary" for="option4">Radio</label>`} />
<Example code={`<input type="radio" class="btn-check" name="options-base" id="option5" autocomplete="off" checked>
<label class="btn" for="option5">Checked</label>
<input type="radio" class="btn-check" name="options-base" id="option6" autocomplete="off">
<label class="btn" for="option6">Radio</label>
<input type="radio" class="btn-check" name="options-base" id="option7" autocomplete="off" disabled>
<label class="btn" for="option7">Disabled</label>
<input type="radio" class="btn-check" name="options-base" id="option8" autocomplete="off">
<label class="btn" for="option8">Radio</label>`} />
### Outlined styles
Different variants of `.btn`, such as the various outlined styles, are supported.
<Example code={`<input type="checkbox" class="btn-check" id="btn-check-outlined" autocomplete="off">
<label class="btn btn-outline-primary" for="btn-check-outlined">Single toggle</label><br>
<input type="checkbox" class="btn-check" id="btn-check-2-outlined" checked autocomplete="off">
<label class="btn btn-outline-secondary" for="btn-check-2-outlined">Checked</label><br>
<input type="radio" class="btn-check" name="options-outlined" id="success-outlined" autocomplete="off" checked>
<label class="btn btn-outline-success" for="success-outlined">Checked success radio</label>
<input type="radio" class="btn-check" name="options-outlined" id="danger-outlined" autocomplete="off">
<label class="btn btn-outline-danger" for="danger-outlined">Danger radio</label>`} />
## CSS
### Sass variables
Variables for checks:
<ScssDocs name="form-check-variables" file="scss/forms/_form-check.scss" />
Variables for switches:
<ScssDocs name="form-switch-variables" file="scss/forms/_form-check.scss" />
+77 -6
View File
@@ -1,9 +1,13 @@
---
title: Form controls
description: Give textual form controls like `<input>`s and `<textarea>`s an upgrade with custom styles, sizing, focus states, and more.
description: Give textual `<input>`, `<textarea>`, and `<select>` elements an upgrade with custom styles, sizing, focus states, and more.
toc: true
---
<Callout type="info">
**Heads up!** As of v6, `<select>` elements are now styled with the `.form-control` class. This reduces a ton of duplication and abstraction while making it easier to consistently customize the appearance of form controls.
</Callout>
## Example
Form controls are styled with a mix of Sass and CSS variables, allowing them to adapt to color modes and support any customization method.
@@ -13,17 +17,78 @@ Form controls are styled with a mix of Sass and CSS variables, allowing them to
<input type="email" class="form-control" id="exampleFormControlInput1" placeholder="name@example.com">
</div>
<div class="mb-3">
<label for="exampleFormControlSelect1" class="form-label">Example select</label>
<select class="form-control" id="exampleFormControlSelect1">
<option>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
</div>
<div>
<label for="exampleFormControlTextarea1" class="form-label">Example textarea</label>
<textarea class="form-control" id="exampleFormControlTextarea1" rows="3"></textarea>
</div>`} />
## Sizing
Set heights using classes like `.form-control-lg` and `.form-control-sm`.
Change the size of a form control by using classes like `.form-control-lg` and `.form-control-sm`. This adjusts `height`, `padding`, `font-size`, `line-height`, and `border-radius`.
<Example code={`<input class="form-control form-control-lg" type="text" placeholder=".form-control-lg" aria-label=".form-control-lg example">
<input class="form-control" type="text" placeholder="Default input" aria-label="default input example">
<input class="form-control form-control-sm" type="text" placeholder=".form-control-sm" aria-label=".form-control-sm example">`} />
<Example code={`<div class="mb-3">
<label for="largeInput" class="form-label">Large input</label>
<input class="form-control form-control-lg" type="text" id="largeInput" placeholder="Large input" aria-label="Large input example">
</div>
<div class="mb-3">
<label for="largeSelect" class="form-label">Large select</label>
<select class="form-control form-control-lg" id="largeSelect">
<option>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
</div>
<div>
<label for="largeTextarea" class="form-label">Large textarea</label>
<textarea class="form-control form-control-lg" id="largeTextarea" rows="3" placeholder="Large textarea" aria-label="Large textarea example"></textarea>
</div>`} />
<Example code={`<div class="mb-3">
<label for="smallInput" class="form-label">Small input</label>
<input class="form-control form-control-sm" type="text" id="smallInput" placeholder="Small input" aria-label="Small input example">
</div>
<div class="mb-3">
<label for="smallSelect" class="form-label">Small select</label>
<select class="form-control form-control-sm" id="smallSelect">
<option>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
</div>
<div>
<label for="smallTextarea" class="form-label">Small textarea</label>
<textarea class="form-control form-control-sm" id="smallTextarea" rows="3" placeholder="Small textarea" aria-label="Small textarea example"></textarea>
</div>`} />
## Select
The `multiple` attribute is supported on select elements:
<Example code={`<select class="form-select" multiple aria-label="Multiple select example">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>`} />
As is the `size` attribute:
<Example code={`<select class="form-select" size="3" aria-label="Size 3 select example">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>`} />
## Form text
@@ -62,7 +127,13 @@ Inline text can use any typical inline HTML element (be it a `<span>`, `<small>`
Add the `disabled` boolean attribute on an input to give it a grayed out appearance, remove pointer events, and prevent focusing.
<Example code={`<input class="form-control" type="text" placeholder="Disabled input" aria-label="Disabled input example" disabled>
<input class="form-control" type="text" value="Disabled readonly input" aria-label="Disabled input example" disabled readonly>`} />
<input class="form-control" type="text" value="Disabled readonly input" aria-label="Disabled input example" disabled readonly>
<select class="form-select" aria-label="Disabled select example" disabled>
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>`} />
## Readonly
+56
View File
@@ -0,0 +1,56 @@
---
title: Radio
description: Highly customizable, native radio `<input>` elements for choosing one option from many.
toc: true
---
## Basic radio
Similar to checkboxes, radios are styled with the `.radio` class. However, there's no custom SVG as we use a Unicode character for the checked state.
<Example code={`<input type="radio" id="radio" class="radio" />`} />
## Label
Wrap the `.radio` in a `<b-radiogroup>` layout component and add your label. We use a custom element for layout here that sets some basic flexbox styling.
<Example code={`<b-radiogroup>
<input type="radio" id="radioLabel" class="radio" />
<label for="radioLabel">Example new radio</label>
</b-radiogroup>
`} />
## Description
With this layout approach, you can easily add a description or other content after the label. Here we use another custom element, `<b-vstack>`, to stack the label and description.
<Example code={`<b-radiogroup>
<input type="radio" id="radioLabelDescription" class="radio" />
<b-vstack>
<label for="radioLabelDescription">Example new radio</label>
<small class="description">Supporting description for the above label.</small>
</b-vstack>
</b-radiogroup>
`} />
## Disabled
Add the `disabled` attribute and the associated `<label>`s are automatically styled to match with a lighter color to help indicate the inputs state.
<Example code={`<b-radiogroup>
<input type="radio" id="radioDisabled" class="radio" disabled />
<label for="radioDisabled">Example new radio</label>
</b-radiogroup>
`} />
## CSS
### Variables
CSS variables for the radio component are built on the Sass variables.
<ScssDocs name="radio-css-variables" file="scss/forms/_radio.scss" />
### Sass variables
<ScssDocs name="radio-variables" file="scss/forms/_radio.scss" />
-69
View File
@@ -1,69 +0,0 @@
---
title: Select
description: Customize the native `<select>`s with custom CSS that changes the elements initial appearance.
toc: true
---
## Default
Custom `<select>` menus need only a custom class, `.form-select` to trigger the custom styles. Custom styles are limited to the `<select>`s initial appearance and cannot modify the `<option>`s due to browser limitations.
<Example code={`<select class="form-select" aria-label="Default select example">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>`} />
## Sizing
You may also choose from small and large custom selects to match our similarly sized text inputs.
<Example code={`<select class="form-select form-select-lg mb-3" aria-label="Large select example">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
<select class="form-select form-select-sm" aria-label="Small select example">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>`} />
The `multiple` attribute is also supported:
<Example code={`<select class="form-select" multiple aria-label="Multiple select example">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>`} />
As is the `size` attribute:
<Example code={`<select class="form-select" size="3" aria-label="Size 3 select example">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>`} />
## Disabled
Add the `disabled` boolean attribute on a select to give it a grayed out appearance and remove pointer events.
<Example code={`<select class="form-select" aria-label="Disabled select example" disabled>
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>`} />
## CSS
### Sass variables
<ScssDocs name="form-select-variables" file="scss/forms/_form-select.scss" />
+68
View File
@@ -0,0 +1,68 @@
---
title: Switch
description: Custom toggle component built on top of native `<input>` checkbox elements.
toc: true
---
## Basic switch
Switches are built with checkboxes under the hood, so their HTML closely mirrors that of checkboxes, including optional layout components.
Switches work by layering an invisible checkbox over the custom switch indicator. This preserves interactivity while giving you a completely customizable layer underneath.
Switches also include the `switch` attribute for browsers that support it. This provides haptic feedback when toggling the switch.
<Example code={`<div class="switch">
<input type="checkbox" value="" id="switch" switch>
</div>`} />
## Label
Wrap the `.switch` in a `<b-checkgroup>` layout component and add your label. We use a custom element for layout here that sets some basic flexbox styling. Switches are checkboxes under the hood, so we reused the same custom element here.
Consider margin utilities for additional spacing, and flex utilities for alignment, especially when using small or large switches.
<Example class="d-flex flex-column gap-3" code={`<b-checkgroup>
<div class="switch switch-sm mt-1">
<input type="checkbox" value="" id="switchSmLabel" switch>
</div>
<label for="switchSmLabel">Small switch</label>
</b-checkgroup>
<b-checkgroup>
<div class="switch">
<input type="checkbox" value="" id="switchMdLabel" switch>
</div>
<label for="switchMdLabel">Default switch</label>
</b-checkgroup>`} />
## Disabled
Add the `disabled` attribute and the associated `<label>`s are automatically styled to match with a lighter color to help indicate the inputs state.
<Example class="d-flex flex-column gap-3" code={`<b-checkgroup>
<div class="switch">
<input type="checkbox" value="" id="switchDisabledLabel" switch disabled>
</div>
<label for="switchDisabledLabel">Disabled switch</label>
</b-checkgroup>`} />
## Sizes
Add a size modifier class to make your switch appear smaller or larger.
<Example class="d-flex flex-column gap-3" code={`<div class="switch switch-sm">
<input type="checkbox" value="" id="switchSizeSm" switch>
</div>
<div class="switch">
<input type="checkbox" value="" id="switchSizeMd" switch>
</div>
<div class="switch switch-lg">
<input type="checkbox" value="" id="switchSizeLg" switch>
</div>`} />
## CSS
### Variables
<ScssDocs name="switch-css-variables" file="scss/forms/_switch.scss" />
@@ -11,7 +11,7 @@ Download ready-to-use compiled code for **Bootstrap v[[config:current_version]]*
- Compiled and minified CSS bundles (see [CSS files comparison]([[docsref:/getting-started/contents#css-files]]))
- Compiled and minified JavaScript plugins (see [JS files comparison]([[docsref:/getting-started/contents#js-files]]))
This doesnt include documentation, source files, or any optional JavaScript dependencies like Popper.
This doesn't include documentation, source files, or any optional JavaScript dependencies like Floating UI.
<a href="[[config:download.dist]]" class="btn btn-bd-primary">Download</a>
@@ -41,10 +41,10 @@ Skip the download with [jsDelivr](https://www.jsdelivr.com/) to deliver cached v
<script src="[[config:cdn.js_bundle]]" integrity="[[config:cdn.js_bundle_hash]]" crossorigin="anonymous"></script>
```
If youre using our compiled JavaScript and prefer to include Popper separately, add Popper before our JS, via a CDN preferably.
If you're using our compiled JavaScript and prefer to include Floating UI separately, add Floating UI before our JS, via a CDN preferably.
```html
<script src="[[config:cdn.popper]]" integrity="[[config:cdn.popper_hash]]" crossorigin="anonymous"></script>
<script src="[[config:cdn.floating_ui]]" integrity="[[config:cdn.floating_ui_hash]]" crossorigin="anonymous"></script>
<script src="[[config:cdn.js]]" integrity="[[config:cdn.js_hash]]" crossorigin="anonymous"></script>
```
@@ -30,7 +30,7 @@ Get started by including Bootstraps production-ready CSS and JavaScript via C
</html>
```
2. **Include Bootstraps CSS and JS.** Place the `<link>` tag in the `<head>` for our CSS, and the `<script>` tag for our JavaScript bundle (including Popper for positioning dropdowns, popovers, and tooltips) before the closing `</body>`. Learn more about our [CDN links](#cdn-links).
2. **Include Bootstrap's CSS and JS.** Place the `<link>` tag in the `<head>` for our CSS, and the `<script>` tag for our JavaScript bundle (including Floating UI for positioning dropdowns, popovers, and tooltips) before the closing `</body>`. Learn more about our [CDN links](#cdn-links).
```html
<!doctype html>
@@ -48,10 +48,10 @@ Get started by including Bootstraps production-ready CSS and JavaScript via C
</html>
```
You can also include [Popper](https://popper.js.org/docs/v2/) and our JS separately. If you dont plan to use dropdowns, popovers, or tooltips, save some kilobytes by not including Popper.
You can also include [Floating UI](https://floating-ui.com/) and our JS separately. If you don't plan to use dropdowns, popovers, or tooltips, save some kilobytes by not including Floating UI.
```html
<script src="[[config:cdn.popper]]" integrity="[[config:cdn.popper_hash]]" crossorigin="anonymous"></script>
<script src="[[config:cdn.floating_ui]]" integrity="[[config:cdn.floating_ui_hash]]" crossorigin="anonymous"></script>
<script src="[[config:cdn.js]]" integrity="[[config:cdn.js_hash]]" crossorigin="anonymous"></script>
```
@@ -41,19 +41,19 @@ We provide a version of Bootstrap built as `ESM` (`bootstrap.esm.js` and `bootst
</script>
```
Compared to JS bundlers, using ESM in the browser requires you to use the full path and filename instead of the module name. [Read more about JS modules in the browser.](https://v8.dev/features/modules#specifiers) Thats why we use `'bootstrap.esm.min.js'` instead of `'bootstrap'` above. However, this is further complicated by our Popper dependency, which imports Popper into our JavaScript like so:
Compared to JS bundlers, using ESM in the browser requires you to use the full path and filename instead of the module name. [Read more about JS modules in the browser.](https://v8.dev/features/modules#specifiers) Thats why we use `'bootstrap.esm.min.js'` instead of `'bootstrap'` above. However, this is further complicated by our Floating UI dependency, which imports Floating UI into our JavaScript like so:
```js
import * as Popper from "@popperjs/core"
import { computePosition } from "@floating-ui/dom"
```
If you try this as-is, youll see an error in the console like the following:
If you try this as-is, you'll see an error in the console like the following:
```text
Uncaught TypeError: Failed to resolve module specifier "@popperjs/core". Relative references must start with either "/", "./", or "../".
Uncaught TypeError: Failed to resolve module specifier "@floating-ui/dom". Relative references must start with either "/", "./", or "../".
```
To fix this, you can use an `importmap` to resolve the arbitrary module names to complete paths. If your [targeted browsers](https://caniuse.com/?search=importmap) do not support `importmap`, youll need to use the [es-module-shims](https://github.com/guybedford/es-module-shims) project. Heres how it works for Bootstrap and Popper:
To fix this, you can use an `importmap` to resolve the arbitrary module names to complete paths. If your [targeted browsers](https://caniuse.com/?search=importmap) do not support `importmap`, you'll need to use the [es-module-shims](https://github.com/guybedford/es-module-shims) project. Here's how it works for Bootstrap and Floating UI:
```html
<!doctype html>
@@ -72,7 +72,7 @@ To fix this, you can use an `importmap` to resolve the arbitrary module names to
<script type="importmap">
{
"imports": {
"@popperjs/core": "[[config:cdn.popper_esm]]",
"@floating-ui/dom": "[[config:cdn.floating_ui_esm]]",
"bootstrap": "https://cdn.jsdelivr.net/npm/bootstrap@[[config:current_version]]/dist/js/bootstrap.esm.min.js"
}
}
@@ -29,7 +29,7 @@ The `rfs()` mixin has shorthands for `font-size`, `margin`, `margin-top`, `margi
font-size: calc(1.525rem + 3.3vw);
}
@media (min-width: 1200px) {
@media (min-width: 1280px) {
.title {
font-size: 4rem;
}
@@ -49,12 +49,12 @@ You can see the above requirements reflected in this modified RTL starter templa
<!-- Optional JavaScript; choose one of the two! -->
<!-- Option 1: Bootstrap Bundle with Popper -->
<!-- Option 1: Bootstrap Bundle with Floating UI -->
<script src="[[config:cdn.js_bundle]]" integrity="[[config:cdn.js_bundle_hash]]" crossorigin="anonymous"></script>
<!-- Option 2: Separate Popper and Bootstrap JS -->
<!-- Option 2: Separate Floating UI and Bootstrap JS -->
<!--
<script src="[[config:cdn.popper]]" integrity="[[config:cdn.popper_hash]]" crossorigin="anonymous"></script>
<script src="[[config:cdn.floating_ui]]" integrity="[[config:cdn.floating_ui_hash]]" crossorigin="anonymous"></script>
<script src="[[config:cdn.js]]" integrity="[[config:cdn.js_hash]]" crossorigin="anonymous"></script>
-->
</body>
+2 -2
View File
@@ -46,7 +46,7 @@ Responsive variations also exist for `.sticky-top` utility.
<div class="sticky-md-top">Stick to the top on viewports sized MD (medium) or wider</div>
<div class="sticky-lg-top">Stick to the top on viewports sized LG (large) or wider</div>
<div class="sticky-xl-top">Stick to the top on viewports sized XL (extra-large) or wider</div>
<div class="sticky-xxl-top">Stick to the top on viewports sized XXL (extra-extra-large) or wider</div>
<div class="sticky-2xl-top">Stick to the top on viewports sized 2XL (extra-extra-large) or wider</div>
```
## Sticky bottom
@@ -66,5 +66,5 @@ Responsive variations also exist for `.sticky-bottom` utility.
<div class="sticky-md-bottom">Stick to the bottom on viewports sized MD (medium) or wider</div>
<div class="sticky-lg-bottom">Stick to the bottom on viewports sized LG (large) or wider</div>
<div class="sticky-xl-bottom">Stick to the bottom on viewports sized XL (extra-large) or wider</div>
<div class="sticky-xxl-bottom">Stick to the bottom on viewports sized XXL (extra-extra-large) or wider</div>
<div class="sticky-2xl-bottom">Stick to the bottom on viewports sized 2XL (extra-extra-large) or wider</div>
```
+14 -14
View File
@@ -23,9 +23,9 @@ Bootstrap includes six default breakpoints, sometimes referred to as _grid tiers
| Extra small | <em>None</em> |&lt;576px |
| Small | `sm` | &ge;576px |
| Medium | `md` | &ge;768px |
| Large | `lg` | &ge;992px |
| Extra large | `xl` | &ge;1200px |
| Extra extra large | `xxl` | &ge;1400px |
| Large | `lg` | &ge;1024px |
| Extra large | `xl` | &ge;1280px |
| Extra extra large | `2xl` | &ge;1536px |
</BsTable>
Each breakpoint was chosen to comfortably hold containers whose widths are multiples of 12. Breakpoints are also representative of a subset of common device sizes and viewport dimensions—they dont specifically target every use case or device. Instead, the ranges provide a strong and consistent foundation to build on for nearly any device.
@@ -52,7 +52,7 @@ Bootstrap primarily uses the following media query ranges—or breakpoints—in
@include media-breakpoint-up(md) { ... }
@include media-breakpoint-up(lg) { ... }
@include media-breakpoint-up(xl) { ... }
@include media-breakpoint-up(xxl) { ... }
@include media-breakpoint-up(2xl) { ... }
// Usage
@@ -79,14 +79,14 @@ These Sass mixins translate in our compiled CSS using the values declared in our
// Medium devices (tablets, 768px and up)
@media (min-width: 768px) { ... }
// Large devices (desktops, 992px and up)
@media (min-width: 992px) { ... }
// Large devices (desktops, 1024px and up)
@media (min-width: 1024px) { ... }
// X-Large devices (large desktops, 1200px and up)
@media (min-width: 1200px) { ... }
// X-Large devices (large desktops, 1280px and up)
@media (min-width: 1280px) { ... }
// XX-Large devices (larger desktops, 1400px and up)
@media (min-width: 1400px) { ... }
// XX-Large devices (larger desktops, 1536px and up)
@media (min-width: 1536px) { ... }
```
### Max-width
@@ -99,7 +99,7 @@ We occasionally use media queries that go in the other direction (the given scre
@include media-breakpoint-down(md) { ... }
@include media-breakpoint-down(lg) { ... }
@include media-breakpoint-down(xl) { ... }
@include media-breakpoint-down(xxl) { ... }
@include media-breakpoint-down(2xl) { ... }
// Example: Style from medium breakpoint and down
@include media-breakpoint-down(md) {
@@ -127,8 +127,8 @@ These mixins take those declared breakpoints, subtract `.02px` from them, and us
// `xl` applies to large devices (desktops, less than 1200px)
@media (max-width: 1199.98px) { ... }
// `xxl` applies to x-large devices (large desktops, less than 1400px)
@media (max-width: 1399.98px) { ... }
// `2xl` applies to x-large devices (large desktops, less than 1600px)
@media (max-width: 1599.98px) { ... }
```
<Callout name="info-mediaqueries-breakpoints" type="warning" />
@@ -143,7 +143,7 @@ There are also media queries and mixins for targeting a single segment of screen
@include media-breakpoint-only(md) { ... }
@include media-breakpoint-only(lg) { ... }
@include media-breakpoint-only(xl) { ... }
@include media-breakpoint-only(xxl) { ... }
@include media-breakpoint-only(2xl) { ... }
```
For example the `@include media-breakpoint-only(md) { ... }` will result in :
+9 -9
View File
@@ -19,14 +19,14 @@ The table below illustrates how each containers `max-width` compares to the o
See them in action and compare them in our [Grid example]([[docsref:/examples/grid/#containers]]).
<BsTable>
| | Extra small<div class="fw-normal">&lt;576px</div> | Small<div class="fw-normal">&ge;576px</div> | Medium<div class="fw-normal">&ge;768px</div> | Large<div class="fw-normal">&ge;992px</div> | X-Large<div class="fw-normal">&ge;1200px</div> | XX-Large<div class="fw-normal">&ge;1400px</div> |
| | Extra small<div class="fw-normal">&lt;576px</div> | Small<div class="fw-normal">&ge;576px</div> | Medium<div class="fw-normal">&ge;768px</div> | Large<div class="fw-normal">&ge;1024px</div> | X-Large<div class="fw-normal">&ge;1280px</div> | 2X-Large<div class="fw-normal">&ge;1536px</div> |
| --- | --- | --- | --- | --- | --- | --- |
| `.container` | <span class="text-body-secondary">100%</span> | 540px | 720px | 960px | 1140px | 1320px |
| `.container-sm` | <span class="text-body-secondary">100%</span> | 540px | 720px | 960px | 1140px | 1320px |
| `.container-md` | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | 720px | 960px | 1140px | 1320px |
| `.container-lg` | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | 960px | 1140px | 1320px |
| `.container-xl` | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | 1140px | 1320px |
| `.container-xxl` | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | 1320px |
| `.container` | <span class="text-body-secondary">100%</span> | 540px | 720px | 960px | 1140px | 1440px |
| `.container-sm` | <span class="text-body-secondary">100%</span> | 540px | 720px | 960px | 1140px | 1440px |
| `.container-md` | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | 720px | 960px | 1140px | 1440px |
| `.container-lg` | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | 960px | 1140px | 1440px |
| `.container-xl` | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | 1140px | 1440px |
| `.container-2xl` | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | 1440px |
| `.container-fluid` | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> | <span class="text-body-secondary">100%</span> |
</BsTable>
@@ -42,14 +42,14 @@ Our default `.container` class is a responsive, fixed-width container, meaning i
## Responsive containers
Responsive containers allow you to specify a class that is 100% wide until the specified breakpoint is reached, after which we apply `max-width`s for each of the higher breakpoints. For example, `.container-sm` is 100% wide to start until the `sm` breakpoint is reached, where it will scale up with `md`, `lg`, `xl`, and `xxl`.
Responsive containers allow you to specify a class that is 100% wide until the specified breakpoint is reached, after which we apply `max-width`s for each of the higher breakpoints. For example, `.container-sm` is 100% wide to start until the `sm` breakpoint is reached, where it will scale up with `md`, `lg`, `xl`, and `2xl`.
```html
<div class="container-sm">100% wide until small breakpoint</div>
<div class="container-md">100% wide until medium breakpoint</div>
<div class="container-lg">100% wide until large breakpoint</div>
<div class="container-xl">100% wide until extra large breakpoint</div>
<div class="container-xxl">100% wide until extra extra large breakpoint</div>
<div class="container-2xl">100% wide until extra extra large breakpoint</div>
```
## Fluid containers
+8 -8
View File
@@ -35,7 +35,7 @@ The above example creates three equal-width columns across all devices and viewp
Breaking it down, heres how the grid system comes together:
- **Our grid supports [six responsive breakpoints]([[docsref:/layout/breakpoints]]).** Breakpoints are based on `min-width` media queries, meaning they affect that breakpoint and all those above it (e.g., `.col-sm-4` applies to `sm`, `md`, `lg`, `xl`, and `xxl`). This means you can control container and column sizing and behavior by each breakpoint.
- **Our grid supports [six responsive breakpoints]([[docsref:/layout/breakpoints]]).** Breakpoints are based on `min-width` media queries, meaning they affect that breakpoint and all those above it (e.g., `.col-sm-4` applies to `sm`, `md`, `lg`, `xl`, and `2xl`). This means you can control container and column sizing and behavior by each breakpoint.
- **Containers center and horizontally pad your content.** Use `.container` for a responsive pixel width, `.container-fluid` for `width: 100%` across all viewports and devices, or a responsive container (e.g., `.container-md`) for a combination of fluid and pixel widths.
@@ -58,7 +58,7 @@ Bootstraps grid system can adapt across all six default breakpoints, and any
- Medium (md)
- Large (lg)
- Extra large (xl)
- Extra extra large (xxl)
- Extra extra large (2xl)
As noted above, each of these breakpoints have their own container, unique class prefix, and modifiers. Heres how the grid changes across these breakpoints:
@@ -70,9 +70,9 @@ As noted above, each of these breakpoints have their own container, unique class
<th scope="col">xs<br/><span class="fw-normal">&lt;576px</span></th>
<th scope="col">sm<br/><span class="fw-normal">&ge;576px</span></th>
<th scope="col">md<br/><span class="fw-normal">&ge;768px</span></th>
<th scope="col">lg<br/><span class="fw-normal">&ge;992px</span></th>
<th scope="col">xl<br/><span class="fw-normal">&ge;1200px</span></th>
<th scope="col">xxl<br/><span class="fw-normal">&ge;1400px</span></th>
<th scope="col">lg<br/><span class="fw-normal">&ge;1024px</span></th>
<th scope="col">xl<br/><span class="fw-normal">&ge;1280px</span></th>
<th scope="col">2xl<br/><span class="fw-normal">&ge;1536px</span></th>
</tr>
</thead>
<tbody>
@@ -83,7 +83,7 @@ As noted above, each of these breakpoints have their own container, unique class
<td>720px</td>
<td>960px</td>
<td>1140px</td>
<td>1320px</td>
<td>1440px</td>
</tr>
<tr>
<th class="text-nowrap" scope="row">Class prefix</th>
@@ -92,7 +92,7 @@ As noted above, each of these breakpoints have their own container, unique class
<td><code>.col-md-</code></td>
<td><code>.col-lg-</code></td>
<td><code>.col-xl-</code></td>
<td><code>.col-xxl-</code></td>
<td><code>.col-2xl-</code></td>
</tr>
<tr>
<th class="text-nowrap" scope="row"># of columns</th>
@@ -124,7 +124,7 @@ Utilize breakpoint-specific column classes for easy column sizing without an exp
### Equal-width
For example, here are two grid layouts that apply to every device and viewport, from `xs` to `xxl`. Add any number of unit-less classes for each breakpoint you need and every column will be the same width.
For example, here are two grid layouts that apply to every device and viewport, from `xs` to `2xl`. Add any number of unit-less classes for each breakpoint you need and every column will be the same width.
<Example class="bd-example-row" code={`<div class="container text-center">
<div class="row">
+91 -709
View File
@@ -1,744 +1,126 @@
---
title: Migrating to v5
title: Migrating to v6
description: Track and review changes to the Bootstrap source files, documentation, and components to help you migrate from v4 to v5.
aliases: "/migration/"
toc: true
---
## v5.3.6
## v6.0.0 Migration
### Dependencies
Bootstrap 6 is a major release with many breaking changes to modernize our codebase, adopt newer build tools, and improve customization. Keep reading for a guide on how to migrate from v5 to v6, and a full changelog of what's new.
- Migrated from Hugo to Astro for building our documentation
1. Bump your Bootstrap dependency:
## v5.3.0
```json
{
"dependencies": {
"bootstrap": "^6.0.0"
}
}
```
If youre migrating from our previous alpha releases of v5.3.0, please review their changes in addition to this section.
2. If using all of Bootstrap's Sass files, include it in your Sass using `@use`:
### Helpers
```scss
@use "bootstrap/scss/bootstrap";
```
- [Colored links]([[docsref:/helpers/colored-links]]) once again have `!important` so they work better with our newly added link utilities.
With this, you can then easily override Bootstrap's Sass variables and maps:
### Utilities
```scss
@use "bootstrap/scss/bootstrap" with (
$spacer: 1rem,
$enable-reduced-motion: true,
);
```
- Added new `.d-inline-grid` [display utility]([[docsref:/utilities/display]]).
3. If using only certain parts of Bootstrap's Sass files, you can use `@use` to import them individually. Be aware that our Sass file structure has changed and you may need to adjust your imports accordingly.
## v5.3.0-alpha2
```scss
@use "bootstrap/scss/forms";
```
If youre migrating from our previous alpha release of v5.3.0, please review the changes listed below.
4. Update HTML and CSS per the changelog and updates in the documentation.
### CSS variables
5. Recompile your Sass to see the changes.
- Removed several duplicate and unused root CSS variables.
## v6.0.0 Changelog
### Color modes
### CSS
- Dark mode colors are now derived from our theme colors (e.g., `$primary`) in Sass, rather than color specific tints or shades (e.g., `$blue-300`). This allows for a more automated dark mode when customizing the default theme colors.
- Added Sass maps for generating theme colors for dark mode text, subtle background, and subtle border.
- [Snippet examples]([[docsref:/examples/#snippets]]) are now ready for dark mode with updated markup and reduced custom styles.
- Added `color-scheme: dark` to dark mode CSS to change OS level controls like scrollbars
- Form validation `border-color` and text `color` states now respond to dark mode, thanks to new Sass and CSS variables.
- Dropped recently added form control background CSS variables and reassigned the Sass variables to use CSS variables instead. This simplifies the styling across color modes and avoids an issue where form controls in dark mode wouldnt update properly.
- Our `box-shadow`s will once again always stay dark instead of inverting to white when in dark mode.
- Improved HTML and JavaScript for our color mode toggle script. The selector for changing the active SVG has been improved, and the markup made more accessible with ARIA attributes.
- Improved docs code syntax colors and more across light and dark modes.
### Typography
- We no longer set a color for `$headings-color-dark` or `--bs-heading-color` for dark mode. To avoid several problems of headings within components appearing the wrong color, weve set the Sass variable to `null` and added a `null` check like we use on the default light mode.
### Components
- Cards now have a `color` set on them to improve rendering across color modes.
- Added new `.nav-underline` variant for our navigation with a simpler bottom border under the active nav link. [See the docs for an example.]([[docsref:/components/navs-tabs#underline]])
- Navs now have new `:focus-visible` styles that better match our custom button focus styles.
### Helpers
- Added new `.icon-link` helper to quickly place and align Bootstrap Icons alongside a textual link. Icon links support our new link utilities, too.
- Added new focus ring helper for removing the default `outline` and setting a custom `box-shadow` focus ring.
### Utilities
- Renamed Sass and CSS variables `${color}-text` to `${color}-text-emphasis` to match their associated utilities.
- Added new `.link-body-emphasis` helper alongside our [colored links]([[docsref:/helpers/colored-links]]). This creates a colored link using our color mode responsive emphasis color.
- Added new link utilities for link color opacity, underline offset, underline color, and underline opacity. [Explore the new links utilities.]([[docsref:/utilities/link]])
- CSS variable based `border-width` utilities have been reverted to set their property directly (as was done prior to v5.2.0). This avoids inheritance issues across nested elements, including tables.
- Added new `.border-black` utility to match our `.text-black` and `.bg-black` utilities.
- <span class="badge text-warning-emphasis bg-warning-subtle">Deprecated</span> The `.text-muted` utility and `$text-muted` Sass variable have been deprecated and replaced with `.text-body-secondary` and `$body-secondary-color`.
### Docs
- Examples are now displayed with the appropriate light or dark color mode as dictated by the setting in our docs. Each example has an individual color mode picker.
- Improved included JavaScript for live Toast demo.
- Added `twbs/examples` repo contents to the top of the Examples page.
### Tooling
- Added SCSS testing via True to help test our utilities API and other customizations.
- Replaced instances of our bootstrap-npm-starter project with the newer and more complete [twbs/examples repo](https://github.com/twbs/examples).
<hr class="mb-4"/>
For a complete list of changes, [see the v5.3.0-alpha2 project on GitHub](https://github.com/orgs/twbs/projects/13).
## v5.3.0-alpha1
<hr class="mb-4"/>
### Color modes!
Learn more by reading the new [color modes documentation]([[docsref:/customize/color-modes]]).
- **Global support for light (default) and dark color modes.** Set color mode globally on the `:root` element, on groups of elements and components with a wrapper class, or directly on components, with `data-bs-theme="light|dark"`. Also included is a new `color-mode()` mixin that can output a ruleset with the `data-bs-theme` selector or a media query, depending on your preference.
<span class="badge text-warning-emphasis bg-warning-subtle">Deprecated</span> Color modes replace dark variants for components, so `.btn-close-white`, `.carousel-dark`, `.dropdown-menu-dark`, and `.navbar-dark` are deprecated.
- **New extended color system.** Weve added new theme colors (but not in `$theme-colors`) for a more nuanced, system-wide color palette with new secondary, tertiary, and emphasis colors for `color` and `background-color`. These new colors are available as Sass variables, CSS variables, and utilities.
- Weve also expanded our theme color Sass variables, CSS variables, and utilities to include text emphasis, subtle background colors, and subtle border colors. These are available as Sass variables, CSS variables, and utilities.
- Adds new `_variables-dark.scss` stylesheet to house dark-mode specific overrides. This stylesheet should be imported immediately after the existing `_variables.scss` file in your import stack.
```diff
diff --git a/scss/bootstrap.scss b/scss/bootstrap.scss
index 8f8296def..449d70487 100644
--- a/scss/bootstrap.scss
+++ b/scss/bootstrap.scss
@@ -6,6 +6,7 @@
// Configuration
@import "functions";
@import "variables";
+@import "variables-dark";
@import "maps";
@import "mixins";
@import "utilities";
```
### CSS variables
- Restores CSS variables for breakpoints, though we dont use them in our media queries as theyre not supported. However, these can be useful in JS-specific contexts.
- Per the color modes update, weve added new utilities for new Sass CSS variables `secondary` and `tertiary` text and background colors, plus `{color}-bg-subtle`, `{color}-border-subtle`, and `{color}-text-emphasis` for our theme colors. These new colors are available through Sass and CSS variables (but not our color maps) with the express goal of making it easier to customize across multiple colors modes like light and dark.
- Adds additional variables for alerts, `.btn-close`, and `.offcanvas`.
- The `--bs-heading-color` variable is back with an update and dark mode support. First, we now check for a `null` value on the associated Sass variable, `$headings-color`, before trying to output the CSS variable, so by default its not present in our compiled CSS. Second, we use the CSS variable with a fallback value, `inherit`, allowing the original behavior to persist, but also allowing for overrides.
- Converts links to use CSS variables for styling `color`, but not `text-decoration`. Colors are now set with `--bs-link-color-rgb` and `--bs-link-opacity` as `rgba()` color, allowing you to customize the translucency with ease. The `a:hover` pseudo-class now overrides `--bs-link-color-rgb` instead of explicitly setting the `color` property.
- `--bs-border-width` is now being used in more components for greater control over default global styling.
- Adds new root CSS variables for our `box-shadow`s, including `--bs-box-shadow`, `--bs-box-shadow-sm`, `--bs-box-shadow-lg`, and `--bs-box-shadow-inset`.
### Components
#### Alert
- Alert variants are now styled via CSS variables.
- <span class="badge text-warning-emphasis bg-warning-subtle">Deprecated</span> The `alert-variant()` mixin is now deprecated. We now [use a Sass loop]([[docsref:/components/alerts#sass-loops]]) directly to modify the components default CSS variables for each variant.
#### List group
- List group item variants are now styled via CSS variables.
- <span class="badge text-warning-emphasis bg-warning-subtle">Deprecated</span> The `list-group-item-variant()` mixin is now deprecated. We now [use a Sass loop]([[docsref:/components/list-group#sass-loops]]) directly to modify the components default CSS variables for each variant.
#### Dropdowns
- <span class="badge text-warning-emphasis bg-warning-subtle">Deprecated</span> The `.dropdown-menu-dark` class has been deprecated and replaced with `data-bs-theme="dark"` on the dropdown or any parent element. [See the docs for an example.]([[docsref:/components/dropdowns#dark-dropdowns]])
#### Close button
- <span class="badge text-warning-emphasis bg-warning-subtle">Deprecated</span> The `.btn-close-white` class has been deprecated and replaced with `data-bs-theme="dark"` on the close button or any parent element. [See the docs for an example.]([[docsref:/components/close-button#dark-variant]])
#### Navbar
- <span class="badge text-warning-emphasis bg-warning-subtle">Deprecated</span> The `.navbar-dark` class has been deprecated and replaced with `data-bs-theme="dark"` on the navbar or any parent element. [See the docs for updated examples.]([[docsref:/components/navbar#color-schemes]])
### Progress bars
The markup for [progress bars]([[docsref:/components/progress]]) has been updated in v5.3.0. Due to the placement of `role` and various `aria-` attributes on the inner `.progress-bar` element, **some screen readers were not announcing zero value progress bars**. Now, `role="progressbar"` and the relevant `aria-*` attributes are on the outer `.progress` element, leaving the `.progress-bar` purely for the visual presentation of the bar and optional label.
While we recommend adopting the new markup for improved compatibility with all screen readers, note that the legacy progress bar structure will continue to work as before.
```html
<!-- Previous markup -->
<div class="progress">
<div class="progress-bar" role="progressbar" aria-label="Basic example" style="width: 25%" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!-- New markup -->
<div class="progress" role="progressbar" aria-label="Basic example" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100">
<div class="progress-bar" style="width: 25%"></div>
</div>
```
Weve also introduced a new `.progress-stacked` class to more logically wrap [multiple progress bars]([[docsref:/components/progress#multiple-bars]]) into a single stacked progress bar.
```html
<!-- Previous markup -->
<div class="progress">
<div class="progress-bar" role="progressbar" aria-label="Segment one" style="width: 15%" aria-valuenow="15" aria-valuemin="0" aria-valuemax="100"></div>
<div class="progress-bar bg-success" role="progressbar" aria-label="Segment two" style="width: 30%" aria-valuenow="30" aria-valuemin="0" aria-valuemax="100"></div>
<div class="progress-bar bg-info" role="progressbar" aria-label="Segment three" style="width: 20%" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!-- New markup -->
<div class="progress-stacked">
<div class="progress" role="progressbar" aria-label="Segment one" aria-valuenow="15" aria-valuemin="0" aria-valuemax="100" style="width: 15%">
<div class="progress-bar"></div>
</div>
<div class="progress" role="progressbar" aria-label="Segment two" aria-valuenow="30" aria-valuemin="0" aria-valuemax="100" style="width: 30%">
<div class="progress-bar bg-success"></div>
</div>
<div class="progress" role="progressbar" aria-label="Segment three" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100" style="width: 20%">
<div class="progress-bar bg-info"></div>
</div>
</div>
```
### Forms
- `.form-control` is now styled with CSS variables to support color modes. This includes the addition of two new root CSS variables for the default and disabled form control backgrounds.
- `.form-check` and `.form-switch` components are now built with CSS variables for setting the `background-image`. The usage here differs from other components in that the various focus, active, etc states for each component arent set on the base class. Instead, the states override one variable (e.g., `--bs-form-switch-bg`).
- Floating form labels now have a `background-color` to fix support for `<textarea>` elements. Additional changes have been made to also support disabled states and more.
- Fixed display of date and time inputs in WebKit based browsers.
### Utilities
- <span class="badge text-warning-emphasis bg-warning-subtle">Deprecated</span> `.text-muted` will be replaced by `.text-body-secondary` in v6.
With the addition of the expanded theme colors and variables, the `.text-muted` variables and utility have been deprecated with v5.3.0. Its default value has also been reassigned to the new `--bs-secondary-color` CSS variable to better support color modes. It will be removed in v6.0.0.
- Adds new `.overflow-x`, `.overflow-y`, and several `.object-fit-*` utilities. _The object-fit property is used to specify how an `<img>` or `<video>` should be resized to fit its container, giving us a responsive alternative to using `background-image` for a resizable fill/fit image._
- Adds new `.fw-medium` utility.
- Added new [`.z-*` utilities]([[docsref:/utilities/z-index]]) for `z-index`.
- [Box shadow utilities]([[docsref:/utilities/shadows]]) (and Sass variables) have been updated for dark mode. They now use `--bs-body-color-rgb` to generate the `rgba()` color values, allowing them to easily adapt to color modes based on the specified foreground color.
For a complete list of changes, [see the v5.3.0 project on GitHub](https://github.com/twbs/bootstrap/projects/).
## v5.2.0
<hr class="mb-4"/>
### Refreshed design
Bootstrap v5.2.0 features a subtle design update for a handful of components and properties across the project, **most notably through refined `border-radius` values on buttons and form controls**. Our documentation also has been updated with a new homepage, simpler docs layout that no longer collapses sections of the sidebar, and more prominent examples of [Bootstrap Icons](https://icons.getbootstrap.com).
### More CSS variables
**Weve updated all our components to use CSS variables.** While Sass still underpins everything, each component has been updated to include CSS variables on the component base classes (e.g., `.btn`), allowing for more real-time customization of Bootstrap. In subsequent releases, we'll continue to expand our use of CSS variables into our layout, forms, helpers, and utilities. Read more about CSS variables in each component on their respective documentation pages.
Our CSS variable usage will be somewhat incomplete until Bootstrap 6. While wed love to fully implement these across the board, they do run the risk of causing breaking changes. For example, setting `$alert-border-width: var(--bs-border-width)` in our source code breaks potential Sass in your own code if you were doing `$alert-border-width * 2` for some reason.
As such, wherever possible, we will continue to push towards more CSS variables, but please recognize our implementation may be slightly limited in v5.
### New `_maps.scss`
**Bootstrap v5.2.0 introduced a new Sass file with `_maps.scss`.** It pulls out several Sass maps from `_variables.scss` to fix an issue where updates to an original map were not applied to secondary maps that extend them. For example, updates to `$theme-colors` were not being applied to other theme maps that relied on `$theme-colors`, breaking key customization workflows. In short, Sass has a limitation where once a default variable or map has been _used_, it cannot be updated. _Theres a similar shortcoming with CSS variables when theyre used to compose other CSS variables._
This is why variable customizations in Bootstrap have to come after `@import "functions"`, but before `@import "variables"` and the rest of our import stack. The same applies to Sass maps—you must override the defaults before they get used. The following maps have been moved to the new `_maps.scss`:
- `$theme-colors-rgb`
- `$utilities-colors`
- `$utilities-text`
- `$utilities-text-colors`
- `$utilities-bg`
- `$utilities-bg-colors`
- `$negative-spacers`
- `$gutters`
Your custom Bootstrap CSS builds should now look something like this with a separate maps import.
```diff
// Functions come first
@import "functions";
// Optional variable overrides here
+ $custom-color: #df711b;
+ $custom-theme-colors: (
+ "custom": $custom-color
+ );
// Variables come next
@import "variables";
+ // Optional Sass map overrides here
+ $theme-colors: map-merge($theme-colors, $custom-theme-colors);
+
+ // Followed by our default maps
+ @import "maps";
+
// Rest of our imports
@import "mixins";
@import "utilities";
@import "root";
@import "reboot";
// etc
```
### New utilities
- Expanded [`font-weight` utilities]([[docsref:/utilities/text#font-weight-and-italics]]) to include `.fw-semibold` for semibold fonts.
- Expanded [`border-radius` utilities]([[docsref:/utilities/border-radius#sizes]]) to include two new sizes, `.rounded-4` and `.rounded-5`, for more options.
### Additional changes
- **Introduced new `$enable-container-classes` option. —** Now when opting into the experimental CSS Grid layout, `.container-*` classes will still be compiled, unless this option is set to `false`. Containers also now keep their gutter values.
- **Offcanvas component now has [responsive variations]([[docsref:/components/offcanvas#responsive]]).** The original `.offcanvas` class remains unchanged—it hides content across all viewports. To make it responsive, change that `.offcanvas` class to any `.offcanvas-{sm|md|lg|xl|xxl}` class.
- **Thicker table dividers are now opt-in. —** Weve removed the thicker and more difficult to override border between table groups and moved it to an optional class you can apply, `.table-group-divider`. [See the table docs for an example.]([[docsref:/content/tables#table-group-dividers]])
- **[Scrollspy has been rewritten](https://github.com/twbs/bootstrap/pull/33421) to use the Intersection Observer API**, which means you no longer need relative parent wrappers, deprecates `offset` config, and more. Look for your Scrollspy implementations to be more accurate and consistent in their nav highlighting.
- **Popovers and tooltips now use CSS variables.** Some CSS variables have been updated from their Sass counterparts to reduce the number of variables. As a result, three variables have been deprecated in this release: `$popover-arrow-color`, `$popover-arrow-outer-color`, and `$tooltip-arrow-color`.
- **Added new `.text-bg-{color}` helpers.** Instead of setting individual `.text-*` and `.bg-*` utilities, you can now use [the `.text-bg-*` helpers]([[docsref:helpers/color-background]]) to set a `background-color` with contrasting foreground `color`.
- Added `.form-check-reverse` modifier to flip the order of labels and associated checkboxes/radios.
- Added [striped columns]([[docsref:/content/tables#striped-columns]]) support to tables via the new `.table-striped-columns` class.
For a complete list of changes, [see the v5.2.0 project on GitHub](https://github.com/twbs/bootstrap/projects/32).
## v5.1.0
<hr class="mb-4"/>
- **Added experimental support for [CSS Grid layout]([[docsref:/layout/css-grid]]). —** This is a work in progress, and is not yet ready for production use, but you can opt into the new feature via Sass. To enable it, disable the default grid, by setting `$enable-grid-classes: false` and enable the CSS Grid by setting `$enable-cssgrid: true`.
- **Updated navbars to support offcanvas. —** Add [offcanvas drawers in any navbar]([[docsref:/components/navbar#offcanvas]]) with the responsive `.navbar-expand-*` classes and some offcanvas markup.
- **Added new [placeholder component]([[docsref:/components/placeholders/]]). —** Our newest component, a way to provide temporary blocks in lieu of real content to help indicate that something is still loading in your site or app.
- **Collapse plugin now supports [horizontal collapsing]([[docsref:/components/collapse#horizontal]]). —** Add `.collapse-horizontal` to your `.collapse` to collapse the `width` instead of the `height`. Avoid browser repainting by setting a `min-height` or `height`.
- **Added new stack and vertical rule helpers. —** Quickly apply multiple flexbox properties to quickly create custom layouts with [stacks]([[docsref:/helpers/stacks/]]). Choose from horizontal (`.hstack`) and vertical (`.vstack`) stacks. Add vertical dividers similar to `<hr>` elements with the [new `.vr` helpers]([[docsref:/helpers/vertical-rule/]]).
- **Added new global `:root` CSS variables. —** Added several new CSS variables to the `:root` level for controlling `<body>` styles. More are in the works, including across our utilities and components, but for now read up [CSS variables in the Customize section]([[docsref:/customize/css-variables/]]).
- **Overhauled color and background utilities to use CSS variables, and added new [text opacity]([[docsref:/utilities/text#opacity]]) and [background opacity]([[docsref:/utilities/background#opacity]]) utilities. —** `.text-*` and `.bg-*` utilities are now built with CSS variables and `rgba()` color values, allowing you to easily customize any utility with new opacity utilities.
- **Added new snippet examples based to show how to customize our components. —** Pull ready to use customized components and other common design patterns with our new [Snippets examples]([[docsref:/examples/#snippets]]). Includes [footers]([[docsref:/examples/footers/]]), [dropdowns]([[docsref:/examples/dropdowns/]]), [list groups]([[docsref:/examples/list-groups/]]), and [modals]([[docsref:/examples/modals/]]).
- **Removed unused positioning styles from popovers and tooltips** as these are handled solely by Popper. `$tooltip-margin` has been deprecated and set to `null` in the process.
Want more information? [Read the v5.1.0 blog post.](https://blog.getbootstrap.com/2021/08/04/bootstrap-5-1-0/)
## v5.0.0
<hr class="mb-4"/>
<Callout>
**Hey there!** Changes to our first major release of Bootstrap 5, v5.0.0, are documented below. They dont reflect the additional changes shown above.
</Callout>
### Dependencies
- Dropped jQuery.
- Upgraded from Popper v1.x to Popper v2.x.
- Replaced Libsass with Dart Sass as our Sass compiler given Libsass was deprecated.
- Migrated from Jekyll to Hugo for building our documentation
### Browser support
- Dropped Internet Explorer 10 and 11
- Dropped Microsoft Edge < 16 (Legacy Edge)
- Dropped Firefox < 60
- Dropped Safari < 12
- Dropped iOS Safari < 12
- Dropped Chrome < 60
<hr class="my-5"/>
### Documentation changes
- Redesigned homepage, docs layout, and footer.
- Added [new Parcel guide]([[docsref:/getting-started/parcel]]).
- Added [new Customize section]([[docsref:/customize/overview/]]), replacing [v4s Theming page](https://getbootstrap.com/docs/4.6/getting-started/theming/), with new details on Sass, global configuration options, color schemes, CSS variables, and more.
- Reorganized all form documentation into [new Forms section]([[docsref:/forms/overview/]]), breaking apart the content into more focused pages.
- Similarly, updated [the Layout section]([[docsref:/layout/breakpoints]]), to flesh out grid content more clearly.
- Renamed “Navs” component page to "Navs & Tabs".
- Renamed “Checks” page to "Checks & radios".
- Redesigned the navbar and added a new subnav to make it easier to get around our sites and docs versions.
- Added new keyboard shortcut for the search field: <kbd><kbd>Ctrl</kbd> + <kbd>/</kbd></kbd>.
- **Implemented CSS layers** in `_root.scss` and applied them to all our Sass files.
- Layers are set in `_root.scss` and then utilized across separate Sass partials.
- We cannot, unfortunately, wrap `@use` or `@forward` statements in `@layer`—Sass expects those to be top level at all times. Also, while CSS allows `@import "file.css" layer(name)`, Sass also does not support that.
- Clarified and simplified CSS-Sass setup.
- New, streamlined color modes and theming.
- Removed `_maps.scss`
- Removed `_variables-dark.scss`
- Added `_colors.scss`, splitting them out from `_variables.scss`,
- Added `_theme.scss` where we setup all our global theming for how colors are applied
- **Updated lg, xl, and 2xl breakpoints and containers.**
- Increased the `lg` breakpoint from 992px to 1024px; it's container remains the same at 960px.
- Increased the `xl` breakpoint from 1200px to 1280px, and it's container from 1140px to 1200px.
- Renamed `xxl` to `2xl` for better scaling with additional custom breakpoints
- Increased the `2xl` breakpoint from 1400px to 1536px, and it's container from 1320px to 1440px.
### Sass
- Weve ditched the default Sass map merges to make it easier to remove redundant values. Keep in mind you now have to define all values in the Sass maps like `$theme-colors`. Check out how to deal with [Sass maps]([[docsref:/customize/sass#maps-and-loops]]).
- Dropped support for Node Sass, including no longer testing any of our source CSS against it.
- Rearranged several Sass files in the process.
- Removed `add()` and `subtract()` functions. Use `calc()` instead.
- **Removes all deprecated Sass variables and values:**
- Removed `$variable-prefix`, use `$prefix` instead.
- Removed `$nested-kbd-font-weight`, no replacement.
- Removed `muted`, `black-50`, and `white-50` from text colors utilities map
- Consolidated carousel dark variables, removing `$carousel-dark-indicator-active-bg`, `$carousel-dark-caption-color`, and `$carousel-dark-control-icon-filter` for their reassigned counterparts.
- Removed `$btn-close-white-filter` for `$btn-close-filter-dark`.
- Removed `$border-radius-2xl`, use `$border-radius-xxl`.
- Removed `$text-muted` for secondary color.
- Removed `$hr-bg-color` for `$hr-border-color` and `$hr-height` for `$hr-border-width`.
- Removed unused `$dropdown-header-padding` for the `-x`/`-y` split variables.
- Removed unused `$accordion-button-focus-border-color`.
- Removed unused `$tooltip-arrow-color`.
- Removed unused `$popover-arrow-color` and `$popover-arrow-outer-color`
- Removed unused `$alert-bg-scale`, `$alert-border-scale`, and `$alert-color-scale` (replaced by theme tokens)
- Removed unused `$list-group-item-bg-scale` and `$list-group-item-color-scale` (replaced by theme tokens)
- <span class="badge text-bg-danger">Breaking</span> Renamed `color-yiq()` function and related variables to `color-contrast()` as its no longer related to YIQ color space. [See #30168.](https://github.com/twbs/bootstrap/pull/30168/)
- `$yiq-contrasted-threshold` is renamed to `$min-contrast-ratio`.
- `$yiq-text-dark` and `$yiq-text-light` are respectively renamed to `$color-contrast-dark` and `$color-contrast-light`.
### Reboot
- <span class="badge text-bg-danger">Breaking</span> Media query mixins parameters have changed for a more logical approach.
- `media-breakpoint-down()` uses the breakpoint itself instead of the next breakpoint (e.g., `media-breakpoint-down(lg)` instead of `media-breakpoint-down(md)` targets viewports smaller than `lg`).
- Similarly, the second parameter in `media-breakpoint-between()` also uses the breakpoint itself instead of the next breakpoint (e.g., `media-breakpoint-between(sm, lg)` instead of `media-breakpoint-between(sm, md)` targets viewports between `sm` and `lg`).
- <span class="badge text-bg-danger">Breaking</span> Removed print styles and `$enable-print-styles` variable. Print display classes are still around. [See #28339](https://github.com/twbs/bootstrap/pull/28339).
- <span class="badge text-bg-danger">Breaking</span> Dropped `color()`, `theme-color()`, and `gray()` functions in favor of variables. [See #29083](https://github.com/twbs/bootstrap/pull/29083).
- <span class="badge text-bg-danger">Breaking</span> Renamed `theme-color-level()` function to `color-level()` and now accepts any color you want instead of only `$theme-color` colors. [See #29083](https://github.com/twbs/bootstrap/pull/29083) **Watch out:** `color-level()` was later on dropped in `v5.0.0-alpha3`.
- <span class="badge text-bg-danger">Breaking</span> Renamed `$enable-prefers-reduced-motion-media-query` and `$enable-pointer-cursor-for-buttons` to `$enable-reduced-motion` and `$enable-button-pointers` for brevity.
- <span class="badge text-bg-danger">Breaking</span> Removed the `bg-gradient-variant()` mixin. Use the `.bg-gradient` class to add gradients to elements instead of the generated `.bg-gradient-*` classes.
- <span class="badge text-bg-danger">Breaking</span> **Removed previously deprecated mixins:**
- `hover`, `hover-focus`, `plain-hover-focus`, and `hover-focus-active`
- `float()`
- `form-control-mixin()`
- `nav-divider()`
- `retina-img()`
- `text-hide()` (also dropped the associated utility class, `.text-hide`)
- `visibility()`
- `form-control-focus()`
- <span class="badge text-bg-danger">Breaking</span> Renamed `scale-color()` function to `shift-color()` to avoid collision with Sasss own color scaling function.
- `box-shadow` mixins now allow `null` values and drop `none` from multiple arguments. [See #30394](https://github.com/twbs/bootstrap/pull/30394).
- The `border-radius()` mixin now has a default value.
### Color system
- The color system which worked with `color-level()` and `$theme-color-interval` was removed in favor of a new color system. All `lighten()` and `darken()` functions in our codebase are replaced by `tint-color()` and `shade-color()`. These functions will mix the color with either white or black instead of changing its lightness by a fixed amount. The `shift-color()` will either tint or shade a color depending on whether its weight parameter is positive or negative. [See #30622](https://github.com/twbs/bootstrap/pull/30622) for more details.
- Added new tints and shades for every color, providing nine separate colors for each base color, as new Sass variables.
- Improved color contrast. Bumped color contrast ratio from 3:1 to 4.5:1 and updated blue, green, cyan, and pink colors to ensure WCAG 2.2 AA contrast. Also changed our color contrast color from `$gray-900` to `$black`.
- To support our color system, weve added new custom `tint-color()` and `shade-color()` functions to mix our colors appropriately.
### Grid updates
- **New breakpoint!** Added new `xxl` breakpoint for `1400px` and up. No changes to all other breakpoints.
- **Improved gutters.** Gutters are now set in rems, and are narrower than v4 (`1.5rem`, or about `24px`, down from `30px`). This aligns our grid systems gutters with our spacing utilities.
- Added new [gutter class]([[docsref:/layout/gutters]]) (`.g-*`, `.gx-*`, and `.gy-*`) to control horizontal/vertical gutters, horizontal gutters, and vertical gutters.
- <span class="badge text-bg-danger">Breaking</span> Renamed `.no-gutters` to `.g-0` to match new gutter utilities.
- Columns no longer have `position: relative` applied, so you may have to add `.position-relative` to some elements to restore that behavior.
- <span class="badge text-bg-danger">Breaking</span> Dropped several `.order-*` classes that often went unused. We now only provide `.order-0` to `.order-5` out of the box.
- <span class="badge text-bg-danger">Breaking</span> Dropped the `.media` component as it can be easily replicated with utilities. [See #28265](https://github.com/twbs/bootstrap/pull/28265) and the [flex utilities page for an example]([[docsref:/utilities/flex#media-object]]).
- <span class="badge text-bg-danger">Breaking</span> `bootstrap-grid.css` now only applies `box-sizing: border-box` to the column instead of resetting the global box-sizing. This way, our grid styles can be used in more places without interference.
- `$enable-grid-classes` no longer disables the generation of container classes anymore. [See #29146.](https://github.com/twbs/bootstrap/pull/29146)
- Updated the `make-col` mixin to default to equal columns without a specified size.
### Content, Reboot, etc
- **[RFS]([[docsref:/getting-started/rfs]]) is now enabled by default.** Headings using the `font-size()` mixin will automatically adjust their `font-size` to scale with the viewport. _This feature was previously opt-in with v4._
- <span class="badge text-bg-danger">Breaking</span> Overhauled our display typography to replace our `$display-*` variables and with a `$display-font-sizes` Sass map. Also removed the individual `$display-*-weight` variables for a single `$display-font-weight` and adjusted `font-size`s.
- Added two new `.display-*` heading sizes, `.display-5` and `.display-6`.
- **Links are underlined by default** (not just on hover), unless theyre part of specific components.
- **Redesigned tables** to refresh their styles and rebuild them with CSS variables for more control over styling.
- <span class="badge text-bg-danger">Breaking</span> Nested tables do not inherit styles anymore.
- <span class="badge text-bg-danger">Breaking</span> `.thead-light` and `.thead-dark` are dropped in favor of the `.table-*` variant classes which can be used for all table elements (`thead`, `tbody`, `tfoot`, `tr`, `th` and `td`).
- <span class="badge text-bg-danger">Breaking</span> The `table-row-variant()` mixin is renamed to `table-variant()` and accepts only 2 parameters: `$color` (color name) and `$value` (color code). The border color and accent colors are automatically calculated based on the table factor variables.
- Split table cell padding variables into `-y` and `-x`.
- <span class="badge text-bg-danger">Breaking</span> Dropped `.pre-scrollable` class. [See #29135](https://github.com/twbs/bootstrap/pull/29135)
- <span class="badge text-bg-danger">Breaking</span> `.text-*` utilities do not add hover and focus states to links anymore. `.link-*` helper classes can be used instead. [See #29267](https://github.com/twbs/bootstrap/pull/29267)
- <span class="badge text-bg-danger">Breaking</span> Dropped `.text-justify` class. [See #29793](https://github.com/twbs/bootstrap/pull/29793)
- <span class="badge text-bg-danger">Breaking</span> ~~`<hr>` elements now use `height` instead of `border` to better support the `size` attribute. This also enables use of padding utilities to create thicker dividers (e.g., `<hr class="py-1">`).~~
- Reset default horizontal `padding-left` on `<ul>` and `<ol>` elements from browser default `40px` to `2rem`.
- Added `$enable-smooth-scroll`, which applies `scroll-behavior: smooth` globally—except for users asking for reduced motion through `prefers-reduced-motion` media query. [See #31877](https://github.com/twbs/bootstrap/pull/31877)
### RTL
- 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`.
- Relocated heading classes (like `.h1`) and some type classes (`.mark` and `.small`) to Reboot from `_type.scss`. This avoids a dependency in Sass modules and we like to avoid extending selectors in general.
### Forms
- **Added new floating forms!** Weve promoted the Floating labels example to fully supported form components. [See the new Floating labels page.]([[docsref:/forms/floating-labels]])
- <span class="badge text-bg-danger">Breaking</span> **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.
- `.custom-control.custom-checkbox` is now `.form-check`.
- `.custom-control.custom-radio` is now `.form-check`.
- `.custom-control.custom-switch` is now `.form-check.form-switch`.
- `.custom-select` is now `.form-select`.
- `.custom-file` and `.form-control-file` have been replaced by custom styles on top of `.form-control`.
- `.custom-range` is now `.form-range`.
- Dropped native `.form-control-file` and `.form-control-range`.
- <span class="badge text-bg-danger">Breaking</span> 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.
- The longstanding [Missing border radius on input group with validation feedback bug](https://github.com/twbs/bootstrap/issues/25110) is finally fixed by adding an additional `.has-validation` class to input groups with validation.
- <span class="badge text-bg-danger">Breaking</span> **Dropped form-specific layout classes for our grid system.** Use our grid and utilities instead of `.form-group`, `.form-row`, or `.form-inline`.
- <span class="badge text-bg-danger">Breaking</span> Form labels now require `.form-label`.
- <span class="badge text-bg-danger">Breaking</span> `.form-text` no longer sets `display`, allowing you to create inline or block help text as you wish just by changing the HTML element.
- Form controls no longer used fixed `height` when possible, instead deferring to `min-height` to improve customization and compatibility with other components.
- Validation icons are no longer applied to `<select>`s with `multiple`.
- Rearranged source Sass files under `scss/forms/`, including input group styles.
<hr class="my-5"/>
### Components
- Unified `padding` values for alerts, breadcrumbs, cards, dropdowns, list groups, modals, popovers, and tooltips to be based on our `$spacer` variable. [See #30564](https://github.com/twbs/bootstrap/pull/30564).
#### Accordion
- Added [new accordion component]([[docsref:/components/accordion]]).
#### Alerts
- Alerts now have [examples with icons]([[docsref:/components/alerts#icons]]).
- Removed custom styles for `<hr>`s in each alert since they already use `currentColor`.
#### Badges
- <span class="badge text-bg-danger">Breaking</span> Dropped all `.badge-*` color classes for background utilities (e.g., use `.bg-primary` instead of `.badge-primary`).
- <span class="badge text-bg-danger">Breaking</span> Dropped `.badge-pill`—use the `.rounded-pill` utility instead.
- <span class="badge text-bg-danger">Breaking</span> Removed hover and focus styles for `<a>` and `<button>` elements.
- Increased default padding for badges from `.25em`/`.5em` to `.35em`/`.65em`.
#### Breadcrumbs
- Simplified the default appearance of breadcrumbs by removing `padding`, `background-color`, and `border-radius`.
- Added new CSS custom property `--bs-breadcrumb-divider` for easy customization without needing to recompile CSS.
#### Buttons
- <span class="badge text-bg-danger">Breaking</span> **[Toggle buttons]([[docsref:/forms/checks-radios#toggle-buttons]]), with checkboxes or radios, no longer require JavaScript and have new markup.** We no longer require a wrapping element, add `.btn-check` to the `<input>`, and pair it with any `.btn` classes on the `<label>`. [See #30650](https://github.com/twbs/bootstrap/pull/30650). _The docs for this has moved from our Buttons page to the new Forms section._
- <span class="badge text-bg-danger">Breaking</span> **Dropped `.btn-block` for utilities.** Instead of using `.btn-block` on the `.btn`, wrap your buttons with `.d-grid` and a `.gap-*` utility to space them as needed. Switch to responsive classes for even more control over them. [Read the docs for some examples.]([[docsref:/components/buttons#block-buttons]])
- Updated our `button-variant()` and `button-outline-variant()` mixins to support additional parameters.
- Updated buttons to ensure increased contrast on hover and active states.
- Disabled buttons now have `pointer-events: none;`.
#### Card
- <span class="badge text-bg-danger">Breaking</span> Dropped `.card-deck` in favor of our grid. Wrap your cards in column classes and add a parent `.row-cols-*` container to recreate card decks (but with more control over responsive alignment).
- <span class="badge text-bg-danger">Breaking</span> Dropped `.card-columns` in favor of Masonry. [See #28922](https://github.com/twbs/bootstrap/pull/28922).
- <span class="badge text-bg-danger">Breaking</span> Replaced the `.card` based accordion with a [new Accordion component]([[docsref:/components/accordion]]).
#### Carousel
- Added new [`.carousel-dark` variant]([[docsref:/components/carousel#dark-variant]]) for dark text, controls, and indicators (great for lighter backgrounds).
- Replaced chevron icons for carousel controls with new SVGs from [Bootstrap Icons]([[config:icons]]).
#### Close button
- <span class="badge text-bg-danger">Breaking</span> Renamed `.close` to `.btn-close` for a less generic name.
- Close buttons now use a `background-image` (embedded SVG) instead of a `&times;` in the HTML, allowing for easier customization without the need to touch your markup.
- Added new `.btn-close-white` variant that uses `filter: invert(1)` to enable higher contrast dismiss icons against darker backgrounds.
#### Collapse
- Removed scroll anchoring for accordions.
#### Dropdowns
- Added new `.dropdown-menu-dark` variant and associated variables for on-demand dark dropdowns.
- Added new variable for `$dropdown-padding-x`.
- Darkened the dropdown divider for improved contrast.
- <span class="badge text-bg-danger">Breaking</span> All the events for the dropdown are now triggered on the dropdown toggle button and then bubbled up to the parent element.
- Dropdown menus now have a `data-bs-popper="static"` attribute set when the positioning of the dropdown is static, or dropdown is in the navbar. This is added by our JavaScript and helps us use custom position styles without interfering with Poppers positioning.
- <span class="badge text-bg-danger">Breaking</span> Dropped `flip` option for dropdown plugin in favor of native Popper configuration. You can now disable the flipping behavior by passing an empty array for [`fallbackPlacements`](https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements) option in [flip](https://popper.js.org/docs/v2/modifiers/flip/) modifier.
- Dropdown menus can now be clickable with a new `autoClose` option to handle the [auto close behavior]([[docsref:/components/dropdowns#auto-close-behavior]]). You can use this option to accept the click inside or outside the dropdown menu to make it interactive.
- Dropdowns now support `.dropdown-item`s wrapped in `<li>`s.
#### Jumbotron
- <span class="badge text-bg-danger">Breaking</span> Dropped the jumbotron component as it can be replicated with utilities. [See our new Jumbotron example for a demo.]([[docsref:/examples/jumbotron]])
#### List group
- Added new [`.list-group-numbered` modifier]([[docsref:/components/list-group#numbered]]) to list groups.
#### Navs and tabs
- Added new `null` variables for `font-size`, `font-weight`, `color`, and `:hover` `color` to the `.nav-link` class.
#### Navbars
- <span class="badge text-bg-danger">Breaking</span> Navbars now require a container within (to drastically simplify spacing requirements and CSS required).
- <span class="badge text-bg-danger">Breaking</span> The `.active` class can no longer be applied to `.nav-item`s, it must be applied directly on `.nav-link`s.
#### Offcanvas
- Added the new [offcanvas component]([[docsref:/components/offcanvas]]).
#### Pagination
- Pagination links now have customizable `margin-left` that are dynamically rounded on all corners when separated from one another.
- Added `transition`s to pagination links.
#### Popovers
- <span class="badge text-bg-danger">Breaking</span> Renamed `.arrow` to `.popover-arrow` in our default popover template.
- Renamed `whiteList` option to `allowList`.
#### Spinners
- Spinners now honor `prefers-reduced-motion: reduce` by slowing down animations. [See #31882](https://github.com/twbs/bootstrap/pull/31882).
- Improved spinner vertical alignment.
#### Toasts
- Toasts can now be [positioned]([[docsref:/components/toasts#placement]]) in a `.toast-container` with the help of [positioning utilities]([[docsref:/utilities/position]]).
- Changed default toast duration to 5 seconds.
- Removed `overflow: hidden` from toasts and replaced with proper `border-radius`s with `calc()` functions.
#### Tooltips
- <span class="badge text-bg-danger">Breaking</span> Renamed `.arrow` to `.tooltip-arrow` in our default tooltip template.
- <span class="badge text-bg-danger">Breaking</span> The default value for the `fallbackPlacements` is changed to `['top', 'right', 'bottom', 'left']` for better placement of popper elements.
- <span class="badge text-bg-danger">Breaking</span> Renamed `whiteList` option to `allowList`.
### Utilities
- <span class="badge text-bg-danger">Breaking</span> Renamed several utilities to use logical property names instead of directional names with the addition of RTL support:
- Renamed `.float-left` and `.float-right` to `.float-start` and `.float-end`.
- Renamed `.border-left` and `.border-right` to `.border-start` and `.border-end`.
- Renamed `.rounded-left` and `.rounded-right` to `.rounded-start` and `.rounded-end`.
- Renamed `.ml-*` and `.mr-*` to `.ms-*` and `.me-*`.
- Renamed `.pl-*` and `.pr-*` to `.ps-*` and `.pe-*`.
- Renamed `.text-*-left` and `.text-*-right` to `.text-*-start` and `.text-*-end`.
- <span class="badge text-bg-danger">Breaking</span> Disabled negative margins by default.
- Added new `.bg-body` class for quickly setting the `<body>`s background to additional elements.
- Added new [position utilities]([[docsref:/utilities/position#arrange-elements]]) for `top`, `right`, `bottom`, and `left`. Values include `0`, `50%`, and `100%` for each property.
- Added new `.translate-middle-x` & `.translate-middle-y` utilities to horizontally or vertically center absolute/fixed positioned elements.
- Added new [`border-width` utilities]([[docsref:/utilities/border#border-width]]).
- <span class="badge text-bg-danger">Breaking</span> Renamed `.text-monospace` to `.font-monospace`.
- <span class="badge text-bg-danger">Breaking</span> Removed `.text-hide` as its an antiquated method for hiding text that shouldnt be used anymore.
- Added `.fs-*` utilities for `font-size` utilities (with RFS enabled). These use the same scale as HTMLs default headings (1-6, large to small), and can be modified via Sass map.
- <span class="badge text-bg-danger">Breaking</span> Renamed `.font-weight-*` utilities as `.fw-*` for brevity and consistency.
- <span class="badge text-bg-danger">Breaking</span> Renamed `.font-italic` utility to `.fst-italic` for brevity and consistency with new `.fst-normal` utility.
- Added `.d-grid` to display utilities and new `gap` utilities (`.gap`) for CSS Grid and flexbox layouts.
- <span class="badge text-bg-danger">Breaking</span> Removed `.rounded-sm` and `rounded-lg`, and introduced a new scale of classes, `.rounded-0` to `.rounded-3`. [See #31687](https://github.com/twbs/bootstrap/pull/31687).
- Added new `line-height` utilities: `.lh-1`, `.lh-sm`, `.lh-base` and `.lh-lg`. See [text utilities]([[docsref:/utilities/text#line-height]]).
- Moved the `.d-none` utility in our CSS to give it more weight over other display utilities.
- Extended the `.visually-hidden-focusable` helper to also work on containers, using `:focus-within`.
- **Refactor checks, radios, and switches.**
- Split apart `_form-check.scss` into separate stylesheets: `_checkbox.scss`, `_radio.scss`, and `_switch.scss`.
- Also split apart the documentation pages for checks, radios, and switches.
- Added new CSS variables on each of these components. _Side note: we could've shared variables here, but chose not to for simplicity's sake._
- Removed several now unused Sass variables.
- Checkboxes now have a wrapping element and an SVG in the DOM for checked and indeterminate states. Radios and switches do not.
- Revamped layout for checks, radios, and switches with labels (and descriptions). We now have custom elements for layout that include basic flexbox styling.
- @mdo-do: Decide on fate of `.form-check-reverse` and `.btn-check`
- **Consolidate `.form-select` into `.form-control`.**
- Removed `.form-select`—use `.form-control` on `<select>` elements now. Too much abstraction and duplication at the same time.
- Adds new CSS variables on `.form-control` for easier customization without Sass compilation.
- `.form-control` now has a `min-height` at all times as opposed to just on `<textarea>` elements. This reduces some CSS for us.
### Helpers
- <span class="badge text-bg-danger">Breaking</span> **Responsive embed helpers have been renamed to [ratio helpers]([[docsref:/utilities/aspect-ratio]])** with new class names and improved behaviors, as well as a helpful CSS variable.
- Classes have been renamed to change `by` to `x` in the aspect ratio. For example, `.ratio-16by9` is now `.ratio-16x9`.
- Weve dropped the `.embed-responsive-item` and element group selector in favor of a simpler `.ratio > *` selector. No more class is needed, and the ratio helper now works with any HTML element.
- The `$embed-responsive-aspect-ratios` Sass map has been renamed to `$aspect-ratios` and its values have been simplified to include the class name and the percentage as the `key: value` pair.
- CSS variables are now generated and included for each value in the Sass map. Modify the `--bs-aspect-ratio` variable on the `.ratio` to create any [custom aspect ratio]([[docsref:/utilities/aspect-ratio#custom-ratios]]).
- Ratio helpers have been moved to utilities.
- Dropped clearfix helper for `.d-flow-root` utility.
- <span class="badge text-bg-danger">Breaking</span> **"Screen reader" classes are now ["visually hidden" classes]([[docsref:/helpers/visually-hidden]]).**
- Changed the Sass file from `scss/helpers/_screenreaders.scss` to `scss/helpers/_visually-hidden.scss`
- Renamed `.sr-only` and `.sr-only-focusable` to `.visually-hidden` and `.visually-hidden-focusable`
- Renamed `sr-only()` and `sr-only-focusable()` mixins to `visually-hidden()` and `visually-hidden-focusable()`.
### Utilities
- `bootstrap-utilities.css` now also includes our helpers. Helpers dont need to be imported in custom builds anymore.
- Ratio helpers are now powered by the utility API and use simplified values without `calc()`.
- mdo-do: Need to refactor utilities API if we want to restore the commented out custom ratios.
- **Display utilities:** added `flow-root` option for a modern clearfix.
- **Sizing utilities:**
- Renamed `.mh-*`/`.mw-*` to `.max-h-*`/`.max-w-*`
- Added `.min-h-*` and `.min-w-*` utilities with two default values, `0` and `100%`
- Added `auto`, `min-content`, `max-content`, and `fit-content` to `width` and `height` utilities.
- **Flex & Grid utilities:**
- Added `.place-items` and `.justify-items` utilities.
### JavaScript
### Docs
- **Dropped jQuery dependency** and rewrote plugins to be in regular JavaScript.
- <span class="badge text-bg-danger">Breaking</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`.
- **All plugins can now accept a CSS selector as the first argument.** You can either pass a DOM element or any valid CSS selector to create a new instance of the plugin:
```js
const modal = new bootstrap.Modal('#myModal')
const dropdown = new bootstrap.Dropdown('[data-bs-toggle="dropdown"]')
```
- `popperConfig` can be passed as a function that accepts the Bootstraps default Popper config as an argument, so that you can merge this default configuration in your way. **Applies to dropdowns, popovers, and tooltips.**
- The default value for the `fallbackPlacements` is changed to `['top', 'right', 'bottom', 'left']` for better placement of Popper elements. **Applies to dropdowns, popovers, and tooltips.**
- Removed underscore from public static methods like `_getInstance()` → `getInstance()`.
- Removed `util.js`, with its functionality now integrated into individual plugins. If you previously included `util.js` manually, you can safely remove it, as it is no longer needed. Each plugin now contains only the utilities it requires, enhancing modularity and reducing dependencies.
- Removed all `AddedIn` badges.
- Rearranged utilities documentation to break apart larger pages that included groups of utilities. Sizing, spacing, flex, type, and more have been broken out into smaller pages with new sub-group headings in the sidebar.
@@ -0,0 +1,212 @@
---
title: Align content
description: Use align-content utilities to align flex items together on the cross axis.
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/align-content
---
import { getData } from '@libs/data'
## Overview
Use `align-content` utilities on flexbox containers to align flex items _together_ on the cross axis. Choose from `start` (browser default), `end`, `center`, `between`, `around`, or `stretch`. To demonstrate these utilities, we've enforced `flex-wrap: wrap` and increased the number of flex items.
**Heads up!** This property has no effect on single rows of flex items.
## Basic usage
### Start
<div class="bd-example bd-example-flex">
<div class="d-flex align-content-start flex-wrap" style="height: 200px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
</div>
```html
<div class="d-flex align-content-start flex-wrap">...</div>
```
### End
<div class="bd-example bd-example-flex">
<div class="d-flex align-content-end flex-wrap" style="height: 200px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
</div>
```html
<div class="d-flex align-content-end flex-wrap">...</div>
```
### Center
<div class="bd-example bd-example-flex">
<div class="d-flex align-content-center flex-wrap" style="height: 200px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
</div>
```html
<div class="d-flex align-content-center flex-wrap">...</div>
```
### Between
<div class="bd-example bd-example-flex">
<div class="d-flex align-content-between flex-wrap" style="height: 200px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
</div>
```html
<div class="d-flex align-content-between flex-wrap">...</div>
```
### Around
<div class="bd-example bd-example-flex">
<div class="d-flex align-content-around flex-wrap" style="height: 200px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
</div>
```html
<div class="d-flex align-content-around flex-wrap">...</div>
```
### Stretch
<div class="bd-example bd-example-flex">
<div class="d-flex align-content-stretch flex-wrap" style="height: 200px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
</div>
```html
<div class="d-flex align-content-stretch flex-wrap">...</div>
```
## Responsive
Responsive variations also exist for `align-content`.
<ul>
{getData('breakpoints').map((breakpoint) => {
return (
<Fragment>
<li><code>.align-content{breakpoint.abbr}-start</code></li>
<li><code>.align-content{breakpoint.abbr}-end</code></li>
<li><code>.align-content{breakpoint.abbr}-center</code></li>
<li><code>.align-content{breakpoint.abbr}-between</code></li>
<li><code>.align-content{breakpoint.abbr}-around</code></li>
<li><code>.align-content{breakpoint.abbr}-stretch</code></li>
</Fragment>
)
})}
</ul>
## CSS
### Sass utilities API
Align content utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
```scss
"align-content": (
responsive: true,
property: align-content,
values: (
start: flex-start,
end: flex-end,
center: center,
between: space-between,
around: space-around,
stretch: stretch,
)
),
```
@@ -0,0 +1,88 @@
---
title: Align items
description: Use align-items utilities to change the alignment of flex items on the cross axis.
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/align-items
---
import { getData } from '@libs/data'
## Overview
Use `align-items` utilities on flexbox containers to change the alignment of flex items on the cross axis (the y-axis to start, x-axis if `flex-direction: column`). Choose from `start`, `end`, `center`, `baseline`, or `stretch` (browser default).
## Basic usage
<div class="bd-example bd-example-flex">
<div class="d-flex align-items-start mb-3" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex align-items-end mb-3" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex align-items-center mb-3" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex align-items-baseline mb-3" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex align-items-stretch" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
</div>
```html
<div class="d-flex align-items-start">...</div>
<div class="d-flex align-items-end">...</div>
<div class="d-flex align-items-center">...</div>
<div class="d-flex align-items-baseline">...</div>
<div class="d-flex align-items-stretch">...</div>
```
## Responsive
Responsive variations also exist for `align-items`.
<ul>
{getData('breakpoints').map((breakpoint) => {
return (
<Fragment>
<li><code>.align-items{breakpoint.abbr}-start</code></li>
<li><code>.align-items{breakpoint.abbr}-end</code></li>
<li><code>.align-items{breakpoint.abbr}-center</code></li>
<li><code>.align-items{breakpoint.abbr}-baseline</code></li>
<li><code>.align-items{breakpoint.abbr}-stretch</code></li>
</Fragment>
)
})}
</ul>
## CSS
### Sass utilities API
Align items utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
```scss
"align-items": (
responsive: true,
property: align-items,
values: (
start: flex-start,
end: flex-end,
center: center,
baseline: baseline,
stretch: stretch,
)
),
```
@@ -0,0 +1,89 @@
---
title: Align self
description: Use align-self utilities to individually change the alignment of flex items on the cross axis.
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/align-self
---
import { getData } from '@libs/data'
## Overview
Use `align-self` utilities on flexbox items to individually change their alignment on the cross axis (the y-axis to start, x-axis if `flex-direction: column`). Choose from the same options as `align-items`: `start`, `end`, `center`, `baseline`, or `stretch` (browser default).
## Basic usage
<div class="bd-example bd-example-flex">
<div class="d-flex mb-3" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="align-self-start p-2">Aligned flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex mb-3" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="align-self-end p-2">Aligned flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex mb-3" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="align-self-center p-2">Aligned flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex mb-3" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="align-self-baseline p-2">Aligned flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="align-self-stretch p-2">Aligned flex item</div>
<div class="p-2">Flex item</div>
</div>
</div>
```html
<div class="align-self-start">Aligned flex item</div>
<div class="align-self-end">Aligned flex item</div>
<div class="align-self-center">Aligned flex item</div>
<div class="align-self-baseline">Aligned flex item</div>
<div class="align-self-stretch">Aligned flex item</div>
```
## Responsive
Responsive variations also exist for `align-self`.
<ul>
{getData('breakpoints').map((breakpoint) => {
return (
<Fragment>
<li><code>.align-self{breakpoint.abbr}-start</code></li>
<li><code>.align-self{breakpoint.abbr}-end</code></li>
<li><code>.align-self{breakpoint.abbr}-center</code></li>
<li><code>.align-self{breakpoint.abbr}-baseline</code></li>
<li><code>.align-self{breakpoint.abbr}-stretch</code></li>
</Fragment>
)
})}
</ul>
## CSS
### Sass utilities API
Align self utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
```scss
"align-self": (
responsive: true,
property: align-self,
values: (
auto: auto,
start: flex-start,
end: flex-end,
center: center,
baseline: baseline,
stretch: stretch,
)
),
```
+13 -13
View File
@@ -296,7 +296,7 @@ Output:
.opacity-md-100 { opacity: 1; }
}
@media (min-width: 992px) {
@media (min-width: 1024px) {
.opacity-lg-0 { opacity: 0; }
.opacity-lg-25 { opacity: .25; }
.opacity-lg-50 { opacity: .5; }
@@ -304,7 +304,7 @@ Output:
.opacity-lg-100 { opacity: 1; }
}
@media (min-width: 1200px) {
@media (min-width: 1280px) {
.opacity-xl-0 { opacity: 0; }
.opacity-xl-25 { opacity: .25; }
.opacity-xl-50 { opacity: .5; }
@@ -312,12 +312,12 @@ Output:
.opacity-xl-100 { opacity: 1; }
}
@media (min-width: 1400px) {
.opacity-xxl-0 { opacity: 0; }
.opacity-xxl-25 { opacity: .25; }
.opacity-xxl-50 { opacity: .5; }
.opacity-xxl-75 { opacity: .75; }
.opacity-xxl-100 { opacity: 1; }
@media (min-width: 1536px) {
.opacity-2xl-0 { opacity: 0; }
.opacity-2xl-25 { opacity: .25; }
.opacity-2xl-50 { opacity: .5; }
.opacity-2xl-75 { opacity: .75; }
.opacity-2xl-100 { opacity: 1; }
}
```
@@ -507,19 +507,19 @@ This will now generate responsive variations of `.border` and `.border-0` for ea
.border-md-0 { ... }
}
@media (min-width: 992px) {
@media (min-width: 1024px) {
.border-lg { ... }
.border-lg-0 { ... }
}
@media (min-width: 1200px) {
@media (min-width: 1280px) {
.border-xl { ... }
.border-xl-0 { ... }
}
@media (min-width: 1400px) {
.border-xxl { ... }
.border-xxl-0 { ... }
@media (min-width: 1536px) {
.border-2xl { ... }
.border-2xl-0 { ... }
}
```
+8 -8
View File
@@ -47,12 +47,12 @@ Change the value of the [`display` property](https://developer.mozilla.org/en-US
## Notation
Display utility classes that apply to all [breakpoints]([[docsref:/layout/breakpoints]]), from `xs` to `xxl`, have no breakpoint abbreviation in them. This is because those classes are applied from `min-width: 0;` and up, and thus are not bound by a media query. The remaining breakpoints, however, do include a breakpoint abbreviation.
Display utility classes that apply to all [breakpoints]([[docsref:/layout/breakpoints]]), from `xs` to `2xl`, have no breakpoint abbreviation in them. This is because those classes are applied from `min-width: 0;` and up, and thus are not bound by a media query. The remaining breakpoints, however, do include a breakpoint abbreviation.
As such, the classes are named using the format:
- `.d-{value}` for `xs`
- `.d-{breakpoint}-{value}` for `sm`, `md`, `lg`, `xl`, and `xxl`.
- `.d-{breakpoint}-{value}` for `sm`, `md`, `lg`, `xl`, and `2xl`.
Where *value* is one of:
@@ -70,7 +70,7 @@ Where *value* is one of:
The display values can be altered by changing the `display` values defined in `$utilities` and recompiling the SCSS.
The media queries affect screen widths with the given breakpoint *or larger*. For example, `.d-lg-none` sets `display: none;` on `lg`, `xl`, and `xxl` screens.
The media queries affect screen widths with the given breakpoint *or larger*. For example, `.d-lg-none` sets `display: none;` on `lg`, `xl`, and `2xl` screens.
## Clearfix
@@ -92,7 +92,7 @@ There's no more clearfix helper in v6 as it's an outdated technique. Instead, us
For faster mobile-friendly development, use responsive display classes for showing and hiding elements by device. Avoid creating entirely different versions of the same site, instead hide elements responsively for each screen size.
To hide elements simply use the `.d-none` class or one of the `.d-{sm,md,lg,xl,xxl}-none` classes for any responsive screen variation.
To hide elements simply use the `.d-none` class or one of the `.d-{sm,md,lg,xl,2xl}-none` classes for any responsive screen variation.
To show an element only on a given interval of screen sizes you can combine one `.d-*-none` class with a `.d-*-*` class, for example `.d-none .d-md-block .d-xl-none` will hide the element for all screen sizes except on medium and large devices.
@@ -104,15 +104,15 @@ To show an element only on a given interval of screen sizes you can combine one
| Hidden only on sm | `.d-sm-none .d-md-block` |
| Hidden only on md | `.d-md-none .d-lg-block` |
| Hidden only on lg | `.d-lg-none .d-xl-block` |
| Hidden only on xl | `.d-xl-none .d-xxl-block` |
| Hidden only on xxl | `.d-xxl-none` |
| Hidden only on xl | `.d-xl-none .d-2xl-block` |
| Hidden only on 2xl | `.d-2xl-none` |
| Visible on all | `.d-block` |
| Visible only on xs | `.d-block .d-sm-none` |
| Visible only on sm | `.d-none .d-sm-block .d-md-none` |
| Visible only on md | `.d-none .d-md-block .d-lg-none` |
| Visible only on lg | `.d-none .d-lg-block .d-xl-none` |
| Visible only on xl | `.d-none .d-xl-block .d-xxl-none` |
| Visible only on xxl | `.d-none .d-xxl-block` |
| Visible only on xl | `.d-none .d-xl-block .d-2xl-none` |
| Visible only on 2xl | `.d-none .d-2xl-block` |
</BsTable>
<Example code={`<div class="d-lg-none">hide on lg and wider screens</div>
+15 -451
View File
@@ -49,7 +49,7 @@ Use `.flex-row` to set a horizontal direction (the browser default), or `.flex-r
<div class="p-2">Flex item 3</div>
</div>`} />
Use `.flex-column` to set a vertical direction, or `.flex-column-reverse` to start the vertical direction from the opposite side.
Use `.flex-column` to set a vertical direction, or `.flex-column-reverse` to start the vertical direction from the opposite side.
<Example class="bd-example-flex" code={`<div class="d-flex flex-column mb-3">
<div class="p-2">Flex item 1</div>
@@ -65,191 +65,14 @@ Use `.flex-column` to set a vertical direction, or `.flex-column-reverse` to st
Responsive variations also exist for `flex-direction`.
<ul>
{getData('breakpoints').map((breakpoint) => {
return (
<Fragment>
<li><code>.flex{breakpoint.abbr}-row</code></li>
<li><code>.flex{breakpoint.abbr}-row-reverse</code></li>
<li><code>.flex{breakpoint.abbr}-column</code></li>
<li><code>.flex{breakpoint.abbr}-column-reverse</code></li>
</Fragment>
)
})}
</ul>
## Justify content
Use `justify-content` utilities on flexbox containers to change the alignment of flex items on the main axis (the x-axis to start, y-axis if `flex-direction: column`). Choose from `start` (browser default), `end`, `center`, `between`, `around`, or `evenly`.
<div class="bd-example bd-example-flex">
<div class="d-flex justify-content-start mb-3">
<div class="p-2 bd-highlight">Justify</div>
<div class="p-2 bd-highlight">Content</div>
<div class="p-2 bd-highlight">Start</div>
</div>
<div class="d-flex justify-content-end mb-3">
<div class="p-2 bd-highlight">Justify</div>
<div class="p-2 bd-highlight">Content</div>
<div class="p-2 bd-highlight">End</div>
</div>
<div class="d-flex justify-content-center mb-3">
<div class="p-2 bd-highlight">Justify</div>
<div class="p-2 bd-highlight">Content</div>
<div class="p-2 bd-highlight">Center</div>
</div>
<div class="d-flex justify-content-between mb-3">
<div class="p-2 bd-highlight">Justify</div>
<div class="p-2 bd-highlight">Content</div>
<div class="p-2 bd-highlight">Between</div>
</div>
<div class="d-flex justify-content-around mb-3">
<div class="p-2 bd-highlight">Justify</div>
<div class="p-2 bd-highlight">Content</div>
<div class="p-2 bd-highlight">Around</div>
</div>
<div class="d-flex justify-content-evenly">
<div class="p-2 bd-highlight">Justify</div>
<div class="p-2 bd-highlight">Content</div>
<div class="p-2 bd-highlight">Evenly</div>
</div>
</div>
```html
<div class="d-flex justify-content-start">...</div>
<div class="d-flex justify-content-end">...</div>
<div class="d-flex justify-content-center">...</div>
<div class="d-flex justify-content-between">...</div>
<div class="d-flex justify-content-around">...</div>
<div class="d-flex justify-content-evenly">...</div>
```
Responsive variations also exist for `justify-content`.
<ul>
{getData('breakpoints').map((breakpoint) => {
return (
<Fragment>
<li><code>.justify-content{breakpoint.abbr}-start</code></li>
<li><code>.justify-content{breakpoint.abbr}-end</code></li>
<li><code>.justify-content{breakpoint.abbr}-center</code></li>
<li><code>.justify-content{breakpoint.abbr}-between</code></li>
<li><code>.justify-content{breakpoint.abbr}-around</code></li>
<li><code>.justify-content{breakpoint.abbr}-evenly</code></li>
</Fragment>
)
})}
</ul>
## Align items
Use `align-items` utilities on flexbox containers to change the alignment of flex items on the cross axis (the y-axis to start, x-axis if `flex-direction: column`). Choose from `start`, `end`, `center`, `baseline`, or `stretch` (browser default).
<div class="bd-example bd-example-flex">
<div class="d-flex align-items-start mb-3" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex align-items-end mb-3" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex align-items-center mb-3" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex align-items-baseline mb-3" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex align-items-stretch" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
</div>
```html
<div class="d-flex align-items-start">...</div>
<div class="d-flex align-items-end">...</div>
<div class="d-flex align-items-center">...</div>
<div class="d-flex align-items-baseline">...</div>
<div class="d-flex align-items-stretch">...</div>
```
Responsive variations also exist for `align-items`.
<ul>
{getData('breakpoints').map((breakpoint) => {
return (
<Fragment>
<li><code>.align-items{breakpoint.abbr}-start</code></li>
<li><code>.align-items{breakpoint.abbr}-end</code></li>
<li><code>.align-items{breakpoint.abbr}-center</code></li>
<li><code>.align-items{breakpoint.abbr}-baseline</code></li>
<li><code>.align-items{breakpoint.abbr}-stretch</code></li>
</Fragment>
)
})}
</ul>
## Align self
Use `align-self` utilities on flexbox items to individually change their alignment on the cross axis (the y-axis to start, x-axis if `flex-direction: column`). Choose from the same options as `align-items`: `start`, `end`, `center`, `baseline`, or `stretch` (browser default).
<div class="bd-example bd-example-flex">
<div class="d-flex mb-3" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="align-self-start p-2">Aligned flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex mb-3" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="align-self-end p-2">Aligned flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex mb-3" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="align-self-center p-2">Aligned flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex mb-3" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="align-self-baseline p-2">Aligned flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex" style="height: 100px">
<div class="p-2">Flex item</div>
<div class="align-self-stretch p-2">Aligned flex item</div>
<div class="p-2">Flex item</div>
</div>
</div>
```html
<div class="align-self-start">Aligned flex item</div>
<div class="align-self-end">Aligned flex item</div>
<div class="align-self-center">Aligned flex item</div>
<div class="align-self-baseline">Aligned flex item</div>
<div class="align-self-stretch">Aligned flex item</div>
```
Responsive variations also exist for `align-self`.
<ul>
{getData('breakpoints').map((breakpoint) => {
return (
<Fragment>
<li><code>.align-self{breakpoint.abbr}-start</code></li>
<li><code>.align-self{breakpoint.abbr}-end</code></li>
<li><code>.align-self{breakpoint.abbr}-center</code></li>
<li><code>.align-self{breakpoint.abbr}-baseline</code></li>
<li><code>.align-self{breakpoint.abbr}-stretch</code></li>
</Fragment>
)
})}
{getSequence(0, 5).map((i) => (
<Fragment>
<li><code>.flex{getData('breakpoints')[i].abbr}-row</code></li>
<li><code>.flex{getData('breakpoints')[i].abbr}-row-reverse</code></li>
<li><code>.flex{getData('breakpoints')[i].abbr}-column</code></li>
<li><code>.flex{getData('breakpoints')[i].abbr}-column-reverse</code></li>
</Fragment>
))}
</ul>
## Fill
@@ -274,7 +97,7 @@ Responsive variations also exist for `flex-fill`.
## Grow and shrink
Use `.flex-grow-*` utilities to toggle a flex items ability to grow to fill available space. In the example below, the `.flex-grow-1` elements uses all available space it can, while allowing the remaining two flex items their necessary space.
Use `.flex-grow-*` utilities to toggle a flex item's ability to grow to fill available space. In the example below, the `.flex-grow-1` elements uses all available space it can, while allowing the remaining two flex items their necessary space.
<Example class="bd-example-flex" code={`<div class="d-flex">
<div class="p-2 flex-grow-1">Flex item</div>
@@ -282,7 +105,7 @@ Use `.flex-grow-*` utilities to toggle a flex items ability to grow to fill a
<div class="p-2">Third flex item</div>
</div>`} />
Use `.flex-shrink-*` utilities to toggle a flex items ability to shrink if necessary. In the example below, the second flex item with `.flex-shrink-1` is forced to wrap its contents to a new line, shrinking to allow more space for the previous flex item with `.w-100`.
Use `.flex-shrink-*` utilities to toggle a flex item's ability to shrink if necessary. In the example below, the second flex item with `.flex-shrink-1` is forced to wrap its contents to a new line, "shrinking" to allow more space for the previous flex item with `.w-100`.
<Example class="bd-example-flex" code={`<div class="d-flex">
<div class="p-2 w-100">Flex item</div>
@@ -295,51 +118,15 @@ Responsive variations also exist for `flex-grow` and `flex-shrink`.
{getData('breakpoints').map((breakpoint) => {
return (
<Fragment>
<li><code>.flex{breakpoint.abbr}-{'{'}grow|shrink{'}'}-0</code></li>
<li><code>.flex{breakpoint.abbr}-{'{'}grow|shrink{'}'}-1</code></li>
<li><code>.flex{breakpoint.abbr}-grow-0</code></li>
<li><code>.flex{breakpoint.abbr}-grow-1</code></li>
<li><code>.flex{breakpoint.abbr}-shrink-0</code></li>
<li><code>.flex{breakpoint.abbr}-shrink-1</code></li>
</Fragment>
)
})}
</ul>
## Auto margins
Flexbox can do some pretty awesome things when you mix flex alignments with auto margins. Shown below are three examples of controlling flex items via auto margins: default (no auto margin), pushing two items to the right (`.me-auto`), and pushing two items to the left (`.ms-auto`).
<Example class="bd-example-flex" code={`<div class="d-flex mb-3">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex mb-3">
<div class="me-auto p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex mb-3">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="ms-auto p-2">Flex item</div>
</div>`} />
### With align-items
Vertically move one flex item to the top or bottom of a container by mixing `align-items`, `flex-direction: column`, and `margin-top: auto` or `margin-bottom: auto`.
<Example class="bd-example-flex" code={`<div class="d-flex align-items-start flex-column mb-3" style="height: 200px;">
<div class="mb-auto p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
<div class="d-flex align-items-end flex-column mb-3" style="height: 200px;">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="mt-auto p-2">Flex item</div>
</div>`} />
## Wrap
Change how flex items wrap in a flex container. Choose from no wrapping at all (the browser default) with `.flex-nowrap`, wrapping with `.flex-wrap`, or reverse wrapping with `.flex-wrap-reverse`.
@@ -424,229 +211,6 @@ Responsive variations also exist for `flex-wrap`.
})}
</ul>
## Order
Change the _visual_ order of specific flex items with a handful of `order` utilities. We only provide options for making an item first or last, as well as a reset to use the DOM order. As `order` takes any integer value from 0 to 5, add custom CSS for any additional values needed.
<Example class="bd-example-flex" code={`<div class="d-flex flex-nowrap">
<div class="order-3 p-2">First flex item</div>
<div class="order-2 p-2">Second flex item</div>
<div class="order-1 p-2">Third flex item</div>
</div>`} />
Responsive variations also exist for `order`.
<ul>
{getData('breakpoints').map((breakpoint) => getSequence(0, 5).map((value) => {
return (
<li><code>.order{breakpoint.abbr}-{value}</code></li>
)
}))}
</ul>
Additionally there are also responsive `.order-first` and `.order-last` classes that change the `order` of an element by applying `order: -1` and `order: 6`, respectively.
<ul>
{getData('breakpoints').map((breakpoint) => ['first', 'last'].map((value) => {
return (
<li><code>.order{breakpoint.abbr}-{value}</code></li>
)
}))}
</ul>
## Align content
Use `align-content` utilities on flexbox containers to align flex items _together_ on the cross axis. Choose from `start` (browser default), `end`, `center`, `between`, `around`, or `stretch`. To demonstrate these utilities, weve enforced `flex-wrap: wrap` and increased the number of flex items.
**Heads up!** This property has no effect on single rows of flex items.
<div class="bd-example bd-example-flex">
<div class="d-flex align-content-start flex-wrap mb-3" style="height: 200px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
</div>
```html
<div class="d-flex align-content-start flex-wrap">
...
</div>
```
<div class="bd-example bd-example-flex">
<div class="d-flex align-content-end flex-wrap mb-3" style="height: 200px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
</div>
```html
<div class="d-flex align-content-end flex-wrap">...</div>
```
<div class="bd-example bd-example-flex">
<div class="d-flex align-content-center flex-wrap mb-3" style="height: 200px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
</div>
```html
<div class="d-flex align-content-center flex-wrap">...</div>
```
<div class="bd-example bd-example-flex">
<div class="d-flex align-content-between flex-wrap mb-3" style="height: 200px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
</div>
```html
<div class="d-flex align-content-between flex-wrap">...</div>
```
<div class="bd-example bd-example-flex">
<div class="d-flex align-content-around flex-wrap mb-3" style="height: 200px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
</div>
```html
<div class="d-flex align-content-around flex-wrap">...</div>
```
<div class="bd-example bd-example-flex">
<div class="d-flex align-content-stretch flex-wrap mb-3" style="height: 200px">
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
<div class="p-2">Flex item</div>
</div>
</div>
```html
<div class="d-flex align-content-stretch flex-wrap">...</div>
```
Responsive variations also exist for `align-content`.
<ul>
{getData('breakpoints').map((breakpoint) => {
return (
<Fragment>
<li><code>.align-content{breakpoint.abbr}-start</code></li>
<li><code>.align-content{breakpoint.abbr}-end</code></li>
<li><code>.align-content{breakpoint.abbr}-center</code></li>
<li><code>.align-content{breakpoint.abbr}-between</code></li>
<li><code>.align-content{breakpoint.abbr}-around</code></li>
<li><code>.align-content{breakpoint.abbr}-stretch</code></li>
</Fragment>
)
})}
</ul>
## Media object
Looking to replicate the [media object component](https://getbootstrap.com/docs/4.6/components/media-object/) from Bootstrap 4? Recreate it in no time with a few flex utilities that allow even more flexibility and customization than before.
<Example code={`<div class="d-flex">
<div class="flex-shrink-0">
<Placeholder width="100" height="100" color="#999" background="#e5e5e5" text="Image" />
</div>
<div class="flex-grow-1 ms-3">
This is some content from a media component. You can replace this with any content and adjust it as needed.
</div>
</div>`} />
And say you want to vertically center the content next to the image:
<Example code={`<div class="d-flex align-items-center">
<div class="flex-shrink-0">
<Placeholder width="100" height="100" color="#999" background="#e5e5e5" text="Image" />
</div>
<div class="flex-grow-1 ms-3">
This is some content from a media component. You can replace this with any content and adjust it as needed.
</div>
</div>`} />
## CSS
### Sass utilities API
+1 -1
View File
@@ -34,7 +34,7 @@ Responsive variations also exist for each `float` value.
<div class="float-md-end">Float end on viewports sized MD (medium) or wider</div><br>
<div class="float-lg-end">Float end on viewports sized LG (large) or wider</div><br>
<div class="float-xl-end">Float end on viewports sized XL (extra large) or wider</div><br>
<div class="float-xxl-end">Float end on viewports sized XXL (extra extra large) or wider</div><br>`} />
<div class="float-2xl-end">Float end on viewports sized 2XL (extra extra large) or wider</div><br>`} />
Here are all the support classes:
@@ -0,0 +1,122 @@
---
title: Font style
description: Utilities for controlling font properties including size, weight, style, line height, and font family.
toc: true
reference:
- class: fs-1
styles:
font-size: 'calc(1.375rem + 1.5vw)'
- class: fs-6
styles:
font-size: '1rem'
- class: fw-bold
styles:
font-weight: '700'
- class: fw-normal
styles:
font-weight: '400'
- class: fst-italic
styles:
font-style: 'italic'
- class: fst-normal
styles:
font-style: 'normal'
- class: lh-1
styles:
line-height: '1'
- class: font-monospace
styles:
font-family: 'var(--bs-font-monospace)'
---
import { getData } from '@libs/data'
## Font size
Quickly change the `font-size` of text. While our heading classes (e.g., `.h1``.h6`) apply `font-size`, `font-weight`, and `line-height`, these utilities _only_ apply `font-size`. Sizing for these utilities matches HTML's heading elements, so as the number increases, their size decreases.
<Example code={`<p class="fs-1">.fs-1 text</p>
<p class="fs-2">.fs-2 text</p>
<p class="fs-3">.fs-3 text</p>
<p class="fs-4">.fs-4 text</p>
<p class="fs-5">.fs-5 text</p>
<p class="fs-6">.fs-6 text</p>`} />
Customize your available `font-size`s by modifying the `$font-sizes` Sass map.
## Font weight and italics
Quickly change the `font-weight` or `font-style` of text with these utilities. `font-style` utilities are abbreviated as `.fst-*` and `font-weight` utilities are abbreviated as `.fw-*`.
<Example code={`<p class="fw-bold">Bold text.</p>
<p class="fw-bolder">Bolder weight text (relative to the parent element).</p>
<p class="fw-semibold">Semibold weight text.</p>
<p class="fw-medium">Medium weight text.</p>
<p class="fw-normal">Normal weight text.</p>
<p class="fw-light">Light weight text.</p>
<p class="fw-lighter">Lighter weight text (relative to the parent element).</p>
<p class="fst-italic">Italic text.</p>
<p class="fst-normal">Text with normal font style</p>`} />
## Line height
Change the line height with `.lh-*` utilities.
<Example code={`<p class="lh-1">This is a long paragraph written to show how the line-height of an element is affected by our utilities. Classes are applied to the element itself or sometimes the parent element. These classes can be customized as needed with our utility API.</p>
<p class="lh-sm">This is a long paragraph written to show how the line-height of an element is affected by our utilities. Classes are applied to the element itself or sometimes the parent element. These classes can be customized as needed with our utility API.</p>
<p class="lh-base">This is a long paragraph written to show how the line-height of an element is affected by our utilities. Classes are applied to the element itself or sometimes the parent element. These classes can be customized as needed with our utility API.</p>
<p class="lh-lg">This is a long paragraph written to show how the line-height of an element is affected by our utilities. Classes are applied to the element itself or sometimes the parent element. These classes can be customized as needed with our utility API.</p>`} />
## Font family
Change a selection to our monospace font stack with `.font-monospace`.
<Example code={`<p class="font-monospace">This is in monospace</p>`} />
## CSS
### Sass utilities API
Font style utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
```scss
"font-family": (
property: font-family,
class: font,
values: (monospace: var(--#{$prefix}font-monospace))
),
"font-size": (
rfs: true,
property: font-size,
class: fs,
values: $font-sizes
),
"font-style": (
property: font-style,
class: fst,
values: italic normal
),
"font-weight": (
property: font-weight,
class: fw,
values: (
lighter: $font-weight-lighter,
light: $font-weight-light,
normal: $font-weight-normal,
medium: $font-weight-medium,
semibold: $font-weight-semibold,
bold: $font-weight-bold,
bolder: $font-weight-bolder
)
),
"line-height": (
property: line-height,
class: lh,
values: (
1: 1,
sm: $line-height-sm,
base: $line-height-base,
lg: $line-height-lg,
)
),
```
+148
View File
@@ -0,0 +1,148 @@
---
title: Height
description: Use height utilities to control the height of elements with responsive height classes.
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/height
reference:
- class: h-25
styles:
height: '25%'
- class: h-50
styles:
height: '50%'
- class: h-75
styles:
height: '75%'
- class: h-100
styles:
height: '100%'
- class: h-auto
styles:
height: 'auto'
- class: h-min
styles:
height: 'min-content'
- class: h-max
styles:
height: 'max-content'
- class: h-fit
styles:
height: 'fit-content'
- class: max-h-100
styles:
max-height: '100%'
- class: min-h-0
styles:
min-height: '0'
- class: min-h-100
styles:
min-height: '100%'
- class: vh-100
styles:
height: '100vh'
- class: min-vh-100
styles:
min-height: '100vh'
---
## Overview
Use height utilities to set the height of elements. Height utilities are generated from the utility API and include support for percentage values, intrinsic sizing keywords, and viewport units.
## Relative height
Set height relative to the parent element using percentage-based utilities. Includes support for `25%`, `50%`, `75%`, `100%`, and `auto` by default.
<Example class="bd-example-flex" code={`<div style="height: 100px;">
<div class="h-25 d-inline-block" style="width: 120px;">Height 25%</div>
<div class="h-50 d-inline-block" style="width: 120px;">Height 50%</div>
<div class="h-75 d-inline-block" style="width: 120px;">Height 75%</div>
<div class="h-100 d-inline-block" style="width: 120px;">Height 100%</div>
<div class="h-auto d-inline-block" style="width: 120px;">Height auto</div>
</div>`} />
## Intrinsic sizing
Use intrinsic sizing keywords to set height based on content.
<Example class="bd-example-flex" code={`<div style="height: 200px;">
<div class="h-min d-inline-block p-3" style="width: 120px;">Height min-content</div>
<div class="h-max d-inline-block p-3" style="width: 120px;">Height max-content</div>
<div class="h-fit d-inline-block p-3" style="width: 120px;">Height fit-content</div>
</div>`} />
## Max height
Set maximum height using `max-height` utilities.
<Example class="bd-example-flex" code={`<div style="height: 100px;">
<div class="max-h-100" style="width: 100px; height: 200px;">Max-height 100%</div>
</div>`} />
## Min height
Set minimum height using `min-height` utilities.
<Example class="bd-example-flex" code={`<div class="min-h-0 p-3" style="width: 200px;">
Min-height 0 (allows content to determine height)
</div>
<div class="min-h-100 p-3" style="width: 200px;">Min-height 100%</div>`} />
## Viewport height
Set height relative to the viewport using viewport units.
```html
<div class="vh-100">Height 100vh</div>
<div class="min-vh-100">Min-height 100vh</div>
```
<Callout>
**Full viewport height sections!** Using `vh-100` makes an element take up the entire viewport height, which is useful for hero sections and full-screen layouts.
</Callout>
## CSS
### Sass utilities API
Height utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
```scss
"height": (
property: height,
class: h,
values: (
25: 25%,
50: 50%,
75: 75%,
100: 100%,
auto: auto,
min: min-content,
max: max-content,
fit: fit-content,
)
),
"max-height": (
property: max-height,
class: max-h,
values: (100: 100%)
),
"min-height": (
property: min-height,
class: min-h,
values: (
0: 0,
100: 100%,
),
),
"viewport-height": (
property: height,
class: vh,
values: (100: 100vh)
),
"min-viewport-height": (
property: min-height,
class: min-vh,
values: (100: 100vh)
),
```
@@ -0,0 +1,96 @@
---
title: Justify content
description: Use justify-content utilities to change the alignment of flex items on the main axis.
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content
---
import { getData } from '@libs/data'
## Overview
Use `justify-content` utilities on flexbox containers to change the alignment of flex items on the main axis (the x-axis to start, y-axis if `flex-direction: column`). Choose from `start` (browser default), `end`, `center`, `between`, `around`, or `evenly`.
## Basic usage
<div class="bd-example bd-example-flex">
<div class="d-flex justify-content-start mb-3">
<div class="p-2 bd-highlight">Justify</div>
<div class="p-2 bd-highlight">Content</div>
<div class="p-2 bd-highlight">Start</div>
</div>
<div class="d-flex justify-content-end mb-3">
<div class="p-2 bd-highlight">Justify</div>
<div class="p-2 bd-highlight">Content</div>
<div class="p-2 bd-highlight">End</div>
</div>
<div class="d-flex justify-content-center mb-3">
<div class="p-2 bd-highlight">Justify</div>
<div class="p-2 bd-highlight">Content</div>
<div class="p-2 bd-highlight">Center</div>
</div>
<div class="d-flex justify-content-between mb-3">
<div class="p-2 bd-highlight">Justify</div>
<div class="p-2 bd-highlight">Content</div>
<div class="p-2 bd-highlight">Between</div>
</div>
<div class="d-flex justify-content-around mb-3">
<div class="p-2 bd-highlight">Justify</div>
<div class="p-2 bd-highlight">Content</div>
<div class="p-2 bd-highlight">Around</div>
</div>
<div class="d-flex justify-content-evenly">
<div class="p-2 bd-highlight">Justify</div>
<div class="p-2 bd-highlight">Content</div>
<div class="p-2 bd-highlight">Evenly</div>
</div>
</div>
```html
<div class="d-flex justify-content-start">...</div>
<div class="d-flex justify-content-end">...</div>
<div class="d-flex justify-content-center">...</div>
<div class="d-flex justify-content-between">...</div>
<div class="d-flex justify-content-around">...</div>
<div class="d-flex justify-content-evenly">...</div>
```
## Responsive
Responsive variations also exist for `justify-content`.
<ul>
{getData('breakpoints').map((breakpoint) => {
return (
<Fragment>
<li><code>.justify-content{breakpoint.abbr}-start</code></li>
<li><code>.justify-content{breakpoint.abbr}-end</code></li>
<li><code>.justify-content{breakpoint.abbr}-center</code></li>
<li><code>.justify-content{breakpoint.abbr}-between</code></li>
<li><code>.justify-content{breakpoint.abbr}-around</code></li>
<li><code>.justify-content{breakpoint.abbr}-evenly</code></li>
</Fragment>
)
})}
</ul>
## CSS
### Sass utilities API
Justify content utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
```scss
"justify-content": (
responsive: true,
property: justify-content,
values: (
start: flex-start,
end: flex-end,
center: center,
between: space-between,
around: space-around,
evenly: space-evenly,
)
),
```
@@ -0,0 +1,82 @@
---
title: Justify items
description: Use justify-items utilities to control the alignment of grid items along the inline axis (horizontally, in most writing modes).
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/justify-items
---
import { getData } from '@libs/data'
## Overview
Use `justify-items` utilities on CSS Grid containers to change the alignment of grid items along the inline (row) axis. This property controls how grid items are positioned horizontally within their grid areas.
## Basic usage
Use `justify-items` utilities to control the horizontal alignment of grid items. Choose from `start`, `end`, `center`, or `stretch` (browser default).
<div class="bd-example bd-example-flex vstack gap-3">
<div class="d-grid gap-3 justify-items-start" style="grid-template-columns: 1fr 1fr 1fr;">
<div class="p-2">Grid item</div>
<div class="p-2">Grid item</div>
<div class="p-2">Grid item</div>
</div>
<div class="d-grid gap-3 justify-items-end" style="grid-template-columns: 1fr 1fr 1fr;">
<div class="p-2">Grid item</div>
<div class="p-2">Grid item</div>
<div class="p-2">Grid item</div>
</div>
<div class="d-grid gap-3 justify-items-center" style="grid-template-columns: 1fr 1fr 1fr;">
<div class="p-2">Grid item</div>
<div class="p-2">Grid item</div>
<div class="p-2">Grid item</div>
</div>
<div class="d-grid gap-3 justify-items-stretch" style="grid-template-columns: 1fr 1fr 1fr;">
<div class="p-2">Grid item</div>
<div class="p-2">Grid item</div>
<div class="p-2">Grid item</div>
</div>
</div>
```html
<div class="d-grid justify-items-start">...</div>
<div class="d-grid justify-items-end">...</div>
<div class="d-grid justify-items-center">...</div>
<div class="d-grid justify-items-stretch">...</div>
```
## Responsive
Responsive variations also exist for `justify-items`.
<ul>
{getData('breakpoints').map((breakpoint) => {
return (
<Fragment>
<li><code>.justify-items{breakpoint.abbr}-start</code></li>
<li><code>.justify-items{breakpoint.abbr}-end</code></li>
<li><code>.justify-items{breakpoint.abbr}-center</code></li>
<li><code>.justify-items{breakpoint.abbr}-stretch</code></li>
</Fragment>
)
})}
</ul>
## CSS
### Sass utilities API
Justify items utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
```scss
"justify-items": (
responsive: true,
property: justify-items,
values: (
start: start,
end: end,
center: center,
stretch: stretch,
)
),
```
+208
View File
@@ -0,0 +1,208 @@
---
title: Margin
description: Use margin utilities to control the space around elements with responsive margin classes.
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/margin
reference:
- class: m-0
styles:
margin: '0'
- class: m-1
styles:
margin: '0.25rem'
- class: m-2
styles:
margin: '0.5rem'
- class: m-3
styles:
margin: '1rem'
- class: m-4
styles:
margin: '1.5rem'
- class: m-5
styles:
margin: '3rem'
- class: m-auto
styles:
margin: 'auto'
- class: mt-0
styles:
margin-top: '0'
- class: me-0
styles:
margin-right: '0'
- class: mb-0
styles:
margin-bottom: '0'
- class: ms-0
styles:
margin-left: '0'
- class: mx-0
styles:
margin-right: '0'
margin-left: '0'
- class: my-0
styles:
margin-top: '0'
margin-bottom: '0'
---
import { getData } from '@libs/data'
## Overview
Use margin utilities to control the outer space around elements. Margin utilities are built from a default Sass map ranging from `.25rem` to `3rem`.
<Callout>
**Using the CSS Grid layout module?** Consider using [the gap utility]([[docsref:/utilities/spacing#gap]]) instead.
</Callout>
## Notation
Margin utilities that apply to all breakpoints, from `xs` to `xxl`, have no breakpoint abbreviation in them. This is because those classes are applied from `min-width: 0` and up, and thus are not bound by a media query. The remaining breakpoints, however, do include a breakpoint abbreviation.
The classes are named using the format `{property}{sides}-{size}` for `xs` and `{property}{sides}-{breakpoint}-{size}` for `sm`, `md`, `lg`, `xl`, and `xxl`.
Where *property* is:
- `m` - for classes that set `margin`
Where *sides* is one of:
- `t` - for classes that set `margin-top`
- `b` - for classes that set `margin-bottom`
- `s` - (start) for classes that set `margin-left` in LTR, `margin-right` in RTL
- `e` - (end) for classes that set `margin-right` in LTR, `margin-left` in RTL
- `x` - for classes that set both `*-left` and `*-right`
- `y` - for classes that set both `*-top` and `*-bottom`
- blank - for classes that set a `margin` on all 4 sides of the element
Where *size* is one of:
- `0` - for classes that eliminate the `margin` by setting it to `0`
- `1` - (by default) for classes that set the `margin` to `$spacer * .25`
- `2` - (by default) for classes that set the `margin` to `$spacer * .5`
- `3` - (by default) for classes that set the `margin` to `$spacer`
- `4` - (by default) for classes that set the `margin` to `$spacer * 1.5`
- `5` - (by default) for classes that set the `margin` to `$spacer * 3`
- `auto` - for classes that set the `margin` to auto
(You can add more sizes by adding entries to the `$spacers` Sass map variable.)
## Examples
Here are some representative examples of these classes:
```scss
.mt-0 {
margin-top: 0;
}
.ms-1 {
margin-left: ($spacer * .25);
}
.mx-2 {
margin-left: ($spacer * .5);
margin-right: ($spacer * .5);
}
.m-3 {
margin: $spacer;
}
```
## Horizontal centering
Bootstrap includes an `.mx-auto` class for horizontally centering fixed-width block level content—that is, content that has `display: block` and a `width` set—by setting the horizontal margins to `auto`.
<Example showMarkup={false} code={`<div class="mx-auto p-2" style="width: 200px; background-color: rgba(var(--bd-violet-rgb),.15); border: rgba(var(--bd-violet-rgb),.3) solid 1px;">
Centered element
</div>`} />
```html
<div class="mx-auto p-2" style="width: 200px;">
Centered element
</div>
```
## Negative margin
When using `display: grid`, you can make use of negative margin utilities along the parent grid container. This can sometimes be helpful to match visual alignment of a child grid with the rest of your layout. Remember that [CSS Grid has a gap property]([[docsref:/utilities/spacing#gap]]) that might be an alternative solution.
<Example showMarkup={false} code={`<div class="grid text-center" style="--bs-columns: 3; --bs-gap: .25rem;">
<div class="g-col-1">.g-col-1</div>
<div class="g-col-1">.g-col-1</div>
<div class="g-col-1">.g-col-1</div>
</div>`} />
```html
<div class="grid" style="--bs-columns: 3; --bs-gap: .25rem;">
<div class="g-col-1">.g-col-1</div>
<div class="g-col-1">.g-col-1</div>
<div class="g-col-1">.g-col-1</div>
</div>
```
## Responsive
All margin utilities are responsive and include all breakpoints.
<ul>
{getData('breakpoints').map((breakpoint) => {
return (
<li><code>.m{breakpoint.abbr}-0</code> through <code>.m{breakpoint.abbr}-5</code> and <code>.m{breakpoint.abbr}-auto</code></li>
)
})}
</ul>
## CSS
### Sass utilities API
Margin utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
```scss
"margin": (
responsive: true,
property: margin,
class: m,
values: map.merge($spacers, (auto: auto))
),
"margin-x": (
responsive: true,
property: margin-right margin-left,
class: mx,
values: map.merge($spacers, (auto: auto))
),
"margin-y": (
responsive: true,
property: margin-top margin-bottom,
class: my,
values: map.merge($spacers, (auto: auto))
),
"margin-top": (
responsive: true,
property: margin-top,
class: mt,
values: map.merge($spacers, (auto: auto))
),
"margin-end": (
responsive: true,
property: margin-right,
class: me,
values: map.merge($spacers, (auto: auto))
),
"margin-bottom": (
responsive: true,
property: margin-bottom,
class: mb,
values: map.merge($spacers, (auto: auto))
),
"margin-start": (
responsive: true,
property: margin-left,
class: ms,
values: map.merge($spacers, (auto: auto))
),
```
@@ -44,13 +44,13 @@ Add the `object-fit-{value}` class to the [replaced element](https://developer.m
## Responsive
Responsive variations also exist for each `object-fit` value using the format `.object-fit-{breakpoint}-{value}`, for the following breakpoint abbreviations: `sm`, `md`, `lg`, `xl`, and `xxl`. Classes can be combined for various effects as you need.
Responsive variations also exist for each `object-fit` value using the format `.object-fit-{breakpoint}-{value}`, for the following breakpoint abbreviations: `sm`, `md`, `lg`, `xl`, and `2xl`. Classes can be combined for various effects as you need.
<Example class="d-flex overflow-auto" code={`<Placeholder width="140" height="80" class="object-fit-sm-contain border rounded" text="Contain on sm" markup="img" />
<Placeholder width="140" height="80" class="object-fit-md-contain border rounded" text="Contain on md" markup="img" />
<Placeholder width="140" height="80" class="object-fit-lg-contain border rounded" text="Contain on lg" markup="img" />
<Placeholder width="140" height="80" class="object-fit-xl-contain border rounded" text="Contain on xl" markup="img" />
<Placeholder width="140" height="80" class="object-fit-xxl-contain border rounded" text="Contain on xxl" markup="img" />`} />
<Placeholder width="140" height="80" class="object-fit-2xl-contain border rounded" text="Contain on 2xl" markup="img" />`} />
## Video
+180
View File
@@ -0,0 +1,180 @@
---
title: Padding
description: Use padding utilities to control the inner space of elements with responsive padding classes.
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
reference:
- class: p-0
styles:
padding: '0'
- class: p-1
styles:
padding: '0.25rem'
- class: p-2
styles:
padding: '0.5rem'
- class: p-3
styles:
padding: '1rem'
- class: p-4
styles:
padding: '1.5rem'
- class: p-5
styles:
padding: '3rem'
- class: pt-0
styles:
padding-top: '0'
- class: pe-0
styles:
padding-right: '0'
- class: pb-0
styles:
padding-bottom: '0'
- class: ps-0
styles:
padding-left: '0'
- class: px-0
styles:
padding-right: '0'
padding-left: '0'
- class: py-0
styles:
padding-top: '0'
padding-bottom: '0'
---
import { getData } from '@libs/data'
## Overview
Use padding utilities to control the inner space within elements. Padding utilities are built from a default Sass map ranging from `.25rem` to `3rem`.
## Notation
Padding utilities that apply to all breakpoints, from `xs` to `xxl`, have no breakpoint abbreviation in them. This is because those classes are applied from `min-width: 0` and up, and thus are not bound by a media query. The remaining breakpoints, however, do include a breakpoint abbreviation.
The classes are named using the format `{property}{sides}-{size}` for `xs` and `{property}{sides}-{breakpoint}-{size}` for `sm`, `md`, `lg`, `xl`, and `xxl`.
Where *property* is:
- `p` - for classes that set `padding`
Where *sides* is one of:
- `t` - for classes that set `padding-top`
- `b` - for classes that set `padding-bottom`
- `s` - (start) for classes that set `padding-left` in LTR, `padding-right` in RTL
- `e` - (end) for classes that set `padding-right` in LTR, `padding-left` in RTL
- `x` - for classes that set both `*-left` and `*-right`
- `y` - for classes that set both `*-top` and `*-bottom`
- blank - for classes that set a `padding` on all 4 sides of the element
Where *size* is one of:
- `0` - for classes that eliminate the `padding` by setting it to `0`
- `1` - (by default) for classes that set the `padding` to `$spacer * .25`
- `2` - (by default) for classes that set the `padding` to `$spacer * .5`
- `3` - (by default) for classes that set the `padding` to `$spacer`
- `4` - (by default) for classes that set the `padding` to `$spacer * 1.5`
- `5` - (by default) for classes that set the `padding` to `$spacer * 3`
(You can add more sizes by adding entries to the `$spacers` Sass map variable.)
## Examples
Here are some representative examples of these classes:
```scss
.pt-0 {
padding-top: 0;
}
.ps-1 {
padding-left: ($spacer * .25);
}
.px-2 {
padding-left: ($spacer * .5);
padding-right: ($spacer * .5);
}
.p-3 {
padding: $spacer;
}
```
## Basic usage
<Example code={`<div class="p-3 mb-2 bg-light">
Regular padding on all sides
</div>
<div class="py-2 px-4 mb-2 bg-light">
Horizontal and vertical padding
</div>
<div class="pt-4 mb-2 bg-light">
Top padding only
</div>`} />
## Responsive
All padding utilities are responsive and include all breakpoints.
<ul>
{getData('breakpoints').map((breakpoint) => {
return (
<li><code>.p{breakpoint.abbr}-0</code> through <code>.p{breakpoint.abbr}-5</code></li>
)
})}
</ul>
## CSS
### Sass utilities API
Padding utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
```scss
"padding": (
responsive: true,
property: padding,
class: p,
values: $spacers
),
"padding-x": (
responsive: true,
property: padding-right padding-left,
class: px,
values: $spacers
),
"padding-y": (
responsive: true,
property: padding-top padding-bottom,
class: py,
values: $spacers
),
"padding-top": (
responsive: true,
property: padding-top,
class: pt,
values: $spacers
),
"padding-end": (
responsive: true,
property: padding-right,
class: pe,
values: $spacers
),
"padding-bottom": (
responsive: true,
property: padding-bottom,
class: pb,
values: $spacers
),
"padding-start": (
responsive: true,
property: padding-left,
class: ps,
values: $spacers
),
```
@@ -0,0 +1,82 @@
---
title: Place items
description: Use place-items utilities to control the alignment of grid items within their grid areas on both the block and inline axes simultaneously.
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/place-items
---
import { getData } from '@libs/data'
## Overview
Use `place-items` utilities on CSS Grid containers as a shorthand to set both `align-items` and `justify-items` at once. This property controls how grid items are positioned within their grid areas on both axes.
## Basic usage
Use `place-items` utilities to control the alignment of grid items. Choose from `start`, `end`, `center`, or `stretch` (browser default).
<div class="bd-example bd-example-flex vstack gap-3">
<div class="d-grid gap-3 place-items-start" style="grid-template-columns: 1fr 1fr 1fr; height: 150px;">
<div class="p-2">Grid item</div>
<div class="p-2">Grid item</div>
<div class="p-2">Grid item</div>
</div>
<div class="d-grid gap-3 place-items-end" style="grid-template-columns: 1fr 1fr 1fr; height: 150px;">
<div class="p-2">Grid item</div>
<div class="p-2">Grid item</div>
<div class="p-2">Grid item</div>
</div>
<div class="d-grid gap-3 place-items-center" style="grid-template-columns: 1fr 1fr 1fr; height: 150px;">
<div class="p-2">Grid item</div>
<div class="p-2">Grid item</div>
<div class="p-2">Grid item</div>
</div>
<div class="d-grid gap-3 place-items-stretch" style="grid-template-columns: 1fr 1fr 1fr; height: 150px;">
<div class="p-2">Grid item</div>
<div class="p-2">Grid item</div>
<div class="p-2">Grid item</div>
</div>
</div>
```html
<div class="d-grid place-items-start">...</div>
<div class="d-grid place-items-end">...</div>
<div class="d-grid place-items-center">...</div>
<div class="d-grid place-items-stretch">...</div>
```
## Responsive
Responsive variations also exist for `place-items`.
<ul>
{getData('breakpoints').map((breakpoint) => {
return (
<Fragment>
<li><code>.place-items{breakpoint.abbr}-start</code></li>
<li><code>.place-items{breakpoint.abbr}-end</code></li>
<li><code>.place-items{breakpoint.abbr}-center</code></li>
<li><code>.place-items{breakpoint.abbr}-stretch</code></li>
</Fragment>
)
})}
</ul>
## CSS
### Sass utilities API
Place items utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
```scss
"place-items": (
responsive: true,
property: place-items,
values: (
start: start,
end: end,
center: center,
stretch: stretch,
)
),
```
@@ -0,0 +1,63 @@
---
title: Pointer events
description: Control how elements respond to mouse and touch interactions with pointer-events utilities.
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
reference:
- class: pe-none
styles:
pointer-events: 'none'
- class: pe-auto
styles:
pointer-events: 'auto'
---
## Overview
Bootstrap provides `.pe-none` and `.pe-auto` classes to prevent or add element interactions through the `pointer-events` CSS property.
## Basic usage
<Example code={`<p><a href="#" class="pe-none" tabindex="-1" aria-disabled="true">This link</a> can not be clicked.</p>
<p><a href="#" class="pe-auto">This link</a> can be clicked (this is default behavior).</p>
<p class="pe-none"><a href="#" tabindex="-1" aria-disabled="true">This link</a> can not be clicked because the <code>pointer-events</code> property is inherited from its parent. However, <a href="#" class="pe-auto">this link</a> has a <code>pe-auto</code> class and can be clicked.</p>`} />
## Important considerations
The `.pe-none` class (and the `pointer-events` CSS property it sets) only prevents interactions with a pointer (mouse, stylus, touch). Links and controls with `.pe-none` are, by default, still focusable and actionable for keyboard users.
To ensure that they are completely neutralized even for keyboard users, you may need to add further attributes such as:
- `tabindex="-1"` (to prevent them from receiving keyboard focus)
- `aria-disabled="true"` (to convey the fact they are effectively disabled to assistive technologies)
- JavaScript to completely prevent them from being actionable
## Better alternatives
If possible, the simpler solution is:
- **For form controls**: Add the `disabled` HTML attribute
- **For links**: Remove the `href` attribute, making it a non-interactive anchor or placeholder link
<Callout type="warning">
**Accessibility warning:** Using `pointer-events: none` can create accessibility barriers. Always ensure that disabled elements are properly marked up with appropriate ARIA attributes and that keyboard users can't accidentally focus them.
</Callout>
## Use cases
- **`.pe-none`** - Disable interactions on overlays, loading states, or temporarily disabled elements
- **`.pe-auto`** - Re-enable interactions on child elements when parent has `pe-none`
## CSS
### Sass utilities API
Pointer events utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
```scss
"pointer-events": (
property: pointer-events,
class: pe,
values: none auto,
),
```
+2 -2
View File
@@ -112,9 +112,9 @@ Assign responsive-friendly `margin` or `padding` values to an element or a subse
### Notation
Spacing utilities that apply to all breakpoints, from `xs` to `xxl`, have no breakpoint abbreviation in them. This is because those classes are applied from `min-width: 0` and up, and thus are not bound by a media query. The remaining breakpoints, however, do include a breakpoint abbreviation.
Spacing utilities that apply to all breakpoints, from `xs` to `2xl`, have no breakpoint abbreviation in them. This is because those classes are applied from `min-width: 0` and up, and thus are not bound by a media query. The remaining breakpoints, however, do include a breakpoint abbreviation.
The classes are named using the format `{property}{sides}-{size}` for `xs` and `{property}{sides}-{breakpoint}-{size}` for `sm`, `md`, `lg`, `xl`, and `xxl`.
The classes are named using the format `{property}{sides}-{size}` for `xs` and `{property}{sides}-{breakpoint}-{size}` for `sm`, `md`, `lg`, `xl`, and `2xl`.
Where *property* is one of:
@@ -0,0 +1,73 @@
---
title: Text alignment
description: Easily realign text with text alignment utilities for start, end, and center alignment.
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/text-align
reference:
- class: text-start
styles:
text-align: 'left'
- class: text-center
styles:
text-align: 'center'
- class: text-end
styles:
text-align: 'right'
---
import { getData } from '@libs/data'
## Overview
Easily realign text to components with text alignment classes. For start, end, and center alignment, responsive classes are available that use the same viewport width breakpoints as the grid system.
## Basic usage
<Example code={`<p class="text-start">Start aligned text on all viewport sizes.</p>
<p class="text-center">Center aligned text on all viewport sizes.</p>
<p class="text-end">End aligned text on all viewport sizes.</p>
<p class="text-sm-end">End aligned text on viewports sized SM (small) or wider.</p>
<p class="text-md-end">End aligned text on viewports sized MD (medium) or wider.</p>
<p class="text-lg-end">End aligned text on viewports sized LG (large) or wider.</p>
<p class="text-xl-end">End aligned text on viewports sized XL (extra large) or wider.</p>
<p class="text-xxl-end">End aligned text on viewports sized XXL (extra extra large) or wider.</p>`} />
<Callout>
Note that we don't provide utility classes for justified text. While, aesthetically, justified text might look more appealing, it does make word-spacing more random and therefore harder to read.
</Callout>
## Responsive
Responsive variations also exist for `text-align`.
<ul>
{getData('breakpoints').map((breakpoint) => {
return (
<Fragment>
<li><code>.text{breakpoint.abbr}-start</code></li>
<li><code>.text{breakpoint.abbr}-center</code></li>
<li><code>.text{breakpoint.abbr}-end</code></li>
</Fragment>
)
})}
</ul>
## CSS
### Sass utilities API
Text alignment utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
```scss
"text-align": (
responsive: true,
property: text-align,
class: text,
values: (
start: left,
end: right,
center: center,
)
),
```
@@ -0,0 +1,69 @@
---
title: Text decoration
description: Utilities for controlling text decoration, text transform, and text color reset.
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration
reference:
- class: text-decoration-underline
styles:
text-decoration: 'underline'
- class: text-decoration-line-through
styles:
text-decoration: 'line-through'
- class: text-decoration-none
styles:
text-decoration: 'none'
- class: text-lowercase
styles:
text-transform: 'lowercase'
- class: text-uppercase
styles:
text-transform: 'uppercase'
- class: text-capitalize
styles:
text-transform: 'capitalize'
---
## Text decoration
Decorate text in components with text decoration classes.
<Example code={`<p class="text-decoration-underline">This text has a line underneath it.</p>
<p class="text-decoration-line-through">This text has a line going through it.</p>
<a href="#" class="text-decoration-none">This link has its text decoration removed</a>`} />
## Text transform
Transform text in components with our text capitalization classes: `text-lowercase`, `text-uppercase` or `text-capitalize`.
<Example code={`<p class="text-lowercase">Lowercased text.</p>
<p class="text-uppercase">Uppercased text.</p>
<p class="text-capitalize">CapiTaliZed text.</p>`} />
Note how `.text-capitalize` only changes the first letter of each word, leaving the case of any other letters unaffected.
## Reset color
Reset a text or link's color with `.text-reset`, so that it inherits the color from its parent.
<Example code={`<p class="text-body-secondary">
Secondary body text with a <a href="#" class="text-reset">reset link</a>.
</p>`} />
## CSS
### Sass utilities API
Text decoration utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
```scss
"text-decoration": (
property: text-decoration,
values: none underline line-through
),
"text-transform": (
property: text-transform,
class: text,
values: lowercase uppercase capitalize
),
```
@@ -0,0 +1,64 @@
---
title: Text wrapping
description: Utilities for controlling text wrapping, overflow, and word breaking behavior.
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/white-space
reference:
- class: text-wrap
styles:
white-space: 'normal'
- class: text-nowrap
styles:
white-space: 'nowrap'
- class: text-break
styles:
word-wrap: 'break-word'
word-break: 'break-word'
---
## Text wrapping and overflow
Wrap text with a `.text-wrap` class.
<Example code={`<div class="badge text-bg-primary text-wrap" style="width: 6rem;">
This text should wrap.
</div>`} />
Prevent text from wrapping with a `.text-nowrap` class.
<Example code={`<div class="text-nowrap bg-body-secondary border" style="width: 8rem;">
This text should overflow the parent.
</div>`} />
## Word break
Prevent long strings of text from breaking your components' layout by using `.text-break` to set `word-wrap: break-word` and `word-break: break-word`. We use `word-wrap` instead of the more common `overflow-wrap` for wider browser support, and add the deprecated `word-break: break-word` to avoid issues with flex containers.
<Example code={`<p class="text-break">mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm</p>`} />
<Callout type="warning">
Note that [breaking words isn't possible in Arabic](https://rtlstyling.com/posts/rtl-styling#3.-line-break), which is the most used RTL language. Therefore `.text-break` is removed from our RTL compiled CSS.
</Callout>
## CSS
### Sass utilities API
Text wrapping utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
```scss
"white-space": (
property: white-space,
class: text,
values: (
wrap: normal,
nowrap: nowrap,
)
),
"word-wrap": (
property: word-wrap word-break,
class: text,
values: (break: break-word),
rtl: false
),
```
+1 -1
View File
@@ -114,7 +114,7 @@ Easily realign text to components with text alignment classes. For start, end, a
<p class="text-md-end">End aligned text on viewports sized MD (medium) or wider.</p>
<p class="text-lg-end">End aligned text on viewports sized LG (large) or wider.</p>
<p class="text-xl-end">End aligned text on viewports sized XL (extra large) or wider.</p>
<p class="text-xxl-end">End aligned text on viewports sized XXL (extra extra large) or wider.</p>`} />
<p class="text-2xl-end">End aligned text on viewports sized 2XL (extra extra large) or wider.</p>`} />
<Callout>
Note that we dont provide utility classes for justified text. While, aesthetically, justified text might look more appealing, it does make word-spacing more random and therefore harder to read.
@@ -0,0 +1,49 @@
---
title: User select
description: Control how users can select text content with user-select utilities.
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/user-select
reference:
- class: user-select-all
styles:
user-select: 'all'
- class: user-select-auto
styles:
user-select: 'auto'
- class: user-select-none
styles:
user-select: 'none'
---
## Overview
Change the way in which the content is selected when the user interacts with it using user-select utilities.
## Basic usage
<Example code={`<p class="user-select-all">This paragraph will be entirely selected when clicked by the user.</p>
<p class="user-select-auto">This paragraph has default select behavior.</p>
<p class="user-select-none">This paragraph will not be selectable when clicked by the user.</p>`} />
## Use cases
- **`.user-select-all`** - Useful for code snippets, IDs, or other content users might want to copy entirely
- **`.user-select-auto`** - Default browser behavior, allows normal text selection
- **`.user-select-none`** - Prevents text selection, useful for UI elements, buttons, or decorative text
<Callout>
**Accessibility note:** Be careful when using `user-select: none` as it can interfere with assistive technologies and keyboard navigation. Ensure that important content remains accessible through other means.
</Callout>
## CSS
### Sass utilities API
User select utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
```scss
"user-select": (
property: user-select,
values: all auto none
),
```
+144
View File
@@ -0,0 +1,144 @@
---
title: Width
description: Use width utilities to control the width of elements with responsive width classes.
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/width
reference:
- class: w-25
styles:
width: '25%'
- class: w-50
styles:
width: '50%'
- class: w-75
styles:
width: '75%'
- class: w-100
styles:
width: '100%'
- class: w-auto
styles:
width: 'auto'
- class: w-min
styles:
width: 'min-content'
- class: w-max
styles:
width: 'max-content'
- class: w-fit
styles:
width: 'fit-content'
- class: max-w-100
styles:
max-width: '100%'
- class: min-w-0
styles:
min-width: '0'
- class: min-w-100
styles:
min-width: '100%'
- class: vw-100
styles:
width: '100vw'
- class: min-vw-100
styles:
min-width: '100vw'
---
## Overview
Use width utilities to set the width of elements. Width utilities are generated from the utility API and include support for percentage values, intrinsic sizing keywords, and viewport units.
## Relative width
Set width relative to the parent element using percentage-based utilities. Includes support for `25%`, `50%`, `75%`, `100%`, and `auto` by default.
<Example class="bd-example-flex" code={`<div class="w-25 p-3">Width 25%</div>
<div class="w-50 p-3">Width 50%</div>
<div class="w-75 p-3">Width 75%</div>
<div class="w-100 p-3">Width 100%</div>
<div class="w-auto p-3">Width auto</div>`} />
## Intrinsic sizing
Use intrinsic sizing keywords to set width based on content.
<Example class="bd-example-flex" code={`<div class="w-min p-3">Width min-content</div>
<div class="w-max p-3">Width max-content</div>
<div class="w-fit p-3">Width fit-content</div>`} />
## Max width
Set maximum width using `max-width` utilities.
<Example class="bd-example-flex" code={`<div style="width: 50%;">
<div class="max-w-100" style="width: 200%;">Max-width 100%</div>
</div>`} />
## Min width
Set minimum width using `min-width` utilities.
<Example class="bd-example-flex" code={`<div class="min-w-0 p-3" style="overflow: hidden;">
<div style="width: 200px;">This content is wider than the min-width: 0 container</div>
</div>
<div class="min-w-100 p-3">Min-width 100%</div>`} />
## Viewport width
Set width relative to the viewport using viewport units.
```html
<div class="vw-100">Width 100vw</div>
<div class="min-vw-100">Min-width 100vw</div>
```
<Callout type="warning">
**Beware of the viewport width!** Using `vw-100` can cause horizontal scrollbars if the content is wider than the viewport, particularly on smaller screens.
</Callout>
## CSS
### Sass utilities API
Width utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
```scss
"width": (
property: width,
class: w,
values: (
25: 25%,
50: 50%,
75: 75%,
100: 100%,
auto: auto,
min: min-content,
max: max-content,
fit: fit-content,
)
),
"max-width": (
property: max-width,
class: max-w,
values: (100: 100%)
),
"min-width": (
property: min-width,
class: min-w,
values: (
0: 0,
100: 100%
)
),
"viewport-width": (
property: width,
class: vw,
values: (100: 100vw)
),
"min-viewport-width": (
property: min-width,
class: min-vw,
values: (100: 100vw)
),
```
+3 -3
View File
@@ -29,9 +29,9 @@ const configSchema = z.object({
js_hash: z.string(),
js_bundle: z.string().url(),
js_bundle_hash: z.string(),
popper: z.string().url(),
popper_esm: z.string().url(),
popper_hash: z.string()
floating_ui: z.string().url(),
floating_ui_esm: z.string().url(),
floating_ui_hash: z.string()
}),
current_version: zVersionSemver,
current_ruby_version: zVersionSemver,
+10 -3
View File
@@ -82,7 +82,14 @@ const dataDefinitions = {
icon_color: z.string().optional(),
pages: z
.object({
title: z.string()
title: z.string().optional(),
group: z.string().optional(),
pages: z
.object({
title: z.string()
})
.array()
.optional()
})
.array()
.optional()
@@ -117,7 +124,7 @@ let data = new Map<DataType, z.infer<DataSchema>>()
export function getData<TType extends DataType>(type: TType): z.infer<(typeof dataDefinitions)[TType]> {
if (data.has(type)) {
// Returns the data if it has already been loaded.
return data.get(type)
return data.get(type) as z.infer<(typeof dataDefinitions)[TType]>
}
const dataPath = `./site/data/${type}.yml`
@@ -127,7 +134,7 @@ export function getData<TType extends DataType>(type: TType): z.infer<(typeof da
const rawData = yaml.load(fs.readFileSync(dataPath, 'utf8'))
// Parse the data using the data schema to validate its content and get back a fully typed data object.
const parsedData = dataDefinitions[type].parse(rawData)
const parsedData = dataDefinitions[type].parse(rawData) as z.infer<(typeof dataDefinitions)[TType]>
// Cache the data.
data.set(type, parsedData)
+349 -347
View File
@@ -9,392 +9,394 @@
// Docs examples
//
.bd-code-snippet {
margin: 0 ($bd-gutter-x * -.5) 1rem;
border: solid var(--bs-border-color);
border-width: 1px 0;
@layer custom {
.bd-code-snippet {
margin: 0 ($bd-gutter-x * -.5) 1rem;
border: solid var(--bs-border-color);
border-width: 1px 0;
@include media-breakpoint-up(md) {
margin-right: 0;
margin-left: 0;
border-width: 1px;
@include border-radius(var(--bs-border-radius));
}
}
.bd-example {
--bd-example-padding: 1rem;
position: relative;
display: flow-root;
padding: var(--bd-example-padding);
margin: 0 ($bd-gutter-x * -.5) 1rem;
border: solid var(--bs-border-color);
border-width: 1px 0;
@include media-breakpoint-up(md) {
--bd-example-padding: 1.5rem;
margin-right: 0;
margin-left: 0;
border-width: 1px;
@include border-radius(var(--bs-border-radius));
@include media-breakpoint-up(md) {
margin-right: 0;
margin-left: 0;
border-width: 1px;
@include border-radius(var(--bs-border-radius));
}
}
+ p {
margin-top: 2rem;
}
.bd-example {
--bd-example-padding: 1rem;
> .form-control {
+ .form-control {
position: relative;
display: flow-root;
padding: var(--bd-example-padding);
margin: 0 ($bd-gutter-x * -.5) 1rem;
border: solid var(--bs-border-color);
border-width: 1px 0;
@include media-breakpoint-up(md) {
--bd-example-padding: 1.5rem;
margin-right: 0;
margin-left: 0;
border-width: 1px;
@include border-radius(var(--bs-border-radius));
}
+ p {
margin-top: 2rem;
}
> .form-control {
+ .form-control {
margin-top: .5rem;
}
}
> .nav + .nav,
> .alert + .alert,
> .navbar + .navbar,
> .progress + .progress {
margin-top: $spacer;
}
> .dropdown-menu {
position: static;
display: block;
}
> :last-child,
> nav:last-child .breadcrumb {
margin-bottom: 0;
}
> hr:last-child {
margin-bottom: $spacer;
}
// Images
> svg + svg,
> img + img {
margin-left: .5rem;
}
// Buttons
> .btn,
> .btn-group {
margin: .25rem .125rem;
}
> .btn-toolbar + .btn-toolbar {
margin-top: .5rem;
}
// List groups
> .list-group {
max-width: 400px;
}
> [class*="list-group-horizontal"] {
max-width: 100%;
}
// Navbars
.fixed-top,
.sticky-top {
position: static;
margin: calc(-1 * var(--bd-example-padding)) calc(-1 * var(--bd-example-padding)) var(--bd-example-padding);
}
.fixed-bottom,
.sticky-bottom {
position: static;
margin: var(--bd-example-padding) calc(-1 * var(--bd-example-padding)) calc(-1 * var(--bd-example-padding));
}
// Pagination
.pagination {
margin-bottom: 0;
}
}
> .nav + .nav,
> .alert + .alert,
> .navbar + .navbar,
> .progress + .progress {
margin-top: $spacer;
//
// Grid examples
//
.bd-example-row [class^="col"],
.bd-example-cols [class^="col"] > *,
.bd-example-cssgrid [class*="grid"] > * {
padding-top: .75rem;
padding-bottom: .75rem;
background-color: color-mix(in srgb, var(--bd-violet) 15%, transparent);
border: 1px solid color-mix(in srgb, var(--bd-violet) 30%, transparent);
}
> .dropdown-menu {
position: static;
display: block;
.bd-example-row .row + .row,
.bd-example-cssgrid .grid + .grid {
margin-top: 1rem;
}
> :last-child,
> nav:last-child .breadcrumb {
margin-bottom: 0;
}
> hr:last-child {
margin-bottom: $spacer;
}
// Images
> svg + svg,
> img + img {
margin-left: .5rem;
}
// Buttons
> .btn,
> .btn-group {
margin: .25rem .125rem;
}
> .btn-toolbar + .btn-toolbar {
margin-top: .5rem;
}
// List groups
> .list-group {
max-width: 400px;
}
> [class*="list-group-horizontal"] {
max-width: 100%;
}
// Navbars
.fixed-top,
.sticky-top {
position: static;
margin: calc(-1 * var(--bd-example-padding)) calc(-1 * var(--bd-example-padding)) var(--bd-example-padding);
}
.fixed-bottom,
.sticky-bottom {
position: static;
margin: var(--bd-example-padding) calc(-1 * var(--bd-example-padding)) calc(-1 * var(--bd-example-padding));
}
// Pagination
.pagination {
margin-bottom: 0;
}
}
//
// Grid examples
//
.bd-example-row [class^="col"],
.bd-example-cols [class^="col"] > *,
.bd-example-cssgrid [class*="grid"] > * {
padding-top: .75rem;
padding-bottom: .75rem;
background-color: color-mix(in srgb, var(--bd-violet) 15%, transparent);
border: 1px solid color-mix(in srgb, var(--bd-violet) 30%, transparent);
}
.bd-example-row .row + .row,
.bd-example-cssgrid .grid + .grid {
margin-top: 1rem;
}
.bd-example-row-flex-cols .row {
min-height: 10rem;
background-color: color-mix(in srgb, var(--bd-violet) 15%, transparent);
}
.bd-example-flex div:not(.vr) {
background-color: color-mix(in srgb, var(--bd-violet) 15%, transparent);
border: 1px solid color-mix(in srgb, var(--bd-violet) 30%, transparent);
}
// // Grid mixins
// .example-container {
// width: 800px;
// @include make-container();
// }
// .example-row {
// @include make-row();
// }
// .example-content-main {
// @include make-col-ready();
// @include media-breakpoint-up(sm) {
// @include make-col(6);
// }
// @include media-breakpoint-up(lg) {
// @include make-col(8);
// }
// }
// .example-content-secondary {
// @include make-col-ready();
// @include media-breakpoint-up(sm) {
// @include make-col(6);
// }
// @include media-breakpoint-up(lg) {
// @include make-col(4);
// }
// }
// Ratio helpers
.bd-example-ratios {
[class*="ratio"] {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 1rem;
color: var(--bs-secondary-color);
background-color: var(--bs-tertiary-bg);
border: var(--bs-border-width) solid var(--bs-border-color);
@include border-radius(var(--bs-border-radius));
}
}
.bd-example-offcanvas {
.offcanvas {
position: static;
display: block;
height: 200px;
visibility: visible;
transform: translate(0);
}
}
// Tooltips
.tooltip-demo {
a {
white-space: nowrap;
}
.btn {
margin: .25rem .125rem;
}
}
// scss-docs-start custom-tooltip
.custom-tooltip {
--bs-tooltip-bg: var(--bd-violet-bg);
--bs-tooltip-color: var(--bs-white);
}
// scss-docs-end custom-tooltip
// scss-docs-start custom-popovers
.custom-popover {
--bs-popover-max-width: 200px;
--bs-popover-border-color: var(--bd-violet-bg);
--bs-popover-header-bg: var(--bd-violet-bg);
--bs-popover-header-color: var(--bs-white);
--bs-popover-body-padding-x: 1rem;
--bs-popover-body-padding-y: .5rem;
}
// scss-docs-end custom-popovers
// Scrollspy demo on fixed height div
.scrollspy-example {
height: 200px;
margin-top: .5rem;
overflow: auto;
}
.scrollspy-example-2 {
height: 350px;
overflow: auto;
}
.simple-list-example-scrollspy {
.active {
.bd-example-row-flex-cols .row {
min-height: 10rem;
background-color: color-mix(in srgb, var(--bd-violet) 15%, transparent);
}
}
.bd-example-border-utils {
[class^="border"] {
display: inline-block;
width: 5rem;
height: 5rem;
margin: .25rem;
background-color: var(--bs-tertiary-bg);
.bd-example-flex div:not(.vr) {
background-color: color-mix(in srgb, var(--bd-violet) 15%, transparent);
border: 1px solid color-mix(in srgb, var(--bd-violet) 30%, transparent);
}
}
.bd-example-rounded-utils {
[class*="rounded"] {
margin: .25rem;
// // Grid mixins
// .example-container {
// width: 800px;
// @include make-container();
// }
// .example-row {
// @include make-row();
// }
// .example-content-main {
// @include make-col-ready();
// @include media-breakpoint-up(sm) {
// @include make-col(6);
// }
// @include media-breakpoint-up(lg) {
// @include make-col(8);
// }
// }
// .example-content-secondary {
// @include make-col-ready();
// @include media-breakpoint-up(sm) {
// @include make-col(6);
// }
// @include media-breakpoint-up(lg) {
// @include make-col(4);
// }
// }
// Ratio helpers
.bd-example-ratios {
[class*="ratio"] {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 1rem;
color: var(--bs-secondary-color);
background-color: var(--bs-tertiary-bg);
border: var(--bs-border-width) solid var(--bs-border-color);
@include border-radius(var(--bs-border-radius));
}
}
}
.bd-example-position-utils {
position: relative;
padding: 2rem;
.position-relative {
.bd-example-offcanvas {
.offcanvas {
position: static;
display: block;
height: 200px;
visibility: visible;
transform: translate(0);
}
}
// Tooltips
.tooltip-demo {
a {
white-space: nowrap;
}
.btn {
margin: .25rem .125rem;
}
}
// scss-docs-start custom-tooltip
.custom-tooltip {
--bs-tooltip-bg: var(--bd-violet-bg);
--bs-tooltip-color: var(--bs-white);
}
// scss-docs-end custom-tooltip
// scss-docs-start custom-popovers
.custom-popover {
--bs-popover-max-width: 200px;
--bs-popover-border-color: var(--bd-violet-bg);
--bs-popover-header-bg: var(--bd-violet-bg);
--bs-popover-header-color: var(--bs-white);
--bs-popover-body-padding-x: 1rem;
--bs-popover-body-padding-y: .5rem;
}
// scss-docs-end custom-popovers
// Scrollspy demo on fixed height div
.scrollspy-example {
height: 200px;
background-color: var(--bs-tertiary-bg);
margin-top: .5rem;
overflow: auto;
}
.position-absolute {
width: 2rem;
height: 2rem;
background-color: var(--bs-body-color);
@include border-radius();
}
}
.bd-example-position-examples {
&::after {
content: none;
}
}
// Placeholders
.bd-example-placeholder-cards {
&::after {
display: none;
.scrollspy-example-2 {
height: 350px;
overflow: auto;
}
.card {
width: 18rem;
}
}
// Toasts
.bd-example-toasts {
min-height: 240px;
}
.bd-example-zindex-levels {
min-height: 15rem;
> div {
color: var(--bs-body-bg);
background-color: var(--bd-violet);
border: 1px solid var(--bd-purple);
> span {
position: absolute;
right: 5px;
bottom: 0;
.simple-list-example-scrollspy {
.active {
background-color: color-mix(in srgb, var(--bd-violet) 15%, transparent);
}
}
> :nth-child(2) {
top: 3rem;
left: 3rem;
}
> :nth-child(3) {
top: 4.5rem;
left: 4.5rem;
}
> :nth-child(4) {
top: 6rem;
left: 6rem;
}
> :nth-child(5) {
top: 7.5rem;
left: 7.5rem;
}
}
//
// Code snippets
//
.highlight {
position: relative;
padding: .75rem ($bd-gutter-x * .5);
background-color: var(--bd-pre-bg);
@include media-breakpoint-up(md) {
padding: .75rem 1.25rem;
@include border-radius(calc(var(--bs-border-radius) - 1px));
}
@include media-breakpoint-up(lg) {
pre {
margin-right: 1.875rem;
.bd-example-border-utils {
[class^="border"] {
display: inline-block;
width: 5rem;
height: 5rem;
margin: .25rem;
background-color: var(--bs-tertiary-bg);
}
}
pre {
padding: .25rem 0 .875rem;
margin-top: .8125rem;
margin-bottom: 0;
overflow: overlay;
white-space: pre;
background-color: transparent;
border: 0;
.bd-example-rounded-utils {
[class*="rounded"] {
margin: .25rem;
}
}
pre code {
@include font-size(inherit);
color: var(--bs-body-color); // Effectively the base text color
word-wrap: normal;
.bd-example-position-utils {
position: relative;
padding: 2rem;
.position-relative {
height: 200px;
background-color: var(--bs-tertiary-bg);
}
.position-absolute {
width: 2rem;
height: 2rem;
background-color: var(--bs-body-color);
@include border-radius();
}
}
}
.bd-example-snippet .highlight pre {
margin-right: 0;
}
.highlight-toolbar {
background-color: var(--bd-pre-bg);
+ .highlight {
@include border-top-radius(0);
.bd-example-position-examples {
&::after {
content: none;
}
}
}
.bd-file-ref {
.highlight-toolbar {
// Placeholders
.bd-example-placeholder-cards {
&::after {
display: none;
}
.card {
width: 18rem;
}
}
// Toasts
.bd-example-toasts {
min-height: 240px;
}
.bd-example-zindex-levels {
min-height: 15rem;
> div {
color: var(--bs-body-bg);
background-color: var(--bd-violet);
border: 1px solid var(--bd-purple);
> span {
position: absolute;
right: 5px;
bottom: 0;
}
}
> :nth-child(2) {
top: 3rem;
left: 3rem;
}
> :nth-child(3) {
top: 4.5rem;
left: 4.5rem;
}
> :nth-child(4) {
top: 6rem;
left: 6rem;
}
> :nth-child(5) {
top: 7.5rem;
left: 7.5rem;
}
}
//
// Code snippets
//
.highlight {
position: relative;
padding: .75rem ($bd-gutter-x * .5);
background-color: var(--bd-pre-bg);
@include media-breakpoint-up(md) {
@include border-top-radius(calc(var(--bs-border-radius) - 1px));
padding: .75rem 1.25rem;
@include border-radius(calc(var(--bs-border-radius) - 1px));
}
@include media-breakpoint-up(lg) {
pre {
margin-right: 1.875rem;
}
}
pre {
padding: .25rem 0 .875rem;
margin-top: .8125rem;
margin-bottom: 0;
overflow: overlay;
white-space: pre;
background-color: transparent;
border: 0;
}
pre code {
@include font-size(inherit);
color: var(--bs-body-color); // Effectively the base text color
word-wrap: normal;
}
}
}
.bd-content .bd-code-snippet {
margin-bottom: 1rem;
.bd-example-snippet .highlight pre {
margin-right: 0;
}
.highlight-toolbar {
background-color: var(--bd-pre-bg);
+ .highlight {
@include border-top-radius(0);
}
}
.bd-file-ref {
.highlight-toolbar {
@include media-breakpoint-up(md) {
@include border-top-radius(calc(var(--bs-border-radius) - 1px));
}
}
}
.bd-content .bd-code-snippet {
margin-bottom: 1rem;
}
}
+5
View File
@@ -28,6 +28,11 @@
color: var(--bs-emphasis-color);
}
.bd-links-subgroup {
margin-left: 1.625rem;
color: var(--bs-emphasis-color);
}
.bd-links-nav {
// @include media-breakpoint-down(lg) {
// font-size: .875rem;
+1 -1
View File
@@ -24,7 +24,7 @@ $bd-callout-variants: info, warning, danger !default;
// --bd-teal-rgb: #{to-rgb($teal-500)};
--bd-violet-bg: var(--bd-violet);
--bd-toc-color: light-dark(var(--bd-violet), var(--bs-indigo-300));
--bd-sidebar-link-bg: color-mix(in srgb, var(--bd-violet), transparent 90%);
--bd-sidebar-link-bg: light-dark(color-mix(in srgb, var(--bd-violet), transparent 90%), color-mix(in srgb, var(--bd-violet), transparent 70%));
--bd-callout-link: #{$blue-600};
--bd-callout-code-color: light-dark(var(--bs-pink-600), var(--bs-pink-300));
--bd-pre-bg: light-dark(var(--bs-gray-100), color-mix(in srgb, var(--bs-gray-900), var(--bs-black) 25%));