* Split font utilities, update API to do more pseudo classes, drop display type classes
* Improve display docs, remove print display utils
* Document gap and grid utils, rename a couple classes
* better url
* Fix color-mix
* Undo utilities API change for now
* fix api changes
* Bundlewatch
* Linter cleanup
* Massive utilities update
- Split several utilities across smaller pages
- New underline thickness utility
- Updated text-wrap utility to use `text-wrap` property, removes white-space utils
- Adds a dozen new width utilities for now—TBD if we keep this, they're not documented yet
- Redoes the color utilities—color, background color, border color, link color—to use color-mix without attribute selectors. Faster, simpler, better support for overriding other components.
- Redesigns margin, padding, gap utils pages—shoutout Tailwind for having a better visualization here. Cribbed their approach to emphasize spacing utilities.
- Fixed up a lot of usages of color utilities, likely more to do
- Fixed up a lot of broken links, probably also more to do
* New details component, simpler a11y color contrast warning, updated docs bottom nav, updated ref tables
* Avoid name collision, update to demo thickness hover
* Rename $new-font-sizes to $font-sizes
* Update width and height docs
* Few cleanup tweaks
* Remove unused attribute selector for borders
* Fixes
* more bundle
* fixes
* spelling
* add json
},
{
"path": "./dist/css/bootstrap-reboot.css",
- "maxSize": "5.25 kB"
+ "maxSize": "5.5 kB"
},
{
"path": "./dist/css/bootstrap-reboot.min.css",
},
{
"path": "./dist/css/bootstrap-utilities.css",
- "maxSize": "14.0 kB"
+ "maxSize": "15.0 kB"
},
{
"path": "./dist/css/bootstrap-utilities.min.css",
- "maxSize": "12.25 kB"
+ "maxSize": "13.25 kB"
},
{
"path": "./dist/css/bootstrap.css",
"favicons",
"fieldsets",
"flexbox",
+ "frontmatter",
"fullscreen",
"getbootstrap",
"Grayscale",
--- /dev/null
+#!/usr/bin/env node
+
+/**
+ * Generate utilities metadata JSON from Sass
+ * This script compiles a special Sass file that outputs utility information as CSS comments,
+ * then extracts and saves it as JSON for documentation use.
+ */
+
+import { readFileSync, writeFileSync, unlinkSync } from 'node:fs'
+import { execSync } from 'node:child_process'
+import { fileURLToPath } from 'node:url'
+import path from 'node:path'
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url))
+const rootDir = path.join(__dirname, '..')
+
+// Compile the metadata generator SCSS file
+console.log('Compiling utilities metadata...')
+
+try {
+ execSync(
+ 'sass --style expanded --no-source-map build/generate-utilities-metadata.scss:dist/css/utilities-metadata.tmp.css',
+ { cwd: rootDir, stdio: 'inherit' }
+ )
+} catch {
+ console.error('Failed to compile metadata SCSS')
+ process.exit(1)
+}
+
+// Read the compiled CSS
+const cssPath = path.join(rootDir, 'dist/css/utilities-metadata.tmp.css')
+const cssContent = readFileSync(cssPath, 'utf8')
+
+// Extract JSON from the CSS comment
+const startMarker = 'BOOTSTRAP-UTILITIES-METADATA-START'
+const endMarker = 'BOOTSTRAP-UTILITIES-METADATA-END'
+
+const startIndex = cssContent.indexOf(startMarker)
+const endIndex = cssContent.indexOf(endMarker)
+
+if (startIndex === -1 || endIndex === -1) {
+ console.error('Could not find metadata markers in compiled CSS')
+ process.exit(1)
+}
+
+// Extract JSON content between markers
+const jsonContent = cssContent
+ .slice(startIndex + startMarker.length, endIndex)
+ .trim()
+
+// Validate JSON
+try {
+ const parsed = JSON.parse(jsonContent)
+ console.log(`✓ Extracted metadata for ${Object.keys(parsed.utilities).length} utilities`)
+
+ // Write to JSON file
+ const outputPath = path.join(rootDir, 'dist/css/bootstrap-utilities.metadata.json')
+ writeFileSync(outputPath, JSON.stringify(parsed, null, 2))
+ console.log(`✓ Wrote metadata to ${outputPath}`)
+
+ // Clean up temporary CSS files (including RTL variants that may have been generated)
+ try {
+ unlinkSync(cssPath)
+ } catch {
+ // File may not exist
+ }
+
+ // Also clean up any RTL variants that postcss may have created
+ const rtlFiles = [
+ 'dist/css/utilities-metadata.tmp.rtl.css',
+ 'dist/css/utilities-metadata.tmp.rtl.css.map',
+ 'dist/css/utilities-metadata.tmp.rtl.min.css',
+ 'dist/css/utilities-metadata.tmp.rtl.min.css.map',
+ 'dist/css/utilities-metadata.tmp.min.css',
+ 'dist/css/utilities-metadata.tmp.min.css.map'
+ ]
+
+ for (const file of rtlFiles) {
+ try {
+ unlinkSync(path.join(rootDir, file))
+ } catch {
+ // File may not exist, ignore
+ }
+ }
+
+ console.log('✓ Cleaned up temporary files')
+} catch (error) {
+ console.error('Failed to parse extracted JSON:', error.message)
+ console.error('Extracted content:', jsonContent.slice(0, 500))
+ process.exit(1)
+}
--- /dev/null
+// Generate utilities metadata JSON for documentation
+// This file is compiled to extract utility information without generating CSS
+
+@use "sass:map";
+@use "sass:list";
+@use "sass:string";
+@use "sass:meta";
+@use "../scss/config" as *;
+@use "../scss/colors" as *;
+@use "../scss/variables" as *;
+@use "../scss/functions" as *;
+@use "../scss/theme" as *;
+@use "../scss/utilities" as *;
+
+// Access the utilities map
+$utilities-map: $utilities !default;
+
+// Start JSON output
+$json: '{"utilities":{' !default;
+
+$utility-count: 0 !default;
+$total-utilities: list.length(map.keys($utilities-map)) !default;
+
+@each $key, $utility in $utilities-map {
+ $utility-count: $utility-count + 1;
+
+ // Skip if utility is null or false (disabled)
+ @if $utility {
+ // Extract class prefix
+ $class: if(map.has-key($utility, "class"), map.get($utility, "class"), $key);
+
+ // Extract property
+ $property: if(map.has-key($utility, "property"), map.get($utility, "property"), null);
+
+ // Extract values
+ $values: if(map.has-key($utility, "values"), map.get($utility, "values"), null);
+
+ // Generate class list
+ $classes: "";
+ @if $values {
+ @if meta.type-of($values) == "map" {
+ $value-keys: map.keys($values);
+ $first: true;
+ @each $value-key in $value-keys {
+ @if not $first {
+ $classes: $classes + ", ";
+ }
+ $class-name: if($value-key == "null" or $value-key == null, $class, "#{$class}-#{$value-key}");
+ $classes: $classes + '"' + $class-name + '"';
+ $first: false;
+ }
+ } @else if meta.type-of($values) == "list" {
+ $first: true;
+ @each $value in $values {
+ @if not $first {
+ $classes: $classes + ", ";
+ }
+ $class-name: "#{$class}-#{$value}";
+ $classes: $classes + '"' + $class-name + '"';
+ $first: false;
+ }
+ }
+ }
+
+ // Build JSON entry
+ $json: $json + '"' + $key + '":{"class":"' + $class + '"';
+
+ @if $property {
+ @if meta.type-of($property) == "string" {
+ $json: $json + ',"property":"' + $property + '"';
+ } @else if meta.type-of($property) == "list" {
+ $property-str: "";
+ $first: true;
+ @each $prop in $property {
+ @if not $first {
+ $property-str: $property-str + " ";
+ }
+ $property-str: $property-str + $prop;
+ $first: false;
+ }
+ $json: $json + ',"property":"' + $property-str + '"';
+ }
+ // Skip map properties as they're complex and don't translate to JSON well
+ }
+
+ @if $classes != "" {
+ $json: $json + ',"classes":[' + $classes + "]";
+ } @else {
+ $json: $json + ',"classes":[]';
+ }
+
+ $json: $json + "}";
+
+ @if $utility-count < $total-utilities {
+ $json: $json + ",";
+ }
+ }
+}
+
+// stylelint-disable-next-line scss/dollar-variable-default
+$json: $json + "}}";
+
+// Output as CSS comment so it appears in compiled file
+
+/*! BOOTSTRAP-UTILITIES-METADATA-START
+#{$json}
+BOOTSTRAP-UTILITIES-METADATA-END */
+
+// Prevent any actual CSS output
+.bootstrap-utilities-metadata-generator {
+ content: "This file should not generate CSS, only metadata comments";
+}
--- /dev/null
+{
+ "utilities": {
+ "align": {
+ "class": "align",
+ "property": "vertical-align",
+ "classes": [
+ "align-baseline",
+ "align-top",
+ "align-middle",
+ "align-bottom",
+ "align-text-bottom",
+ "align-text-top"
+ ]
+ },
+ "aspect-ratio-attr": {
+ "class": "ratio-",
+ "property": "aspect-ratio",
+ "classes": []
+ },
+ "aspect-ratio": {
+ "class": "ratio",
+ "property": "--bs-ratio",
+ "classes": [
+ "ratio-auto",
+ "ratio-1x1",
+ "ratio-4x3",
+ "ratio-16x9",
+ "ratio-21x9"
+ ]
+ },
+ "float": {
+ "class": "float",
+ "property": "float",
+ "classes": [
+ "float-start",
+ "float-end",
+ "float-none"
+ ]
+ },
+ "object-fit": {
+ "class": "object-fit",
+ "property": "object-fit",
+ "classes": [
+ "object-fit-contain",
+ "object-fit-cover",
+ "object-fit-fill",
+ "object-fit-scale",
+ "object-fit-none"
+ ]
+ },
+ "opacity": {
+ "class": "opacity",
+ "property": "opacity",
+ "classes": [
+ "opacity-0",
+ "opacity-25",
+ "opacity-50",
+ "opacity-75",
+ "opacity-100"
+ ]
+ },
+ "overflow": {
+ "class": "overflow",
+ "property": "overflow",
+ "classes": [
+ "overflow-auto",
+ "overflow-hidden",
+ "overflow-visible",
+ "overflow-scroll"
+ ]
+ },
+ "overflow-x": {
+ "class": "overflow-x",
+ "property": "overflow-x",
+ "classes": [
+ "overflow-x-auto",
+ "overflow-x-hidden",
+ "overflow-x-visible",
+ "overflow-x-scroll"
+ ]
+ },
+ "overflow-y": {
+ "class": "overflow-y",
+ "property": "overflow-y",
+ "classes": [
+ "overflow-y-auto",
+ "overflow-y-hidden",
+ "overflow-y-visible",
+ "overflow-y-scroll"
+ ]
+ },
+ "display": {
+ "class": "d",
+ "property": "display",
+ "classes": [
+ "d-inline",
+ "d-inline-block",
+ "d-block",
+ "d-grid",
+ "d-inline-grid",
+ "d-table",
+ "d-table-row",
+ "d-table-cell",
+ "d-flex",
+ "d-inline-flex",
+ "d-contents",
+ "d-flow-root",
+ "d-none"
+ ]
+ },
+ "shadow": {
+ "class": "shadow",
+ "property": "box-shadow",
+ "classes": [
+ "shadow",
+ "shadow-sm",
+ "shadow-lg",
+ "shadow-none"
+ ]
+ },
+ "focus-ring": {
+ "class": "focus-ring",
+ "property": "--bs-focus-ring-color",
+ "classes": [
+ "focus-ring-primary",
+ "focus-ring-accent",
+ "focus-ring-success",
+ "focus-ring-danger",
+ "focus-ring-warning",
+ "focus-ring-info",
+ "focus-ring-inverse",
+ "focus-ring-secondary"
+ ]
+ },
+ "position": {
+ "class": "position",
+ "property": "position",
+ "classes": [
+ "position-static",
+ "position-relative",
+ "position-absolute",
+ "position-fixed",
+ "position-sticky"
+ ]
+ },
+ "top": {
+ "class": "top",
+ "property": "top",
+ "classes": [
+ "top-0",
+ "top-50",
+ "top-100"
+ ]
+ },
+ "bottom": {
+ "class": "bottom",
+ "property": "bottom",
+ "classes": [
+ "bottom-0",
+ "bottom-50",
+ "bottom-100"
+ ]
+ },
+ "start": {
+ "class": "start",
+ "property": "left",
+ "classes": [
+ "start-0",
+ "start-50",
+ "start-100"
+ ]
+ },
+ "end": {
+ "class": "end",
+ "property": "right",
+ "classes": [
+ "end-0",
+ "end-50",
+ "end-100"
+ ]
+ },
+ "translate-middle": {
+ "class": "translate-middle",
+ "property": "transform",
+ "classes": [
+ "translate-middle",
+ "translate-middle-x",
+ "translate-middle-y"
+ ]
+ },
+ "border": {
+ "class": "border",
+ "property": "border",
+ "classes": [
+ "border",
+ "border-0"
+ ]
+ },
+ "border-top": {
+ "class": "border-top",
+ "property": "border-block-start",
+ "classes": [
+ "border-top",
+ "border-top-0"
+ ]
+ },
+ "border-end": {
+ "class": "border-end",
+ "property": "border-inline-end",
+ "classes": [
+ "border-end",
+ "border-end-0"
+ ]
+ },
+ "border-bottom": {
+ "class": "border-bottom",
+ "property": "border-block-end",
+ "classes": [
+ "border-bottom",
+ "border-bottom-0"
+ ]
+ },
+ "border-start": {
+ "class": "border-start",
+ "property": "border-inline-start",
+ "classes": [
+ "border-start",
+ "border-start-0"
+ ]
+ },
+ "border-y": {
+ "class": "border-y",
+ "property": "border-block",
+ "classes": [
+ "border-y",
+ "border-y-0"
+ ]
+ },
+ "border-x": {
+ "class": "border-x",
+ "property": "border-inline",
+ "classes": [
+ "border-x",
+ "border-x-0"
+ ]
+ },
+ "border-color": {
+ "class": "border",
+ "classes": [
+ "border-primary",
+ "border-accent",
+ "border-success",
+ "border-danger",
+ "border-warning",
+ "border-info",
+ "border-inverse",
+ "border-secondary",
+ "border-bg",
+ "border-body",
+ "border-muted",
+ "border-subtle",
+ "border-emphasized",
+ "border-white",
+ "border-black"
+ ]
+ },
+ "border-color-subtle": {
+ "class": "border-subtle",
+ "classes": [
+ "border-subtle-primary",
+ "border-subtle-accent",
+ "border-subtle-success",
+ "border-subtle-danger",
+ "border-subtle-warning",
+ "border-subtle-info",
+ "border-subtle-inverse",
+ "border-subtle-secondary"
+ ]
+ },
+ "border-width": {
+ "class": "border",
+ "property": "border-width",
+ "classes": [
+ "border-1",
+ "border-2",
+ "border-3",
+ "border-4",
+ "border-5"
+ ]
+ },
+ "border-opacity": {
+ "class": "border",
+ "property": "border-color",
+ "classes": [
+ "border-10",
+ "border-20",
+ "border-30",
+ "border-40",
+ "border-50",
+ "border-60",
+ "border-70",
+ "border-80",
+ "border-90",
+ "border-100"
+ ]
+ },
+ "width": {
+ "class": "w",
+ "property": "width",
+ "classes": [
+ "w-1",
+ "w-2",
+ "w-3",
+ "w-4",
+ "w-5",
+ "w-6",
+ "w-7",
+ "w-8",
+ "w-9",
+ "w-10",
+ "w-11",
+ "w-12",
+ "w-25",
+ "w-50",
+ "w-75",
+ "w-100",
+ "w-auto",
+ "w-min",
+ "w-max",
+ "w-fit"
+ ]
+ },
+ "max-width": {
+ "class": "max-w",
+ "property": "max-width",
+ "classes": [
+ "max-w-100"
+ ]
+ },
+ "min-width": {
+ "class": "min-w",
+ "property": "min-width",
+ "classes": [
+ "min-w-0",
+ "min-w-100"
+ ]
+ },
+ "viewport-width": {
+ "class": "vw",
+ "property": "width",
+ "classes": [
+ "vw-100"
+ ]
+ },
+ "min-viewport-width": {
+ "class": "min-vw",
+ "property": "min-width",
+ "classes": [
+ "min-vw-100"
+ ]
+ },
+ "height": {
+ "class": "h",
+ "property": "height",
+ "classes": [
+ "h-25",
+ "h-50",
+ "h-75",
+ "h-100",
+ "h-auto",
+ "h-min",
+ "h-max",
+ "h-fit"
+ ]
+ },
+ "max-height": {
+ "class": "max-h",
+ "property": "max-height",
+ "classes": [
+ "max-h-100"
+ ]
+ },
+ "min-height": {
+ "class": "min-h",
+ "property": "min-height",
+ "classes": [
+ "min-h-0",
+ "min-h-100"
+ ]
+ },
+ "viewport-height": {
+ "class": "vh",
+ "property": "height",
+ "classes": [
+ "vh-100"
+ ]
+ },
+ "min-viewport-height": {
+ "class": "min-vh",
+ "property": "min-height",
+ "classes": [
+ "min-vh-100"
+ ]
+ },
+ "flex": {
+ "class": "flex",
+ "property": "flex",
+ "classes": [
+ "flex-fill"
+ ]
+ },
+ "flex-direction": {
+ "class": "flex",
+ "property": "flex-direction",
+ "classes": [
+ "flex-row",
+ "flex-column",
+ "flex-row-reverse",
+ "flex-column-reverse"
+ ]
+ },
+ "flex-grow": {
+ "class": "flex",
+ "property": "flex-grow",
+ "classes": [
+ "flex-grow-0",
+ "flex-grow-1"
+ ]
+ },
+ "flex-shrink": {
+ "class": "flex",
+ "property": "flex-shrink",
+ "classes": [
+ "flex-shrink-0",
+ "flex-shrink-1"
+ ]
+ },
+ "flex-wrap": {
+ "class": "flex",
+ "property": "flex-wrap",
+ "classes": [
+ "flex-wrap",
+ "flex-nowrap",
+ "flex-wrap-reverse"
+ ]
+ },
+ "justify-content": {
+ "class": "justify-content",
+ "property": "justify-content",
+ "classes": [
+ "justify-content-start",
+ "justify-content-end",
+ "justify-content-center",
+ "justify-content-between",
+ "justify-content-around",
+ "justify-content-evenly"
+ ]
+ },
+ "justify-items": {
+ "class": "justify-items",
+ "property": "justify-items",
+ "classes": [
+ "justify-items-start",
+ "justify-items-end",
+ "justify-items-center",
+ "justify-items-stretch"
+ ]
+ },
+ "justify-self": {
+ "class": "justify-self",
+ "property": "justify-self",
+ "classes": [
+ "justify-self-start",
+ "justify-self-end",
+ "justify-self-center"
+ ]
+ },
+ "align-items": {
+ "class": "align-items",
+ "property": "align-items",
+ "classes": [
+ "align-items-start",
+ "align-items-end",
+ "align-items-center",
+ "align-items-baseline",
+ "align-items-stretch"
+ ]
+ },
+ "align-content": {
+ "class": "align-content",
+ "property": "align-content",
+ "classes": [
+ "align-content-start",
+ "align-content-end",
+ "align-content-center",
+ "align-content-between",
+ "align-content-around",
+ "align-content-stretch"
+ ]
+ },
+ "align-self": {
+ "class": "align-self",
+ "property": "align-self",
+ "classes": [
+ "align-self-auto",
+ "align-self-start",
+ "align-self-end",
+ "align-self-center",
+ "align-self-baseline",
+ "align-self-stretch"
+ ]
+ },
+ "place-items": {
+ "class": "place-items",
+ "property": "place-items",
+ "classes": [
+ "place-items-start",
+ "place-items-end",
+ "place-items-center",
+ "place-items-stretch"
+ ]
+ },
+ "grid-column-counts": {
+ "class": "grid-cols",
+ "property": "--bs-columns",
+ "classes": [
+ "grid-cols-3",
+ "grid-cols-4",
+ "grid-cols-6"
+ ]
+ },
+ "grid-columns": {
+ "class": "grid-cols",
+ "property": "grid-column",
+ "classes": [
+ "grid-cols-fill"
+ ]
+ },
+ "grid-auto-flow": {
+ "class": "grid-auto-flow",
+ "property": "grid-auto-flow",
+ "classes": [
+ "grid-auto-flow-row",
+ "grid-auto-flow-column",
+ "grid-auto-flow-dense"
+ ]
+ },
+ "order": {
+ "class": "order",
+ "property": "order",
+ "classes": [
+ "order-first",
+ "order-0",
+ "order-1",
+ "order-2",
+ "order-3",
+ "order-4",
+ "order-5",
+ "order-last"
+ ]
+ },
+ "margin": {
+ "class": "m",
+ "property": "margin",
+ "classes": [
+ "m-0",
+ "m-1",
+ "m-2",
+ "m-3",
+ "m-4",
+ "m-5",
+ "m-auto"
+ ]
+ },
+ "margin-x": {
+ "class": "mx",
+ "property": "margin-right margin-left",
+ "classes": [
+ "mx-0",
+ "mx-1",
+ "mx-2",
+ "mx-3",
+ "mx-4",
+ "mx-5",
+ "mx-auto"
+ ]
+ },
+ "margin-y": {
+ "class": "my",
+ "property": "margin-top margin-bottom",
+ "classes": [
+ "my-0",
+ "my-1",
+ "my-2",
+ "my-3",
+ "my-4",
+ "my-5",
+ "my-auto"
+ ]
+ },
+ "margin-top": {
+ "class": "mt",
+ "property": "margin-top",
+ "classes": [
+ "mt-0",
+ "mt-1",
+ "mt-2",
+ "mt-3",
+ "mt-4",
+ "mt-5",
+ "mt-auto"
+ ]
+ },
+ "margin-end": {
+ "class": "me",
+ "property": "margin-right",
+ "classes": [
+ "me-0",
+ "me-1",
+ "me-2",
+ "me-3",
+ "me-4",
+ "me-5",
+ "me-auto"
+ ]
+ },
+ "margin-bottom": {
+ "class": "mb",
+ "property": "margin-bottom",
+ "classes": [
+ "mb-0",
+ "mb-1",
+ "mb-2",
+ "mb-3",
+ "mb-4",
+ "mb-5",
+ "mb-auto"
+ ]
+ },
+ "margin-start": {
+ "class": "ms",
+ "property": "margin-left",
+ "classes": [
+ "ms-0",
+ "ms-1",
+ "ms-2",
+ "ms-3",
+ "ms-4",
+ "ms-5",
+ "ms-auto"
+ ]
+ },
+ "padding": {
+ "class": "p",
+ "property": "padding",
+ "classes": [
+ "p-0",
+ "p-1",
+ "p-2",
+ "p-3",
+ "p-4",
+ "p-5"
+ ]
+ },
+ "padding-x": {
+ "class": "px",
+ "property": "padding-right padding-left",
+ "classes": [
+ "px-0",
+ "px-1",
+ "px-2",
+ "px-3",
+ "px-4",
+ "px-5"
+ ]
+ },
+ "padding-y": {
+ "class": "py",
+ "property": "padding-top padding-bottom",
+ "classes": [
+ "py-0",
+ "py-1",
+ "py-2",
+ "py-3",
+ "py-4",
+ "py-5"
+ ]
+ },
+ "padding-top": {
+ "class": "pt",
+ "property": "padding-top",
+ "classes": [
+ "pt-0",
+ "pt-1",
+ "pt-2",
+ "pt-3",
+ "pt-4",
+ "pt-5"
+ ]
+ },
+ "padding-end": {
+ "class": "pe",
+ "property": "padding-right",
+ "classes": [
+ "pe-0",
+ "pe-1",
+ "pe-2",
+ "pe-3",
+ "pe-4",
+ "pe-5"
+ ]
+ },
+ "padding-bottom": {
+ "class": "pb",
+ "property": "padding-bottom",
+ "classes": [
+ "pb-0",
+ "pb-1",
+ "pb-2",
+ "pb-3",
+ "pb-4",
+ "pb-5"
+ ]
+ },
+ "padding-start": {
+ "class": "ps",
+ "property": "padding-left",
+ "classes": [
+ "ps-0",
+ "ps-1",
+ "ps-2",
+ "ps-3",
+ "ps-4",
+ "ps-5"
+ ]
+ },
+ "gap": {
+ "class": "gap",
+ "property": "gap",
+ "classes": [
+ "gap-0",
+ "gap-1",
+ "gap-2",
+ "gap-3",
+ "gap-4",
+ "gap-5"
+ ]
+ },
+ "row-gap": {
+ "class": "row-gap",
+ "property": "row-gap",
+ "classes": [
+ "row-gap-0",
+ "row-gap-1",
+ "row-gap-2",
+ "row-gap-3",
+ "row-gap-4",
+ "row-gap-5"
+ ]
+ },
+ "column-gap": {
+ "class": "column-gap",
+ "property": "column-gap",
+ "classes": [
+ "column-gap-0",
+ "column-gap-1",
+ "column-gap-2",
+ "column-gap-3",
+ "column-gap-4",
+ "column-gap-5"
+ ]
+ },
+ "font-family": {
+ "class": "font",
+ "property": "font-family",
+ "classes": [
+ "font-monospace",
+ "font-body"
+ ]
+ },
+ "font-size": {
+ "class": "fs",
+ "property": "font-size",
+ "classes": [
+ "fs-xs",
+ "fs-sm",
+ "fs-md",
+ "fs-lg",
+ "fs-xl",
+ "fs-2xl",
+ "fs-3xl",
+ "fs-4xl",
+ "fs-5xl",
+ "fs-6xl"
+ ]
+ },
+ "text-size": {
+ "class": "text",
+ "classes": [
+ "text-xs",
+ "text-sm",
+ "text-md",
+ "text-lg",
+ "text-xl",
+ "text-2xl",
+ "text-3xl",
+ "text-4xl",
+ "text-5xl",
+ "text-6xl"
+ ]
+ },
+ "font-style": {
+ "class": "fst",
+ "property": "font-style",
+ "classes": [
+ "fst-italic",
+ "fst-normal"
+ ]
+ },
+ "font-weight": {
+ "class": "fw",
+ "property": "font-weight",
+ "classes": [
+ "fw-lighter",
+ "fw-light",
+ "fw-normal",
+ "fw-medium",
+ "fw-semibold",
+ "fw-bold",
+ "fw-bolder"
+ ]
+ },
+ "line-height": {
+ "class": "lh",
+ "property": "line-height",
+ "classes": [
+ "lh-1",
+ "lh-sm",
+ "lh-base",
+ "lh-lg"
+ ]
+ },
+ "text-align": {
+ "class": "text",
+ "property": "text-align",
+ "classes": [
+ "text-start",
+ "text-end",
+ "text-center"
+ ]
+ },
+ "text-decoration": {
+ "class": "text-decoration",
+ "property": "text-decoration",
+ "classes": [
+ "text-decoration-none",
+ "text-decoration-underline",
+ "text-decoration-line-through"
+ ]
+ },
+ "text-transform": {
+ "class": "text",
+ "property": "text-transform",
+ "classes": [
+ "text-lowercase",
+ "text-uppercase",
+ "text-capitalize"
+ ]
+ },
+ "text-wrap": {
+ "class": "text",
+ "property": "white-space",
+ "classes": [
+ "text-wrap",
+ "text-nowrap",
+ "text-balance",
+ "text-pretty"
+ ]
+ },
+ "word-wrap": {
+ "class": "text",
+ "property": "word-wrap word-break",
+ "classes": [
+ "text-break"
+ ]
+ },
+ "fg": {
+ "class": "fg",
+ "classes": [
+ "fg-primary",
+ "fg-accent",
+ "fg-success",
+ "fg-danger",
+ "fg-warning",
+ "fg-info",
+ "fg-inverse",
+ "fg-secondary",
+ "fg-body",
+ "fg-1",
+ "fg-2",
+ "fg-3",
+ "fg-white",
+ "fg-black",
+ "fg-inherit"
+ ]
+ },
+ "fg-emphasis": {
+ "class": "fg-emphasis",
+ "classes": [
+ "fg-emphasis-primary",
+ "fg-emphasis-accent",
+ "fg-emphasis-success",
+ "fg-emphasis-danger",
+ "fg-emphasis-warning",
+ "fg-emphasis-info",
+ "fg-emphasis-inverse",
+ "fg-emphasis-secondary"
+ ]
+ },
+ "fg-opacity": {
+ "class": "fg",
+ "property": "color",
+ "classes": [
+ "fg-10",
+ "fg-20",
+ "fg-30",
+ "fg-40",
+ "fg-50",
+ "fg-60",
+ "fg-70",
+ "fg-80",
+ "fg-90",
+ "fg-100"
+ ]
+ },
+ "fg-contrast": {
+ "class": "fg-contrast",
+ "classes": [
+ "fg-contrast-primary",
+ "fg-contrast-accent",
+ "fg-contrast-success",
+ "fg-contrast-danger",
+ "fg-contrast-warning",
+ "fg-contrast-info",
+ "fg-contrast-inverse",
+ "fg-contrast-secondary"
+ ]
+ },
+ "link-opacity": {
+ "class": "link",
+ "property": "color",
+ "classes": [
+ "link-10",
+ "link-20",
+ "link-30",
+ "link-40",
+ "link-50",
+ "link-60",
+ "link-70",
+ "link-80",
+ "link-90",
+ "link-100"
+ ]
+ },
+ "underline-offset": {
+ "class": "underline-offset",
+ "property": "text-underline-offset",
+ "classes": [
+ "underline-offset-1",
+ "underline-offset-2",
+ "underline-offset-3"
+ ]
+ },
+ "underline-color": {
+ "class": "underline",
+ "property": "text-decoration-color",
+ "classes": [
+ "underline-primary",
+ "underline-accent",
+ "underline-success",
+ "underline-danger",
+ "underline-warning",
+ "underline-info",
+ "underline-inverse",
+ "underline-secondary"
+ ]
+ },
+ "underline-opacity": {
+ "class": "underline",
+ "property": "text-decoration-color",
+ "classes": [
+ "underline-10",
+ "underline-20",
+ "underline-30",
+ "underline-40",
+ "underline-50",
+ "underline-60",
+ "underline-70",
+ "underline-80",
+ "underline-90",
+ "underline-100"
+ ]
+ },
+ "underline-thickness": {
+ "class": "underline-thickness",
+ "property": "text-decoration-thickness",
+ "classes": [
+ "underline-thickness-1",
+ "underline-thickness-2",
+ "underline-thickness-3",
+ "underline-thickness-4",
+ "underline-thickness-5"
+ ]
+ },
+ "bg-color": {
+ "class": "bg",
+ "classes": [
+ "bg-primary",
+ "bg-accent",
+ "bg-success",
+ "bg-danger",
+ "bg-warning",
+ "bg-info",
+ "bg-inverse",
+ "bg-secondary",
+ "bg-body",
+ "bg-1",
+ "bg-2",
+ "bg-3",
+ "bg-white",
+ "bg-black",
+ "bg-transparent",
+ "bg-inherit"
+ ]
+ },
+ "bg-color-subtle": {
+ "class": "bg-subtle",
+ "classes": [
+ "bg-subtle-primary",
+ "bg-subtle-accent",
+ "bg-subtle-success",
+ "bg-subtle-danger",
+ "bg-subtle-warning",
+ "bg-subtle-info",
+ "bg-subtle-inverse",
+ "bg-subtle-secondary"
+ ]
+ },
+ "bg-color-muted": {
+ "class": "bg-muted",
+ "classes": [
+ "bg-muted-primary",
+ "bg-muted-accent",
+ "bg-muted-success",
+ "bg-muted-danger",
+ "bg-muted-warning",
+ "bg-muted-info",
+ "bg-muted-inverse",
+ "bg-muted-secondary"
+ ]
+ },
+ "bg-opacity": {
+ "class": "bg",
+ "property": "background-color",
+ "classes": [
+ "bg-10",
+ "bg-20",
+ "bg-30",
+ "bg-40",
+ "bg-50",
+ "bg-60",
+ "bg-70",
+ "bg-80",
+ "bg-90",
+ "bg-100"
+ ]
+ },
+ "gradient": {
+ "class": "bg",
+ "property": "background-image",
+ "classes": [
+ "bg-gradient"
+ ]
+ },
+ "user-select": {
+ "class": "user-select",
+ "property": "user-select",
+ "classes": [
+ "user-select-all",
+ "user-select-auto",
+ "user-select-none"
+ ]
+ },
+ "pointer-events": {
+ "class": "pe",
+ "property": "pointer-events",
+ "classes": [
+ "pe-none",
+ "pe-auto"
+ ]
+ },
+ "border-radius": {
+ "class": "rounded",
+ "property": "border-radius",
+ "classes": [
+ "rounded",
+ "rounded-0",
+ "rounded-1",
+ "rounded-2",
+ "rounded-3",
+ "rounded-4",
+ "rounded-5",
+ "rounded-circle",
+ "rounded-pill"
+ ]
+ },
+ "rounded-top": {
+ "class": "rounded-top",
+ "property": "border-top-left-radius border-top-right-radius",
+ "classes": [
+ "rounded-top",
+ "rounded-top-0",
+ "rounded-top-1",
+ "rounded-top-2",
+ "rounded-top-3",
+ "rounded-top-4",
+ "rounded-top-5",
+ "rounded-top-circle",
+ "rounded-top-pill"
+ ]
+ },
+ "rounded-end": {
+ "class": "rounded-end",
+ "property": "border-top-right-radius border-bottom-right-radius",
+ "classes": [
+ "rounded-end",
+ "rounded-end-0",
+ "rounded-end-1",
+ "rounded-end-2",
+ "rounded-end-3",
+ "rounded-end-4",
+ "rounded-end-5",
+ "rounded-end-circle",
+ "rounded-end-pill"
+ ]
+ },
+ "rounded-bottom": {
+ "class": "rounded-bottom",
+ "property": "border-bottom-right-radius border-bottom-left-radius",
+ "classes": [
+ "rounded-bottom",
+ "rounded-bottom-0",
+ "rounded-bottom-1",
+ "rounded-bottom-2",
+ "rounded-bottom-3",
+ "rounded-bottom-4",
+ "rounded-bottom-5",
+ "rounded-bottom-circle",
+ "rounded-bottom-pill"
+ ]
+ },
+ "rounded-start": {
+ "class": "rounded-start",
+ "property": "border-bottom-left-radius border-top-left-radius",
+ "classes": [
+ "rounded-start",
+ "rounded-start-0",
+ "rounded-start-1",
+ "rounded-start-2",
+ "rounded-start-3",
+ "rounded-start-4",
+ "rounded-start-5",
+ "rounded-start-circle",
+ "rounded-start-pill"
+ ]
+ },
+ "visibility": {
+ "class": "",
+ "property": "visibility",
+ "classes": [
+ "-visible",
+ "-invisible"
+ ]
+ },
+ "z-index": {
+ "class": "z",
+ "property": "z-index",
+ "classes": [
+ "z-n1",
+ "z-0",
+ "z-1",
+ "z-2",
+ "z-3"
+ ]
+ }
+ }
+}
\ No newline at end of file
"scripts": {
"start": "npm-run-all --parallel watch docs-serve",
"bundlewatch": "bundlewatch --config .bundlewatch.config.json",
- "css": "npm-run-all css-compile css-prefix css-rtl css-minify",
+ "css": "npm-run-all css-compile css-prefix css-rtl css-minify css-docs",
"css-compile": "sass --style expanded --source-map --embed-sources --no-error-css scss/bootstrap.scss:dist/css/bootstrap.css scss/bootstrap-grid.scss:dist/css/bootstrap-grid.css scss/bootstrap-reboot.scss:dist/css/bootstrap-reboot.css scss/bootstrap-utilities.scss:dist/css/bootstrap-utilities.css",
- "css-rtl": "cross-env NODE_ENV=RTL postcss --config build/postcss.config.mjs --dir \"dist/css\" --ext \".rtl.css\" \"dist/css/*.css\" \"!dist/css/*.min.css\" \"!dist/css/*.rtl.css\"",
+ "css-docs": "node build/generate-utilities-json.mjs",
+ "css-rtl": "cross-env NODE_ENV=RTL postcss --config build/postcss.config.mjs --dir \"dist/css\" --ext \".rtl.css\" \"dist/css/*.css\" \"!dist/css/*.min.css\" \"!dist/css/*.rtl.css\" \"!dist/css/*.tmp.css\"",
"css-lint": "npm-run-all --aggregate-output --continue-on-error --parallel css-lint-*",
"css-lint-stylelint": "stylelint \"**/*.{css,scss}\" --cache --cache-location .cache/.stylelintcache",
"css-lint-vars": "fusv scss/ site/src/scss/",
"css-minify": "npm-run-all --aggregate-output --parallel css-minify-*",
- "css-minify-main": "cleancss -O1 --format breakWith=lf --with-rebase --source-map --source-map-inline-sources --output dist/css/ --batch --batch-suffix \".min\" \"dist/css/*.css\" \"!dist/css/*.min.css\" \"!dist/css/*rtl*.css\"",
+ "css-minify-main": "cleancss -O1 --format breakWith=lf --with-rebase --source-map --source-map-inline-sources --output dist/css/ --batch --batch-suffix \".min\" \"dist/css/*.css\" \"!dist/css/*.min.css\" \"!dist/css/*rtl*.css\" \"!dist/css/*.tmp.css\"",
"css-minify-rtl": "cleancss -O1 --format breakWith=lf --with-rebase --source-map --source-map-inline-sources --output dist/css/ --batch --batch-suffix \".min\" \"dist/css/*rtl.css\" \"!dist/css/*.min.css\"",
"css-prefix": "npm-run-all --aggregate-output --parallel css-prefix-*",
- "css-prefix-main": "postcss --config build/postcss.config.mjs --replace \"dist/css/*.css\" \"!dist/css/*.rtl*.css\" \"!dist/css/*.min.css\"",
+ "css-prefix-main": "postcss --config build/postcss.config.mjs --replace \"dist/css/*.css\" \"!dist/css/*.rtl*.css\" \"!dist/css/*.min.css\" \"!dist/css/*.tmp.css\"",
"css-prefix-examples": "postcss --config build/postcss.config.mjs --replace \"site/src/assets/examples/**/*.css\"",
"css-prefix-examples-rtl": "cross-env-shell NODE_ENV=RTL postcss --config build/postcss.config.mjs --dir \"site/src/assets/examples/\" --ext \".rtl.css\" --base \"site/src/assets/examples/\" \"site/src/assets/examples/{blog,carousel,dashboard,cheatsheet}/*.css\" \"!site/src/assets/examples/{blog,carousel,dashboard,cheatsheet}/*.rtl.css\"",
"css-test": "jasmine --config=scss/tests/jasmine.js",
.card-link {
&:hover {
- text-decoration: if($link-hover-decoration == underline, none, null);
+ text-decoration: none;
}
+ .card-link {
:root {
@each $color, $hue in $hues {
- --#{$prefix}#{$color}-025: color-mix(in oklch, #fff 94%, #{$hue});
- --#{$prefix}#{$color}-050: color-mix(in oklch, #fff 90%, #{$hue});
- --#{$prefix}#{$color}-100: color-mix(in oklch, #fff 80%, #{$hue});
- --#{$prefix}#{$color}-200: color-mix(in oklch, #fff 60%, #{$hue});
- --#{$prefix}#{$color}-300: color-mix(in oklch, #fff 40%, #{$hue});
- --#{$prefix}#{$color}-400: color-mix(in oklch, #fff 20%, #{$hue});
+ --#{$prefix}#{$color}-025: color-mix(in lab, #fff 94%, #{$hue});
+ --#{$prefix}#{$color}-050: color-mix(in lab, #fff 90%, #{$hue});
+ --#{$prefix}#{$color}-100: color-mix(in lab, #fff 80%, #{$hue});
+ --#{$prefix}#{$color}-200: color-mix(in lab, #fff 60%, #{$hue});
+ --#{$prefix}#{$color}-300: color-mix(in lab, #fff 40%, #{$hue});
+ --#{$prefix}#{$color}-400: color-mix(in lab, #fff 20%, #{$hue});
--#{$prefix}#{$color}-500: #{$hue};
- --#{$prefix}#{$color}-600: color-mix(in oklch, #000 16%, #{$hue});
- --#{$prefix}#{$color}-700: color-mix(in oklch, #000 32%, #{$hue});
- --#{$prefix}#{$color}-800: color-mix(in oklch, #000 48%, #{$hue});
- --#{$prefix}#{$color}-900: color-mix(in oklch, #000 64%, #{$hue});
- --#{$prefix}#{$color}-950: color-mix(in oklch, #000 76%, #{$hue});
- --#{$prefix}#{$color}-975: color-mix(in oklch, #000 88%, #{$hue});
+ --#{$prefix}#{$color}-600: color-mix(in lab, #000 16%, #{$hue});
+ --#{$prefix}#{$color}-700: color-mix(in lab, #000 32%, #{$hue});
+ --#{$prefix}#{$color}-800: color-mix(in lab, #000 48%, #{$hue});
+ --#{$prefix}#{$color}-900: color-mix(in lab, #000 64%, #{$hue});
+ --#{$prefix}#{$color}-950: color-mix(in lab, #000 76%, #{$hue});
+ --#{$prefix}#{$color}-975: color-mix(in lab, #000 88%, #{$hue});
}
}
) !default;
// scss-docs-end spacer-variables-maps
+$sizes: (
+ 1: $spacer,
+ 2: calc($spacer * 2),
+ 3: calc($spacer * 3),
+ 4: calc($spacer * 4),
+ 5: calc($spacer * 5),
+ 6: calc($spacer * 6),
+ 7: calc($spacer * 7),
+ 8: calc($spacer * 8),
+ 9: calc($spacer * 9),
+ 10: calc($spacer * 10),
+ 11: calc($spacer * 11),
+ 12: calc($spacer * 12),
+) !default;
+
// Grid breakpoints
//
// Define the minimum dimensions at which your layout will change,
font-weight: $font-weight-normal;
color: var(--#{$prefix}dropdown-link-color);
text-align: inherit; // For `<button>`s
- text-decoration: if($link-decoration == none, null, none);
+ text-decoration: none;
white-space: nowrap; // prevent links from randomly breaking onto new lines
background-color: transparent; // For `<button>`s
border: 0; // For `<button>`s
&:hover,
&:focus {
color: var(--#{$prefix}dropdown-link-hover-color);
- text-decoration: if($link-hover-decoration == underline, none, null);
@include gradient-bg(var(--#{$prefix}dropdown-link-hover-bg));
}
&.active,
&:active {
color: var(--#{$prefix}dropdown-link-active-color);
- text-decoration: none;
@include gradient-bg(var(--#{$prefix}dropdown-link-active-bg));
}
@return $result;
}
+// Extract a specific nested property from all items in a map
+// Useful for extracting a single property from nested map structures
+// Example: map-get-nested($font-sizes, "font-size")
+// Returns: ("xs": clamp(...), "sm": clamp(...), ...)
+@function map-get-nested($map, $nested-key) {
+ $result: ();
+ @each $key, $value in $map {
+ @if meta.type-of($value) == "map" {
+ $nested-value: map.get($value, $nested-key);
+ @if $nested-value != null {
+ $result: map.merge($result, ($key: $nested-value));
+ }
+ }
+ }
+ @return $result;
+}
+
// Merge multiple maps
@function map-merge-multiple($maps...) {
$merged-maps: ();
@include font-size(var(--#{$prefix}nav-link-font-size));
font-weight: var(--#{$prefix}nav-link-font-weight);
color: var(--#{$prefix}nav-link-color);
- text-decoration: if($link-decoration == none, null, none);
+ text-decoration: none;
background: none;
border: 0;
@include transition($nav-link-transition);
&:hover,
&:focus {
color: var(--#{$prefix}nav-link-hover-color);
- text-decoration: if($link-hover-decoration == underline, none, null);
}
&:focus-visible {
margin-right: var(--#{$prefix}navbar-brand-margin-end);
@include font-size(var(--#{$prefix}navbar-brand-font-size));
color: var(--#{$prefix}navbar-brand-color);
- text-decoration: if($link-decoration == none, null, none);
+ text-decoration: none;
white-space: nowrap;
&:hover,
&:focus {
color: var(--#{$prefix}navbar-brand-hover-color);
- text-decoration: if($link-hover-decoration == underline, none, null);
}
}
padding: var(--#{$prefix}pagination-padding-y) var(--#{$prefix}pagination-padding-x);
@include font-size(var(--#{$prefix}pagination-font-size));
color: var(--#{$prefix}pagination-color);
- text-decoration: if($link-decoration == none, null, none);
+ text-decoration: none;
background-color: var(--#{$prefix}pagination-bg);
border: var(--#{$prefix}pagination-border-width) solid var(--#{$prefix}pagination-border-color);
@include transition($pagination-transition);
&:hover {
z-index: 2;
color: var(--#{$prefix}pagination-hover-color);
- text-decoration: if($link-hover-decoration == underline, none, null);
background-color: var(--#{$prefix}pagination-hover-bg);
border-color: var(--#{$prefix}pagination-hover-border-color);
}
}
--#{$prefix}body-font-family: #{meta.inspect($font-family-base)};
+ // scss-docs-start root-font-size-variables
--#{$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);
+ // --#{$prefix}font-size-sm: calc(#{$font-size-base} * .9285);
+ // --#{$prefix}font-size-lg: calc(#{$font-size-base} * 1.285);
+
+ --#{$prefix}font-size-xs: clamp(.75rem, .7rem + .25vw, .875rem);
+ --#{$prefix}font-size-sm: clamp(.875rem, .8rem + .375vw, 1rem);
+ --#{$prefix}font-size-md: clamp(1rem, .9rem + .5vw, 1.125rem);
+ --#{$prefix}font-size-lg: clamp(1.25rem, 1rem + .625vw, 1.5rem);
+ --#{$prefix}font-size-xl: clamp(1.5rem, 1.1rem + .75vw, 1.75rem);
+ --#{$prefix}font-size-2xl: clamp(1.75rem, 1.3rem + 1vw, 2.25rem);
+ --#{$prefix}font-size-3xl: clamp(2rem, 1.5rem + 1.875vw, 2.5rem);
+ --#{$prefix}font-size-4xl: clamp(2.25rem, 1.75rem + 2.5vw, 3rem);
+ --#{$prefix}font-size-5xl: clamp(3rem, 2rem + 5vw, 4rem);
+ --#{$prefix}font-size-6xl: clamp(3.75rem, 2.5rem + 6.25vw, 5rem);
+
+ --#{$prefix}line-height-xs: 1.5;
+ --#{$prefix}line-height-sm: 1.5;
+ --#{$prefix}line-height-md: 1.5;
+ --#{$prefix}line-height-lg: 1.5;
+ --#{$prefix}line-height-xl: calc(2.5 / 1.75);
+ --#{$prefix}line-height-2xl: calc(3 / 2.25);
+ --#{$prefix}line-height-3xl: 1.2;
+ --#{$prefix}line-height-4xl: 1.1;
+ --#{$prefix}line-height-5xl: 1.1;
+ --#{$prefix}line-height-6xl: 1;
+ // scss-docs-end root-font-size-variables
@include rfs($font-size-base, --#{$prefix}body-font-size);
--#{$prefix}body-font-weight: #{$font-weight-base};
--#{$prefix}link-decoration: #{$link-decoration};
--#{$prefix}link-hover-color: color-mix(in oklch, var(--#{$prefix}link-color) 90%, #000);
- @if $link-hover-decoration != null {
- --#{$prefix}link-hover-decoration: #{$link-hover-decoration};
- }
-
--#{$prefix}code-color: #{$code-color};
--#{$prefix}highlight-color: #{$mark-color};
--#{$prefix}highlight-bg: #{$mark-bg};
@return $result;
}
+// Generate opacity values using color-mix()
+@function theme-opacity-values($color-var, $opacities: $util-opacity) {
+ $result: ();
+
+ @each $key, $value in $opacities {
+ @if $key == 100 {
+ // For 100%, use direct variable reference (more efficient)
+ $result: map.merge($result, ($key: var($color-var)));
+ } @else {
+ // For other values, use color-mix()
+ $percentage: $key * 1%;
+ $result: map.merge($result, ($key: color-mix(in oklch, var($color-var) $percentage, transparent)));
+ }
+ }
+
+ @return $result;
+}
+
// Generate theme classes dynamically based on the keys in each theme color map
@mixin generate-theme-classes() {
@each $color-name, $color-map in $new-theme-colors {
"base": var(--#{$prefix}blue-500),
"text": light-dark(var(--#{$prefix}blue-600), var(--#{$prefix}blue-400)),
"text-emphasis": light-dark(var(--#{$prefix}blue-800), var(--#{$prefix}blue-200)),
- "bg": light-dark(var(--#{$prefix}blue-500), var(--#{$prefix}blue-500)),
+ "bg": var(--#{$prefix}blue-500),
"bg-subtle": light-dark(var(--#{$prefix}blue-100), var(--#{$prefix}blue-900)),
"bg-muted": light-dark(var(--#{$prefix}blue-200), var(--#{$prefix}blue-800)),
"border": light-dark(var(--#{$prefix}blue-300), var(--#{$prefix}blue-600)),
"base": var(--#{$prefix}indigo-500),
"text": light-dark(var(--#{$prefix}indigo-600), color-mix(in oklch, var(--#{$prefix}indigo-400), var(--#{$prefix}indigo-300))),
"text-emphasis": light-dark(var(--#{$prefix}indigo-800), var(--#{$prefix}indigo-300)),
- "bg": light-dark(var(--#{$prefix}indigo-500), var(--#{$prefix}indigo-500)),
+ "bg": var(--#{$prefix}indigo-500),
"bg-subtle": light-dark(var(--#{$prefix}indigo-100), var(--#{$prefix}indigo-900)),
"bg-muted": light-dark(var(--#{$prefix}indigo-200), var(--#{$prefix}indigo-800)),
"border": light-dark(var(--#{$prefix}indigo-300), var(--#{$prefix}indigo-600)),
"base": var(--#{$prefix}green-500),
"text": light-dark(var(--#{$prefix}green-600), var(--#{$prefix}green-400)),
"text-emphasis": light-dark(var(--#{$prefix}green-800), var(--#{$prefix}green-300)),
- "bg": light-dark(var(--#{$prefix}green-500), var(--#{$prefix}green-500)),
+ "bg": var(--#{$prefix}green-500),
"bg-subtle": light-dark(var(--#{$prefix}green-100), var(--#{$prefix}green-900)),
"bg-muted": light-dark(var(--#{$prefix}green-200), var(--#{$prefix}green-800)),
"border": light-dark(var(--#{$prefix}green-300), var(--#{$prefix}green-600)),
"base": var(--#{$prefix}red-500),
"text": light-dark(var(--#{$prefix}red-600), var(--#{$prefix}red-400)),
"text-emphasis": light-dark(var(--#{$prefix}red-800), var(--#{$prefix}red-300)),
- "bg": light-dark(var(--#{$prefix}red-500), var(--#{$prefix}red-500)),
+ "bg": var(--#{$prefix}red-500),
"bg-subtle": light-dark(var(--#{$prefix}red-100), var(--#{$prefix}red-900)),
"bg-muted": light-dark(var(--#{$prefix}red-200), var(--#{$prefix}red-800)),
"border": light-dark(var(--#{$prefix}red-300), var(--#{$prefix}red-600)),
"base": var(--#{$prefix}yellow-500),
"text": light-dark(var(--#{$prefix}yellow-700), var(--#{$prefix}yellow-400)),
"text-emphasis": light-dark(var(--#{$prefix}yellow-800), var(--#{$prefix}yellow-300)),
- "bg": light-dark(var(--#{$prefix}yellow-500), var(--#{$prefix}yellow-500)),
+ "bg": var(--#{$prefix}yellow-500),
"bg-subtle": light-dark(var(--#{$prefix}yellow-100), var(--#{$prefix}yellow-900)),
"bg-muted": light-dark(var(--#{$prefix}yellow-200), var(--#{$prefix}yellow-800)),
"border": light-dark(var(--#{$prefix}yellow-300), var(--#{$prefix}yellow-600)),
"base": var(--#{$prefix}cyan-500),
"text": light-dark(var(--#{$prefix}cyan-600), var(--#{$prefix}cyan-400)),
"text-emphasis": light-dark(var(--#{$prefix}cyan-800), var(--#{$prefix}cyan-300)),
- "bg": light-dark(var(--#{$prefix}cyan-500), var(--#{$prefix}cyan-500)),
+ "bg": var(--#{$prefix}cyan-500),
"bg-subtle": light-dark(var(--#{$prefix}cyan-100), var(--#{$prefix}cyan-900)),
"bg-muted": light-dark(var(--#{$prefix}cyan-200), var(--#{$prefix}cyan-800)),
"border": light-dark(var(--#{$prefix}cyan-300), var(--#{$prefix}cyan-600)),
) !default;
$theme-borders: (
- null: light-dark(var(--#{$prefix}gray-300), var(--#{$prefix}gray-800)),
+ "bg": var(--#{$prefix}bg-body),
+ "body": light-dark(var(--#{$prefix}gray-300), var(--#{$prefix}gray-800)),
"muted": light-dark(var(--#{$prefix}gray-200), var(--#{$prefix}gray-800)),
"subtle": light-dark(var(--#{$prefix}gray-100), var(--#{$prefix}gray-900)),
"emphasized": light-dark(var(--#{$prefix}gray-400), var(--#{$prefix}gray-600)),
+ "white": var(--#{$prefix}white),
+ "black": var(--#{$prefix}black),
) !default;
-// $util-opacity: (
-// "10": .1,
-// "20": .2,
-// "30": .3,
-// "40": .4,
-// "50": .5,
-// "60": .6,
-// "70": .7,
-// "80": .8,
-// "90": .9,
-// "100": 1
-// ) !default;
+$util-opacity: (
+ 10: .1,
+ 20: .2,
+ 30: .3,
+ 40: .4,
+ 50: .5,
+ 60: .6,
+ 70: .7,
+ 80: .8,
+ 90: .9,
+ 100: 1
+) !default;
@use "theme" as *;
// add:
-// - placeItems
// - double check css grid helpers
//
// update:
// scss-docs-start utils-display
"display": (
responsive: true,
- print: true,
property: display,
class: d,
- important: true,
values: inline inline-block block grid inline-grid table table-row table-cell flex inline-flex contents flow-root none
),
// scss-docs-end utils-display
// scss-docs-start utils-position
"position": (
property: position,
- important: true,
values: static relative absolute fixed sticky
),
"top": (
0: 0,
)
),
+ // scss-docs-end utils-borders
+ // scss-docs-start utils-border-color
"border-color": (
- property: border-color,
+ property: (
+ "--#{$prefix}border-color": null,
+ "border-color": var(--#{$prefix}border-color)
+ ),
class: border,
- values: theme-color-values("border")
+ values: map.merge(theme-color-values("bg"), $theme-borders),
+ ),
+ "border-color-subtle": (
+ property: (
+ "--#{$prefix}border-color": null,
+ "border-color": var(--#{$prefix}border-color)
+ ),
+ class: border-subtle,
+ values: theme-color-values("border"),
),
"border-width": (
property: border-width,
class: border,
values: $border-widths
),
- // "border-opacity": (
- // css-var: true,
- // class: border-opacity,
- // values: (
- // 10: .1,
- // 25: .25,
- // 50: .5,
- // 75: .75,
- // 100: 1
- // )
- // ),
- // scss-docs-end utils-borders
+ "border-opacity": (
+ class: border,
+ property: border-color,
+ values: theme-opacity-values(--#{$prefix}border-color)
+ ),
+ // scss-docs-end utils-border-color
// Sizing utilities
- // scss-docs-start utils-sizing
+ // scss-docs-start utils-width
"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,
+ values: map.merge(
+ $sizes,
+ (
+ 25: 25%,
+ 50: 50%,
+ 75: 75%,
+ 100: 100%,
+ auto: auto,
+ min: min-content,
+ max: max-content,
+ fit: fit-content,
+ )
)
),
"max-width": (
class: min-vw,
values: (100: 100vw)
),
+ // scss-docs-end utils-width
+ // scss-docs-start utils-height
"height": (
property: height,
class: h,
class: min-vh,
values: (100: 100vh)
),
- // scss-docs-end utils-sizing
+ // scss-docs-end utils-height
// Flex utilities
// scss-docs-start utils-flex
"flex": (
stretch: stretch,
)
),
+ "grid-column-counts": (
+ responsive: true,
+ property: --#{$prefix}columns,
+ class: grid-cols,
+ values: (
+ 3,
+ 4,
+ 6
+ )
+ ),
+ "grid-columns": (
+ responsive: true,
+ property: grid-column,
+ class: grid-cols,
+ values: (
+ fill: #{"1 / -1"},
+ )
+ ),
+ "grid-auto-flow": (
+ responsive: true,
+ property: grid-auto-flow,
+ class: grid-auto-flow,
+ values: row column dense
+ ),
"order": (
responsive: true,
property: order,
),
// scss-docs-end utils-spacing
// Text
- // scss-docs-start utils-text
+ // scss-docs-start utils-font-family
"font-family": (
property: font-family,
class: font,
- values: (monospace: var(--#{$prefix}font-monospace))
+ values: (
+ "monospace": var(--#{$prefix}font-monospace),
+ "body": var(--#{$prefix}font-sans-serif),
+ )
),
+ // scss-docs-end utils-font-family
+ // scss-docs-start utils-font-size
"font-size": (
- rfs: true,
property: font-size,
class: fs,
+ values: map-get-nested($font-sizes, "font-size")
+ ),
+ "text-size": (
+ property: (
+ "font-size": 1rem,
+ "line-height": 1.5
+ ),
+ class: text,
values: $font-sizes
),
+ // scss-docs-end utils-font-size
"font-style": (
property: font-style,
class: fst,
property: text-decoration,
values: none underline line-through
),
+ // scss-docs-start utils-text-transform
"text-transform": (
property: text-transform,
class: text,
values: lowercase uppercase capitalize
),
- "white-space": (
+ // scss-docs-end utils-text-transform
+ // "white-space": (
+ // property: white-space,
+ // class: text,
+ // values: (
+ // wrap: normal,
+ // nowrap: nowrap,
+ // )
+ // ),
+ "text-wrap": (
property: white-space,
class: text,
- values: (
- wrap: normal,
- nowrap: nowrap,
- )
+ values: wrap nowrap balance pretty,
),
+ // scss-docs-start utils-text-break
"word-wrap": (
property: word-wrap word-break,
class: text,
values: (break: break-word),
rtl: false
),
+ // scss-docs-end utils-text-break
// scss-docs-end utils-text
// scss-docs-start utils-color
- "color-attr": (
- selector: "attr-includes",
- class: "color-",
- property: color,
- values: var(--#{$prefix}color),
- ),
- "color": (
- property: --#{$prefix}color,
- class: color,
+ // "color-attr": (
+ // selector: "attr-includes",
+ // class: "fg-",
+ // property: color,
+ // values: var(--#{$prefix}fg),
+ // ),
+ "fg": (
+ property: (
+ "--#{$prefix}fg": null,
+ "color": var(--#{$prefix}fg)
+ ),
+ class: fg,
values: map.merge(theme-color-values("text"), $theme-fgs),
),
- "color-opacity": (
- class: color,
+ "fg-emphasis": (
+ property: (
+ "--#{$prefix}fg": null,
+ "color": var(--#{$prefix}fg)
+ ),
+ class: fg-emphasis,
+ values: theme-color-values("text-emphasis"),
+ ),
+ "fg-opacity": (
+ class: fg,
property: color,
- values: (
- 10: color-mix(in oklch, var(--#{$prefix}color) 10%, transparent),
- 20: color-mix(in oklch, var(--#{$prefix}color) 20%, transparent),
- 30: color-mix(in oklch, var(--#{$prefix}color) 30%, transparent),
- 40: color-mix(in oklch, var(--#{$prefix}color) 40%, transparent),
- 50: color-mix(in oklch, var(--#{$prefix}color) 50%, transparent),
- 60: color-mix(in oklch, var(--#{$prefix}color) 60%, transparent),
- 70: color-mix(in oklch, var(--#{$prefix}color) 70%, transparent),
- 80: color-mix(in oklch, var(--#{$prefix}color) 80%, transparent),
- 90: color-mix(in oklch, var(--#{$prefix}color) 90%, transparent),
- 100: var(--#{$prefix}color),
- )
- ),
- "contrast-color": (
- property: --#{$prefix}color,
- class: color-on,
+ values: theme-opacity-values(--#{$prefix}fg)
+ ),
+ "fg-contrast": (
+ property: (
+ "--#{$prefix}fg": null,
+ "color": var(--#{$prefix}fg)
+ ),
+ class: fg-contrast,
values: theme-color-values("contrast"),
),
// scss-docs-end utils-color
// scss-docs-start utils-links
"link-opacity": (
- property: --#{$prefix}link-opacity,
+ property: color,
// css-var: true,
- class: link-opacity,
+ class: link,
state: hover,
- values: (
- 10: .1,
- 25: .25,
- 50: .5,
- 75: .75,
- 100: 1
- )
+ values: theme-opacity-values(--#{$prefix}link-color)
),
- "link-offset": (
+ // scss-docs-end utils-links
+ // scss-docs-start utils-underline
+ "underline-offset": (
property: text-underline-offset,
- class: link-offset,
+ class: underline-offset,
state: hover,
values: (
1: .125em,
3: .375em,
)
),
- "link-underline": (
+ "underline-color": (
property: text-decoration-color,
- class: link-underline,
- local-vars: (
- "link-underline-opacity": 1
- ),
- // values: map.merge(
- // $utilities-links-underline,
- // (
- // // null: rgba(var(--#{$prefix}link-color-rgb), var(--#{$prefix}link-underline-opacity, 1)),
- // )
- // )
- ),
- "link-underline-opacity": (
- // css-var: true,
- property: --#{$prefix}link-underline-opacity,
- class: link-underline-opacity,
+ class: underline,
+ values: theme-color-values("text"),
+ ),
+ "underline-opacity": (
+ property: text-decoration-color,
+ class: underline,
+ state: hover,
+ values: theme-opacity-values(--#{$prefix}link-color)
+ ),
+ "underline-thickness": (
+ property: text-decoration-thickness,
+ class: underline-thickness,
state: hover,
values: (
- 0: 0,
- 10: .1,
- 25: .25,
- 50: .5,
- 75: .75,
- 100: 1
- ),
+ 1: 1px,
+ 2: 2px,
+ 3: 3px,
+ 4: 4px,
+ 5: 5px,
+ )
),
- // scss-docs-end utils-links
+ // scss-docs-end utils-underline
// scss-docs-start utils-bg-color
- "bg-attr": (
- selector: "attr-includes",
- class: "bg-",
- property: background-color,
- values: var(--#{$prefix}bg),
- ),
"bg-color": (
- property: --#{$prefix}bg,
+ property: (
+ "--#{$prefix}bg": null,
+ "background-color": var(--#{$prefix}bg)
+ ),
class: bg,
values: map.merge(theme-color-values("bg"), $theme-bgs),
),
"bg-color-subtle": (
- property: --#{$prefix}bg,
+ property: (
+ "--#{$prefix}bg": null,
+ "background-color": var(--#{$prefix}bg)
+ ),
class: bg-subtle,
values: theme-color-values("bg-subtle"),
),
"bg-color-muted": (
- property: --#{$prefix}bg,
+ property: (
+ "--#{$prefix}bg": null,
+ "background-color": var(--#{$prefix}bg)
+ ),
class: bg-muted,
values: theme-color-values("bg-muted"),
),
"bg-opacity": (
class: bg,
property: background-color,
- values: (
- 10: color-mix(in oklch, var(--#{$prefix}bg) 10%, transparent),
- 20: color-mix(in oklch, var(--#{$prefix}bg) 20%, transparent),
- 30: color-mix(in oklch, var(--#{$prefix}bg) 30%, transparent),
- 40: color-mix(in oklch, var(--#{$prefix}bg) 40%, transparent),
- 50: color-mix(in oklch, var(--#{$prefix}bg) 50%, transparent),
- 60: color-mix(in oklch, var(--#{$prefix}bg) 60%, transparent),
- 70: color-mix(in oklch, var(--#{$prefix}bg) 70%, transparent),
- 80: color-mix(in oklch, var(--#{$prefix}bg) 80%, transparent),
- 90: color-mix(in oklch, var(--#{$prefix}bg) 90%, transparent),
- 100: var(--#{$prefix}bg),
- )
+ values: theme-opacity-values(--#{$prefix}bg)
),
// scss-docs-end utils-bg-color
"gradient": (
"visibility": (
property: visibility,
class: null,
- important: true,
values: (
visible: visible,
invisible: hidden,
$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;
+// $link-hover-decoration: $link-decoration !default;
$stretched-link-pseudo-element: after !default;
$stretched-link-z-index: 1 !default;
5: 5px
) !default;
$border-style: solid !default;
-$border-color: var(--#{$prefix}gray-200) !default;
+$border-color: color-mix(in oklch, var(--#{$prefix}gray-100), var(--#{$prefix}gray-200)) !default;
$border-color-translucent: rgba($black, .175) !default;
// scss-docs-end border-variables
$line-height-sm: 1.25 !default;
$line-height-lg: 2 !default;
-$h1-font-size: $font-size-base * 2.5 !default;
-$h2-font-size: $font-size-base * 2 !default;
-$h3-font-size: $font-size-base * 1.75 !default;
-$h4-font-size: $font-size-base * 1.5 !default;
-$h5-font-size: $font-size-base * 1.25 !default;
-$h6-font-size: $font-size-base !default;
+$h1-font-size: var(--#{$prefix}font-size-3xl) !default;
+$h2-font-size: var(--#{$prefix}font-size-2xl) !default;
+$h3-font-size: var(--#{$prefix}font-size-xl) !default;
+$h4-font-size: var(--#{$prefix}font-size-lg) !default;
+$h5-font-size: var(--#{$prefix}font-size-md) !default;
+$h6-font-size: var(--#{$prefix}font-size-sm) !default;
// scss-docs-end font-variables
-// scss-docs-start font-sizes
+// Font sizes with line-height for utilities
$font-sizes: (
- 1: $h1-font-size,
- 2: $h2-font-size,
- 3: $h3-font-size,
- 4: $h4-font-size,
- 5: $h5-font-size,
- 6: $h6-font-size
+ "xs": (
+ "font-size": var(--#{$prefix}font-size-xs),
+ "line-height": var(--#{$prefix}line-height-xs)
+ ),
+ "sm": (
+ "font-size": var(--#{$prefix}font-size-sm),
+ "line-height": var(--#{$prefix}line-height-sm)
+ ),
+ "md": (
+ "font-size": var(--#{$prefix}font-size-md),
+ "line-height": var(--#{$prefix}line-height-md)
+ ),
+ "lg": (
+ "font-size": var(--#{$prefix}font-size-lg),
+ "line-height": var(--#{$prefix}line-height-lg)
+ ),
+ "xl": (
+ "font-size": var(--#{$prefix}font-size-xl),
+ "line-height": var(--#{$prefix}line-height-xl)
+ ),
+ "2xl": (
+ "font-size": var(--#{$prefix}font-size-2xl),
+ "line-height": var(--#{$prefix}line-height-2xl)
+ ),
+ "3xl": (
+ "font-size": var(--#{$prefix}font-size-3xl),
+ "line-height": var(--#{$prefix}line-height-3xl)
+ ),
+ "4xl": (
+ "font-size": var(--#{$prefix}font-size-4xl),
+ "line-height": var(--#{$prefix}line-height-4xl)
+ ),
+ "5xl": (
+ "font-size": var(--#{$prefix}font-size-5xl),
+ "line-height": var(--#{$prefix}line-height-5xl)
+ ),
+ "6xl": (
+ "font-size": var(--#{$prefix}font-size-6xl),
+ "line-height": var(--#{$prefix}line-height-6xl)
+ ),
) !default;
-// scss-docs-end font-sizes
// scss-docs-start headings-variables
$headings-margin-bottom: $spacer * .5 !default;
$headings-color: inherit !default;
// scss-docs-end headings-variables
-// scss-docs-start display-headings
-$display-font-sizes: (
- 1: 5rem,
- 2: 4.5rem,
- 3: 4rem,
- 4: 3.5rem,
- 5: 3rem,
- 6: 2.5rem
-) !default;
-
-$display-font-family: null !default;
-$display-font-style: null !default;
-$display-font-weight: 300 !default;
-$display-line-height: $headings-line-height !default;
-// scss-docs-end display-headings
-
// scss-docs-start type-variables
-$lead-font-size: $font-size-base * 1.25 !default;
-$lead-font-weight: 300 !default;
-
$small-font-size: .875em !default;
$sub-sup-font-size: .75em !default;
line-height: var(--#{$prefix}btn-line-height);
color: var(--#{$prefix}btn-color);
text-align: center;
- text-decoration: if($link-decoration == none, null, none);
+ text-decoration: none;
white-space: $btn-white-space;
vertical-align: middle;
cursor: if($enable-button-pointers, pointer, null);
&:hover {
color: var(--#{$prefix}btn-hover-color);
- text-decoration: if($link-hover-decoration == underline, none, null);
background-color: var(--#{$prefix}btn-hover-bg);
border-color: var(--#{$prefix}btn-hover-border-color);
}
--#{$prefix}btn-box-shadow: 0 0 0 #000; // Can't use `none` as keyword negates all values when used with multiple shadows
// --#{$prefix}btn-focus-shadow-rgb: #{$btn-link-focus-shadow-rgb};
- text-decoration: $link-decoration;
+ text-decoration: var(--#{$prefix}link-decoration);
+
@if $enable-gradients {
background-image: none;
}
- &:hover,
- &:focus-visible {
- text-decoration: $link-hover-decoration;
- }
-
&:focus-visible {
color: var(--#{$prefix}btn-color);
}
text-underline-offset: $link-underline-offset;
&:hover {
+ // --#{$prefix}link-color: var(--#{$prefix}link-hover-color);
+ // --#{$prefix}link-decoration: var(--#{$prefix}link-hover-decoration, var(--#{$prefix}link-decoration));
color: var(--#{$prefix}link-hover-color);
- text-decoration: var(--#{$prefix}link-hover-decoration);
+ text-decoration: var(--#{$prefix}link-hover-decoration, var(--#{$prefix}link-decoration));
}
}
@use "../vendor/rfs" as *;
@layer content {
- .lead {
- @include font-size($lead-font-size);
- font-weight: $lead-font-weight;
- }
-
- // Type display classes
- @each $display, $font-size in $display-font-sizes {
- .display-#{$display} {
- font-family: $display-font-family;
- font-style: $display-font-style;
- font-weight: $display-font-weight;
- line-height: $display-line-height;
- @include font-size($font-size);
- }
- }
-
//
// Lists
//
@each $color, $value in $new-theme-colors {
.text-bg-#{$color} {
color: var(--#{$prefix}#{$color}-text);
- background-color: var(--#{$prefix}#{$color}-bg-subtle);
+ --#{$prefix}bg: var(--#{$prefix}#{$color}-bg-subtle);
// color: color-contrast($value);
// background-color: RGBA(var(--#{$prefix}#{$color}-rgb), var(--#{$prefix}bg-opacity, 1));
}
@use "../theme" as *;
@use "../variables" as *;
-// All-caps `RGBA()` function used because of this Sass bug: https://github.com/sass/node-sass/issues/2251
@layer helpers {
@each $color, $value in $new-theme-colors {
.link-#{$color} {
- color: var(--#{$prefix}#{$color}-text);
- // color: color-mix(in srgb, var(--#{$prefix}#{$color}), transparent var(--#{$prefix}link-opacity));
- text-decoration-color: color-mix(in srgb, var(--#{$prefix}#{$color}-text), transparent var(--#{$prefix}link-underline-opacity));
+ --#{$prefix}link-color: var(--#{$prefix}#{$color}-text);
+ // text-decoration-color: color-mix(in srgb, var(--#{$prefix}#{$color}-text), transparent var(--#{$prefix}link-underline-opacity));
@if $link-shade-percentage != 0 {
&:hover,
&:focus {
+ --#{$prefix}link-color: var(--#{$prefix}#{$color}-text-emphasis);
+ --#{$prefix}link-hover-color: var(--#{$prefix}#{$color}-text-emphasis);
// $hover-color: if(color-contrast($value) == $color-contrast-light, shade-color($value, $link-shade-percentage), tint-color($value, $link-shade-percentage));
// color: color-mix(in srgb, $hover-color, transparent var(--#{$prefix}link-opacity));
- text-decoration-color: color-mix(in srgb, var(--#{$prefix}#{$color}-text), transparent var(--#{$prefix}link-underline-opacity));
+ // text-decoration-color: color-mix(in srgb, var(--#{$prefix}#{$color}-text), transparent var(--#{$prefix}link-underline-opacity));
}
}
}
gap: var(--#{$prefix}gap);
}
- // mdo-do: add to utilities?
- .g-col-auto {
- grid-column: auto/auto;
- }
+ // .g-col-auto {
+ // grid-column: auto;
+ // }
// mdo-do: add to utilities?
- .grid-cols-3 {
- --#{$prefix}columns: 3;
- }
- .grid-cols-4 {
- --#{$prefix}columns: 4;
- }
- .grid-cols-6 {
- --#{$prefix}columns: 6;
- }
+ // .grid-cols-3 {
+ // --#{$prefix}columns: 3;
+ // }
+ // .grid-cols-4 {
+ // --#{$prefix}columns: 4;
+ // }
+ // .grid-cols-6 {
+ // --#{$prefix}columns: 6;
+ // }
- .grid-full {
- grid-column: 1 / -1;
- }
+ // .grid-full {
+ // grid-column: 1 / -1;
+ // }
}
// Utility generator
-// - Utilities can three different types of selectors:
+// - Utilities can use 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 generate regular CSS properties and CSS custom properties
// - Utilities can be responsive or not
-// - Utilities can have a state (e.g., :hover, :focus, :active, etc.)
+// - Utilities can have state variants (e.g., hover, focus, active)
+// - Utilities can define local CSS variables
+//
+// CSS custom properties can be generated in two ways:
+//
+// 1. Property map with null values (CSS var receives the utility value):
+// "bg-color": (
+// property: (
+// "--#{$prefix}bg": null,
+// "background-color": var(--#{$prefix}bg)
+// ),
+// class: bg,
+// values: (
+// primary: var(--#{$prefix}blue-500),
+// )
+// )
+// Generates:
+// .bg-primary {
+// --bs-bg: var(--bs-blue-500);
+// background-color: var(--bs-bg);
+// }
+//
+// 2. Variables map (static CSS custom properties on every class):
+// "link-underline": (
+// property: text-decoration-color,
+// class: link-underline,
+// variables: (
+// "link-underline-opacity": 1
+// ),
+// values: (...)
+// )
+// Generates:
+// .link-underline {
+// --bs-link-underline-opacity: 1;
+// text-decoration-color: ...;
+// }
+
+// Helper mixin to generate CSS properties for both legacy and property map approaches
+@mixin generate-properties($utility, $propertyMap, $properties, $value) {
+ @if $propertyMap != null {
+ // New Property-Value Mapping approach
+ @each $property, $defaultValue in $propertyMap {
+ // If value is a map, check if it has a key for this property
+ // Otherwise, use defaultValue (or $value if defaultValue is null)
+ $actualValue: $defaultValue;
+ @if meta.type-of($value) == "map" and map.has-key($value, $property) {
+ $actualValue: map.get($value, $property);
+ } @else if $defaultValue == null {
+ $actualValue: $value;
+ }
+ @if map.get($utility, important) {
+ #{$property}: $actualValue !important; // stylelint-disable-line declaration-no-important
+ } @else {
+ #{$property}: $actualValue;
+ }
+ }
+ } @else {
+ // Legacy approach
+ @each $property in $properties {
+ @if map.get($utility, important) {
+ #{$property}: $value !important; // stylelint-disable-line declaration-no-important
+ } @else {
+ #{$property}: $value;
+ }
+ }
+ }
+}
-@mixin generate-utility($utility, $infix: "", $is-rfs-media-query: false) {
+@mixin generate-utility($utility, $infix: "") {
// 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"])
@each $key, $value in $values {
$properties: map.get($utility, property);
-
- // Multiple properties are possible, for example with vertical or horizontal margins or paddings
- @if meta.type-of($properties) == "string" {
- $properties: list.append((), $properties);
+ $propertyMap: null;
+ $customClass: "";
+
+ // Check if property is a map (new Property-Value Mapping approach)
+ // @debug "Properties type: #{meta.type-of($properties)}";
+ // @debug "Properties: #{$properties}";
+ @if meta.type-of($properties) == "map" {
+ $propertyMap: $properties;
+ // For property maps, we need to determine the class from the utility definition
+ $customClass: if(map.has-key($utility, class), map.get($utility, class), "");
+ } @else {
+ // Legacy approach: Multiple properties are possible, for example with vertical or horizontal margins or paddings
+ @if meta.type-of($properties) == "string" {
+ $properties: list.append((), $properties);
+ }
+ // 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 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`
// 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 params to generate state variants
$state: if(map.has-key($utility, state), map.get($utility, state), ());
// $infix: if($customClass == "" and str-slice($infix, 1, 1) == "-", str-slice($infix, 2), $infix);
// @debug $values;
#{$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.";
- }
- @if $is-rfs-media-query {
- @each $property in $properties {
- @include rfs($value, $property);
+ // Generate CSS custom properties (variables) if provided
+ // Variables receive the current utility value, then properties reference them
+ @if map.has-key($utility, variables) {
+ $variables: map.get($utility, variables);
+ @if meta.type-of($variables) == "list" {
+ // If variables is a list, each variable gets the utility value
+ @each $var-name in $variables {
+ --#{$prefix}#{$var-name}: #{$value};
}
- }
- @else {
- @each $property in $properties {
- @include rfs($value, $property);
+ } @else if meta.type-of($variables) == "map" {
+ // If variables is a map, use the provided values (for static variables)
+ @each $var-key, $var-value in $variables {
+ --#{$prefix}#{$var-key}: #{$var-value};
}
}
- } @else {
- @each $property in $properties {
- @if map.get($utility, important) {
- #{$property}: $value !important; // stylelint-disable-line declaration-no-important
- } @else {
- #{$property}: $value;
+ }
+ @include generate-properties($utility, $propertyMap, $properties, $value);
+ }
+
+ // Generate state variants
+ @if $state != () {
+ @each $state-variant in $state {
+ #{$selector}-#{$state-variant}:#{$state-variant} {
+ // Generate CSS custom properties (variables) if provided
+ @if map.has-key($utility, variables) {
+ $variables: map.get($utility, variables);
+ @if meta.type-of($variables) == "list" {
+ // If variables is a list, each variable gets the utility value
+ @each $var-name in $variables {
+ --#{$prefix}#{$var-name}: #{$value};
+ }
+ } @else if meta.type-of($variables) == "map" {
+ // If variables is a map, use the provided values (for static variables)
+ @each $var-key, $var-value in $variables {
+ --#{$prefix}#{$var-key}: #{$var-value};
+ }
+ }
}
+ @include generate-properties($utility, $propertyMap, $properties, $value);
}
}
}
-
- // @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);
}
}
icon_color: red
pages:
- title: API
- - title: Background
- - title: Border
- - title: Border radius
- - title: Colors
+ - group: Color
+ pages:
+ - title: Colors
+ - title: Background
- group: Layout
pages:
- title: Aspect ratio
- title: Align items
- title: Align self
- title: Flex
+ - title: Gap
+ - title: Grid
- title: Justify content
- title: Justify items
- title: Place items
- title: Padding
- group: Type
pages:
+ - title: Font family
+ - title: Font size
- title: Font style
+ - title: Font weight
+ - title: Line height
+ - title: Link
- title: Text alignment
- title: Text decoration
+ - title: Text transform
- title: Text wrapping
- title: Vertical align
+ - title: Word break
+ - group: Borders
+ pages:
+ - title: Border
+ - title: Border color
+ - title: Border radius
- group: Interactions
pages:
- title: Pointer events
{group.icon && (
<svg
class="bi me-2"
- style={group.icon_color && `color: light-dark(var(--bs-${group.icon_color}-500), var(--bs-${group.icon_color}-300));`}
+ style={group.icon_color && `color: light-dark(var(--bs-${group.icon_color}-500), var(--bs-${group.icon_color}-400));`}
aria-hidden="true"
>
<use xlink:href={`#${group.icon}`} />
--- /dev/null
+---
+interface ClassItem {
+ class: string;
+ description: string;
+}
+
+interface Props {
+ classes: ClassItem[];
+ className?: string;
+}
+
+const {
+ classes,
+ className = "table reference-table"
+} = Astro.props;
+
+// Format class names with dot prefix if needed
+const tableData = classes.map(item => ({
+ class: item.class.startsWith('.') ? item.class : `.${item.class}`,
+ description: item.description
+}));
+---
+
+<div class="table-responsive bd-reference-table">
+ <table class={className}>
+ <thead>
+ <tr>
+ <th scope="col">Class</th>
+ <th scope="col">Description</th>
+ </tr>
+ </thead>
+ <tbody>
+ {tableData.map((row) => (
+ <tr>
+ <td><code>{row.class}</code></td>
+ <td>{row.description}</td>
+ </tr>
+ ))}
+ </tbody>
+ </table>
+</div>
---
+import { readFileSync } from 'node:fs';
+import { join } from 'node:path';
+
interface ReferenceItem {
class: string;
- styles: string | string[] | Record<string, string>;
+ styles?: string | string[] | Record<string, string>;
+ description?: string;
+ comment?: string; // Optional manual comment to append
[key: string]: any; // Allow additional properties
}
// Use explicit reference prop or data prop
const referenceData = reference || data || [];
+// Parse CSS variables from _root.scss at build time
+function parseCSSVariables(): Record<string, string> {
+ try {
+ const projectRoot = process.cwd();
+ const rootScssPath = join(projectRoot, 'scss/_root.scss');
+ const scssContent = readFileSync(rootScssPath, 'utf-8');
+
+ const cssVarValues: Record<string, string> = {};
+
+ // Match CSS variable declarations: --#{$prefix}variable-name: value;
+ // This regex captures the variable name and its value
+ const varRegex = /--#\{\$prefix\}([a-z0-9-]+):\s*([^;]+);/gi;
+ let match;
+
+ while ((match = varRegex.exec(scssContent)) !== null) {
+ const varName = `--bs-${match[1]}`;
+ let value = match[2].trim();
+
+ // Clean up SCSS interpolation syntax (e.g., #{$variable})
+ value = value.replace(/#\{[^}]+\}/g, '').trim();
+
+ // Remove inline comments
+ value = value.replace(/\/\/.*$/gm, '').trim();
+
+ // Only store if we have a clean value (not empty after removing interpolations)
+ if (value) {
+ cssVarValues[varName] = value;
+ }
+ }
+
+ return cssVarValues;
+ } catch (error) {
+ console.warn('Could not parse CSS variables from _root.scss:', error);
+ return {};
+ }
+}
+
+const cssVarValues = parseCSSVariables();
+
+// Function to add CSS variable value comments
+function addVarComments(cssValue: string): string {
+ const comments: string[] = [];
+
+ // Collect resolved values for all CSS variables
+ cssValue.replace(/var\((--[a-z0-9-]+)\)/gi, (match, varName) => {
+ const resolvedValue = cssVarValues[varName];
+ if (resolvedValue) {
+ comments.push(`<span class="color-3">/* ${resolvedValue} */</span>`);
+ }
+ return match;
+ });
+
+ // Append comments after the last semicolon or at the end
+ if (comments.length > 0) {
+ const hasSemicolon = cssValue.trimEnd().endsWith(';');
+ return `${cssValue}${hasSemicolon ? '' : ';'} ${comments.join(' ')}`;
+ }
+
+ return cssValue;
+}
+
// If no explicit columns provided, infer from the first data item
const inferredColumns = columns || (() => {
if (referenceData.length === 0) {
}
const firstItem = referenceData[0];
- return Object.keys(firstItem).map(key => ({
- label: key.charAt(0).toUpperCase() + key.slice(1), // Capitalize first letter
- key: key
- }));
+ return Object.keys(firstItem)
+ .filter(key => key !== 'comment') // Exclude comment field from columns
+ .map(key => ({
+ label: key.charAt(0).toUpperCase() + key.slice(1),
+ key: key
+ }));
})();
// Transform frontmatter format to table format
}
if (key === 'styles') {
+ let processedStyles = '';
+
if (typeof value === 'string') {
- transformedItem[key] = value;
+ processedStyles = addVarComments(value);
} else if (typeof value === 'object' && !Array.isArray(value)) {
// Handle object syntax: { prop: value, prop2: value2 }
- transformedItem[key] = Object.entries(value)
- .map(([prop, val]) => `${prop}: ${val};`)
+ processedStyles = Object.entries(value)
+ .map(([prop, val]) => {
+ const cssLine = `${prop}: ${val};`;
+ return addVarComments(cssLine);
+ })
.join('<br/>');
} else if (Array.isArray(value)) {
- transformedItem[key] = value.map((style: any) => {
+ processedStyles = value.map((style: any) => {
if (typeof style === 'string') {
- return style.includes(':') ? style + (style.endsWith(';') ? '' : ';') : style;
+ const formattedStyle = style.includes(':') ? style + (style.endsWith(';') ? '' : ';') : style;
+ return addVarComments(formattedStyle);
}
if (typeof style === 'object') {
- return Object.entries(style).map(([prop, val]) => `${prop}: ${val};`).join(' ');
+ const cssLine = Object.entries(style).map(([prop, val]) => `${prop}: ${val};`).join(' ');
+ return addVarComments(cssLine);
}
return style;
}).join('<br/>');
} else {
- transformedItem[key] = value || '';
+ processedStyles = value || '';
}
+
+ // Append manual comment if provided in frontmatter
+ if (item.comment) {
+ processedStyles += `<br/><span class="color-3">/* ${item.comment} */</span>`;
+ }
+
+ transformedItem[key] = processedStyles;
} else {
transformedItem[key] = value;
}
--- /dev/null
+---
+import { readFileSync } from 'node:fs';
+import { join } from 'node:path';
+
+interface Props {
+ utility: string | string[]; // The utility key(s) from the metadata (e.g., "font-size" or ["font-size", "text-size"])
+ className?: string;
+}
+
+const {
+ utility,
+ className = "table reference-table"
+} = Astro.props;
+
+// Normalize to array
+const utilities = Array.isArray(utility) ? utility : [utility];
+
+// Parse CSS variables from _root.scss at build time
+function parseCSSVariables(): Record<string, string> {
+ try {
+ const projectRoot = process.cwd();
+ const rootScssPath = join(projectRoot, 'scss/_root.scss');
+ const scssContent = readFileSync(rootScssPath, 'utf-8');
+
+ const cssVarValues: Record<string, string> = {};
+ const varRegex = /--#\{\$prefix\}([a-z0-9-]+):\s*([^;]+);/gi;
+ let match;
+
+ while ((match = varRegex.exec(scssContent)) !== null) {
+ const varName = `--bs-${match[1]}`;
+ let value = match[2].trim();
+ value = value.replace(/#\{[^}]+\}/g, '').trim();
+ value = value.replace(/\/\/.*$/gm, '').trim();
+
+ if (value) {
+ cssVarValues[varName] = value;
+ }
+ }
+
+ return cssVarValues;
+ } catch (error) {
+ console.warn('Could not parse CSS variables from _root.scss:', error);
+ return {};
+ }
+}
+
+// Load utilities metadata
+function loadUtilitiesMetadata(): any {
+ try {
+ const projectRoot = process.cwd();
+ const metadataPath = join(projectRoot, 'dist/css/bootstrap-utilities.metadata.json');
+ const metadataContent = readFileSync(metadataPath, 'utf-8');
+ return JSON.parse(metadataContent);
+ } catch (error) {
+ console.warn('Could not load utilities metadata:', error);
+ return { utilities: {} };
+ }
+}
+
+// Parse compiled CSS to extract styles for given class selectors
+function parseCompiledCSS(classNames: string[]): Record<string, string[]> {
+ try {
+ const projectRoot = process.cwd();
+ const bootstrapCssPath = join(projectRoot, 'dist/css/bootstrap.css');
+ const cssContent = readFileSync(bootstrapCssPath, 'utf-8');
+
+ const classStyles: Record<string, string[]> = {};
+
+ classNames.forEach(className => {
+ // Match ONLY single class selectors: .classname { declarations }
+ const escapedClass = className.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ const selectorRegex = new RegExp(`(?:^|\\n)\\s*\\.${escapedClass}\\s*\\{([^}]+)\\}`, 'gm');
+
+ let match;
+ let foundDeclarations: string[] = [];
+
+ while ((match = selectorRegex.exec(cssContent)) !== null) {
+ const declarations = match[1]
+ .split(';')
+ .map(decl => decl.trim())
+ .filter(decl => decl.length > 0)
+ .map(decl => `${decl};`);
+
+ if (declarations.length > 0) {
+ foundDeclarations = declarations;
+ break;
+ }
+ }
+
+ classStyles[className] = foundDeclarations;
+ });
+
+ return classStyles;
+ } catch (error) {
+ console.warn('Could not parse compiled CSS:', error);
+ return {};
+ }
+}
+
+const cssVarValues = parseCSSVariables();
+const metadata = loadUtilitiesMetadata();
+
+// Collect classes from all specified utilities
+let allClasses: string[] = [];
+
+utilities.forEach(util => {
+ const utilityMeta = metadata.utilities[util];
+
+ if (!utilityMeta) {
+ console.warn(`Utility "${util}" not found in metadata. Available utilities: ${Object.keys(metadata.utilities).join(', ')}`);
+ return;
+ }
+
+ const classes = utilityMeta.classes || [];
+ allClasses = allClasses.concat(classes);
+});
+
+if (allClasses.length === 0) {
+ throw new Error(`No classes found for utilities: ${utilities.join(', ')}`);
+}
+
+const classStyles = parseCompiledCSS(allClasses);
+
+// Function to add CSS variable value comments
+function addVarComments(cssValue: string): string {
+ const comments: string[] = [];
+
+ cssValue.replace(/var\((--[a-z0-9-]+)\)/gi, (match, varName) => {
+ const resolvedValue = cssVarValues[varName];
+ if (resolvedValue) {
+ comments.push(`<span class="color-3">/* ${resolvedValue} */</span>`);
+ }
+ return match;
+ });
+
+ if (comments.length > 0) {
+ const hasSemicolon = cssValue.trimEnd().endsWith(';');
+ return `${cssValue}${hasSemicolon ? '' : ';'} ${comments.join(' ')}`;
+ }
+
+ return cssValue;
+}
+
+// Build table data
+const tableData = allClasses.map(cls => {
+ const styles = classStyles[cls] || [];
+ const formattedStyles = styles.map(style => addVarComments(style)).join('<br/>');
+
+ return {
+ class: `.${cls}`,
+ styles: formattedStyles || '<em>Not found</em>'
+ };
+});
+---
+
+<div class="table-responsive bd-reference-table">
+ <table class={className}>
+ <thead>
+ <tr>
+ <th scope="col">Class</th>
+ <th scope="col">Styles</th>
+ </tr>
+ </thead>
+ <tbody>
+ {tableData.map((row) => (
+ <tr>
+ <td>{row.class}</td>
+ <td><Fragment set:html={row.styles} /></td>
+ </tr>
+ ))}
+ </tbody>
+ </table>
+</div>
Apply any of our included utility classes to our components to customize their appearance, like the navigation
example below. There are hundreds of classes available—from <a href={getVersionedDocsPath('utilities/position')}
>positioning</a
- > and <a href={getVersionedDocsPath('utilities/sizing')}>sizing</a> to <a
+ > and <a href={getVersionedDocsPath('utilities/width')}>sizing</a> to <a
href={getVersionedDocsPath('utilities/colors')}>colors</a
> and <a href={getVersionedDocsPath('utilities/shadows')}>effects</a>. Mix them with CSS variable overrides for
even more control.
| 'info-npm-starter'
| 'info-prefersreducedmotion'
| 'info-sanitizer'
- | 'warning-color-assistive-technologies'
| 'warning-data-bs-title-vs-title'
| 'warning-input-support'
/**
let Content: MarkdownInstance<{}>['Content'] | undefined
if (name) {
- const callout = await getCalloutByName(name)
+ const callout = await getCalloutByName(name) as any
if (!callout) {
throw new Error(`Could not find callout with name '${name}'.`)
}
- const namedCallout = await callout.render()
+ const namedCallout = await callout.render() as any
Content = namedCallout.Content
}
---
--- /dev/null
+# Details Component
+
+The Details component is an expandable/collapsible content component that looks similar to the Callout component but requires a click to reveal the full content. It uses the native HTML `<details>` and `<summary>` elements under the hood.
+
+## Features
+
+- **Expandable/Collapsible**: Content is hidden by default and expands when the summary is clicked
+- **Markdown Support**: Can reference external `.md` files using the `name` prop
+- **Flexible Content**: Accepts inline content via slot or named markdown files
+- **Simple Styling**: Single, unified design that works everywhere
+
+## Usage
+
+### Basic Usage with Inline Content
+
+```astro
+<Details summary="Click to expand">
+ This is the content that will be hidden until the user clicks the summary.
+</Details>
+```
+
+### With Named Content (External Markdown File)
+
+Create a markdown file in `site/src/content/details/` with a `title` in the frontmatter:
+
+```markdown
+<!-- site/src/content/details/my-example.md -->
+---
+title: Click to see more
+---
+
+**This is the content** from an external markdown file.
+
+It supports full markdown formatting including:
+- Lists
+- Links
+- **Bold** and *italic* text
+```
+
+Then use it in your component (the title from frontmatter will be used as the summary):
+
+```astro
+<Details name="my-example" />
+```
+
+You can also override the title with a custom summary:
+
+```astro
+<Details summary="Custom summary text" name="my-example" />
+```
+
+### With Markdown Formatting in Slot
+
+```astro
+<Details summary="Advanced usage">
+ You can use **markdown** formatting, including:
+
+ - Lists
+ - [Links](#)
+ - `code`
+ - And more!
+</Details>
+```
+
+## Props
+
+| Prop | Type | Default | Description |
+|------|------|---------|-------------|
+| `summary` | `string` | *Optional* | The text displayed in the summary (always visible). If not provided, uses the `title` from the markdown frontmatter when `name` is set. |
+| `name` | `string` | `undefined` | Reference to a markdown file in `src/content/details/` |
+
+**Note:** Either `summary` must be provided, or `name` must reference a markdown file with a `title` in its frontmatter.
+
+## Creating Named Content Files
+
+1. Create a new `.md` file in `site/src/content/details/`
+2. Add a `title` in the frontmatter for the summary text
+3. Write your markdown content
+4. Reference it using the `name` prop (without the `.md` extension)
+
+Example:
+
+```bash
+# Create the file
+cat > site/src/content/details/api-notes.md << EOF
+---
+title: API Authentication Notes
+---
+
+**API Note:** This endpoint requires authentication.
+EOF
+```
+
+```astro
+<!-- Use it (title from frontmatter is used automatically) -->
+<Details name="api-notes" />
+
+<!-- Or override the title with a custom summary -->
+<Details summary="Custom summary" name="api-notes" />
+```
+
+## Styling
+
+The Details component has a simple, unified style:
+- `.bd-details` - Base class with neutral, theme-aware styling
+- Uses Bootstrap's tertiary background color
+- Automatically adapts to light and dark modes
+
+The styling is defined in `site/src/scss/_details.scss`.
+
+## Examples
+
+See the [Docs Reference](/docsref/) page for live examples of the Details component in action.
+
+## When to Use
+
+**Use Details when:**
+- Content is supplementary and doesn't need to be immediately visible
+- You want to reduce visual clutter on the page
+- Information is relevant but not critical to understanding the main content
+- You're documenting edge cases, advanced tips, or optional information
+
+**Use Callout instead when:**
+- Information must be immediately visible
+- Content is critical to user success
+- You want to draw immediate attention to important information
--- /dev/null
+---
+import { getDetailsByName } from '@libs/content'
+import type { MarkdownInstance } from 'astro'
+
+interface Props {
+ /**
+ * The name of an existing details content to display located in `src/content/details`.
+ * This will override any content passed in via the default slot.
+ */
+ name?:
+ | 'danger-example'
+ | 'info-example'
+ | 'warning-color-assistive-technologies'
+ | 'warning-example'
+ /**
+ * The summary text displayed before the details are expanded.
+ * If not provided and `name` is set, will use the `title` from the markdown frontmatter.
+ */
+ summary?: string
+}
+
+const { name } = Astro.props
+let { summary } = Astro.props
+
+let Content: MarkdownInstance<{}>['Content'] | undefined
+
+if (name) {
+ const details = await getDetailsByName(name) as any
+
+ if (!details) {
+ throw new Error(`Could not find details with name '${name}'.`)
+ }
+
+ // Use title from frontmatter if summary is not provided
+ if (!summary && details.data?.title) {
+ summary = details.data.title
+ }
+
+ const namedDetails = await details.render() as any
+ Content = namedDetails.Content
+}
+
+// Ensure summary is always provided
+if (!summary) {
+ throw new Error('Details component requires either a `summary` prop or a `title` in the markdown frontmatter.')
+}
+---
+
+<details class="bd-details">
+ <summary class="bd-details-summary">
+ <svg class="bd-details-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
+ <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708"/>
+ </svg>
+ {summary}
+ </summary>
+ <div class="bd-details-content">
+ {Content ? <Content /> : <slot />}
+ </div>
+</details>
+++ /dev/null
-**Accessibility tip:** Using color to add meaning only provides a visual indication, which will not be conveyed to users of assistive technologies like screen readers. Please ensure the meaning is obvious from the content itself (e.g., the visible text with a [_sufficient_ color contrast](/docs/[[config:docs_version]]/getting-started/accessibility/#color-contrast)) or is included through alternative means, such as additional text hidden with the `.visually-hidden` class.
})
.array()
.optional(),
+ utility: z.union([z.string(), z.string().array()]).optional(),
+ classes: z
+ .object({
+ class: z.string(),
+ description: z.string()
+ })
+ .array()
+ .optional(),
sections: z
.object({
description: z.string(),
schema: calloutsSchema
})
+const detailsSchema = z.object({
+ title: z.string().optional()
+})
+
+const detailsCollection = defineCollection({
+ schema: detailsSchema
+})
+
export const collections = {
docs: docsCollection,
- callouts: calloutsCollection
+ callouts: calloutsCollection,
+ details: detailsCollection
}
--- /dev/null
+---
+title: "Accessibility Tip: Using color to convey meaning"
+---
+
+Using color to add meaning only provides a visual indication, which will not be conveyed to users of assistive technologies like screen readers. Please ensure the meaning is obvious from the content itself (e.g., the visible text with a [_sufficient_ color contrast](/docs/[[config:docs_version]]/getting-started/accessibility/#color-contrast)) or is included through alternative means, such as additional text hidden with the `.visually-hidden` class.
A simple ${themeColor.name} alert—check it out!
</div>`)} />
-<Callout name="warning-color-assistive-technologies" />
+<Details name="warning-color-assistive-technologies" />
### Live example
<Example code={getData('theme-colors').map((themeColor) => `<span class="badge theme-${themeColor.name}">${themeColor.title}</span>`)} />
<Example code={getData('theme-colors').map((themeColor) => `<span class="badge badge-subtle theme-${themeColor.name}">${themeColor.title}</span>`)} />
-<Callout name="warning-color-assistive-technologies" />
+<Details name="warning-color-assistive-technologies" />
## Pill badges
`), `
<button type="button" class="btn btn-link">Link</button>`]} />
-<Callout name="warning-color-assistive-technologies" />
+<Details name="warning-color-assistive-technologies" />
## Disable text wrapping
## Example
-Cards are built with as little markup and styles as possible, but still manage to deliver a ton of control and customization. Built with flexbox, they offer easy alignment and mix well with other Bootstrap components. They have no `margin` by default, so use [spacing utilities]([[docsref:/utilities/spacing]]) as needed.
+Cards are built with as little markup and styles as possible, but still manage to deliver a ton of control and customization. Built with flexbox, they offer easy alignment and mix well with other Bootstrap components. They have no `margin` by default, so use [margin utilities]([[docsref:/utilities/margin]]) as needed.
Below is an example of a basic card with mixed content and a fixed width. Cards have no fixed width to start, so they’ll naturally fill the full width of its parent element. This is easily customized with our various [sizing options](#sizing).
### Using utilities
-Use our handful of [available sizing utilities]([[docsref:/utilities/sizing]]) to quickly set a card’s width.
+Use our handful of [available sizing utilities]([[docsref:/utilities/width]]) to quickly set a card’s width.
<Example code={`<div class="card w-75 mb-3">
<div class="card-body">
## Text alignment
-You can quickly change the text alignment of any card—in its entirety or specific parts—with our [text align classes]([[docsref:/utilities/text#text-alignment]]).
+You can quickly change the text alignment of any card—in its entirety or specific parts—with our [text align classes]([[docsref:/utilities/text-alignment]]).
<Example code={`<div class="card mb-3" style="width: 18rem;">
<div class="card-body">
</div>
</div>`)} />
-<Callout name="warning-color-assistive-technologies" />
+<Details name="warning-color-assistive-technologies" />
### Border
## Horizontal
-The collapse plugin supports horizontal collapsing. Add the `.collapse-horizontal` modifier class to transition the `width` instead of `height` and set a `width` on the immediate child element. Feel free to write your own custom Sass, use inline styles, or use our [width utilities]([[docsref:/utilities/sizing]]).
+The collapse plugin supports horizontal collapsing. Add the `.collapse-horizontal` modifier class to transition the `width` instead of `height` and set a `width` on the immediate child element. Feel free to write your own custom Sass, use inline styles, or use our [width utilities]([[docsref:/utilities/width]]).
<Callout>
Please note that while the example below has a `min-height` set to avoid excessive repaints in our docs, this is not explicitly required. **Only the `width` on the child element is required.**
### Text
-Place any freeform text within a dropdown menu with text and use [spacing utilities]([[docsref:/utilities/spacing]]). Note that you’ll likely need additional sizing styles to constrain the menu width.
+Place any freeform text within a dropdown menu with text and use [margin]([[docsref:/utilities/margin]]) and [padding]([[docsref:/utilities/padding]]) utilities. Note that you’ll likely need additional sizing styles to constrain the menu width.
<Example code={`<div class="dropdown-menu p-4 text-body-secondary" style="max-width: 200px;">
<p>
### Forms
-Put a form within a dropdown menu, or make it into a dropdown menu, and use [margin or padding utilities]([[docsref:/utilities/spacing]]) to give it the negative space you require.
+Put a form within a dropdown menu, or make it into a dropdown menu, and use [margin]([[docsref:/utilities/margin]]) and [padding]([[docsref:/utilities/padding]]) utilities to give it the negative space you require.
<Example code={`<div class="dropdown-menu">
<form class="px-4 py-3">
`</div>`
]} />
-<Callout name="warning-color-assistive-technologies" />
+<Details name="warning-color-assistive-technologies" />
## With badges
```
<Callout>
-In the above static example, we use `<h5>`, to avoid issues with the heading hierarchy in the documentation page. Structurally, however, a modal dialog represents its own separate document/context, so the `.modal-title` should ideally be an `<h1>`. If necessary, you can use the [font size utilities]([[docsref:/utilities/text#font-size]]) to control the heading’s appearance. All the following live examples use this approach.
+In the above static example, we use `<h5>`, to avoid issues with the heading hierarchy in the documentation page. Structurally, however, a modal dialog represents its own separate document/context, so the `.modal-title` should ideally be an `<h1>`. If necessary, you can use the [font size utilities]([[docsref:/utilities/font-size]]) to control the heading’s appearance. All the following live examples use this approach.
</Callout>
### Live demo
- 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.
+- Use our [margin]([[docsref:/utilities/margin]]), [padding]([[docsref:/utilities/padding]]), 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.
- Ensure accessibility by using a `<nav>` element or, if using a more generic element such as a `<div>`, add a `role="navigation"` to every navbar to explicitly identify it as a landmark region for users of assistive technologies.
- Indicate the current item by using `aria-current="page"` for the current page or `aria-current="true"` for the current item in a set.
</div>
</nav>`} />
-This example uses [background]([[docsref:/utilities/background]]) (`bg-body-tertiary`) and [spacing]([[docsref:/utilities/spacing]]) (`me-auto`, `mb-2`, `mb-lg-0`, `me-2`) utility classes.
+This example uses [background]([[docsref:/utilities/background]]) (`bg-body-tertiary`) and [margin]([[docsref:/utilities/margin]]) (`me-auto`, `mb-2`, `mb-lg-0`, `me-2`) utility classes.
### Brand
### Width
-Bootstrap provides a handful of [utilities for setting width]([[docsref:/utilities/sizing]]). Depending on your needs, these may help with quickly configuring the width of the `.progress-bar`.
+Bootstrap provides a handful of [utilities for setting width]([[docsref:/utilities/width]]). Depending on your needs, these may help with quickly configuring the width of the `.progress-bar`.
<Example code={`<div class="progress" role="progressbar" aria-label="Basic example" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100">
<div class="progress-bar w-75"></div>
<div class="progress-bar bg-danger" style="width: 100%"></div>
</div>`} />
-<Callout name="warning-color-assistive-technologies" />
+<Details name="warning-color-assistive-technologies" />
If you’re adding labels to progress bars with a custom background color, make sure to also set an appropriate [text color]([[docsref:/utilities/colors#colors]]), so the labels remain readable and have sufficient contrast. We recommend using the [color and background]([[docsref:/helpers/color-background]]) helper classes.
### Placement
-Use [flexbox utilities][flex], [float utilities][float], or [text alignment][text] utilities to place spinners exactly where you need them in any situation.
+Use [flexbox utilities][flex], [float utilities][float], or [text alignment][text-alignment] utilities to place spinners exactly where you need them in any situation.
#### Flex
<ScssDocs name="spinner-grow-keyframes" file="scss/_spinners.scss" />
-[color]: [[docsref:/utilities/colors]]
-[flex]: [[docsref:/utilities/flex]]
-[float]: [[docsref:/utilities/float]]
-[margin]: [[docsref:/utilities/spacing]]
-[text]: [[docsref:/utilities/text]]
+[color]: [[docsref:/utilities/colors]]
+[flex]: [[docsref:/utilities/flex]]
+[float]: [[docsref:/utilities/float]]
+[margin]: [[docsref:/utilities/margin]]
+[text-alignment]: [[docsref:/utilities/text-alignment]]
<figcaption class="figure-caption">A caption for the above image.</figcaption>
</figure>`} />
-Aligning the figure’s caption is easy with our [text utilities]([[docsref:/utilities/text#text-alignment]]).
+Aligning the figure’s caption is easy with our [text utilities]([[docsref:/utilities/text-alignment]]).
<Example code={`<figure class="figure">
<Placeholder width="400" height="300" class="figure-img img-fluid rounded" />
## Aligning images
-Align images with the [helper float classes]([[docsref:/utilities/float]]) or [text alignment classes]([[docsref:/utilities/text#text-alignment]]). `block`-level images can be centered using [the `.mx-auto` margin utility class]([[docsref:/utilities/spacing#horizontal-centering]]).
+Align images with the [helper float classes]([[docsref:/utilities/float]]) or [text alignment classes]([[docsref:/utilities/text-alignment]]). `block`-level images can be centered using [the `.mx-auto` margin utility class]([[docsref:/utilities/margin#horizontal-centering]]).
<Example code={`<Placeholder width="200" height="200" class="rounded float-start" />
<Placeholder width="200" height="200" class="rounded float-end" />`} />
`</tr>`
]} lang="html" />
-<Callout name="warning-color-assistive-technologies" />
+<Details name="warning-color-assistive-technologies" />
## Accented tables
## Global settings
-Bootstrap sets basic global display, typography, and link styles. When more control is needed, check out the [textual utility classes]([[docsref:/utilities/text]]).
+Bootstrap sets basic global display, typography, and link styles. When more control is needed, check out our text utilities.
- Use a [native font stack]([[docsref:/content/reboot#native-font-stack]]) that selects the best `font-family` for each OS and device.
- For a more inclusive and accessible type scale, we use the browser’s default root `font-size` (typically 16px) so visitors can customize their browser defaults as needed.
- Use the `$font-family-base`, `$font-size-base`, and `$line-height-base` attributes as our typographic base applied to the `<body>`.
-- Set the global link color via `$link-color`.
-- Use `$body-bg` to set a `background-color` on the `<body>` (`#fff` by default).
+- Set the global link color via `--bs-link-color`.
+- Use `--bs-body-bg` to set a `background-color` on the `<body>` (`#fff` by default).
These styles can be found within `_reboot.scss`, and the global variables are defined in `_variables.scss`. Make sure to set `$font-size-base` in `rem`.
<p class="h5">h5. Bootstrap heading</p>
<p class="h6">h6. Bootstrap heading</p>`} />
+Head to our [font size utilities]([[docsref:/utilities/font-size]]) for more control over the `font-size` and `line-height`.
+
### Customizing headings
Use the included utility classes to recreate the small secondary heading text from Bootstrap 3.
<small class="text-body-secondary">With faded secondary text</small>
</h3>`} />
-## Display headings
-
-Traditional heading elements are designed to work best in the meat of your page content. When you need a heading to stand out, consider using a **display heading**—a larger, slightly more opinionated heading style.
-
-<Example showMarkup={false} code={`
-<div class="display-1 pb-3 mb-3 border-bottom">Display 1</div>
-<div class="display-2 pb-3 mb-3 border-bottom">Display 2</div>
-<div class="display-3 pb-3 mb-3 border-bottom">Display 3</div>
-<div class="display-4 pb-3 mb-3 border-bottom">Display 4</div>
-<div class="display-5 pb-3 mb-3 border-bottom">Display 5</div>
-<div class="display-6">Display 6</div>
-`} />
-
-```html
-<h1 class="display-1">Display 1</h1>
-<h1 class="display-2">Display 2</h1>
-<h1 class="display-3">Display 3</h1>
-<h1 class="display-4">Display 4</h1>
-<h1 class="display-5">Display 5</h1>
-<h1 class="display-6">Display 6</h1>
-```
-
-Display headings are configured via the `$display-font-sizes` Sass map and two variables, `$display-font-weight` and `$display-line-height`.
-
-Display headings are customizable via two variables, `$display-font-family` and `$display-font-style`.
-
-<ScssDocs name="display-headings" file="scss/_variables.scss" />
-
-## Lead
-
-Make a paragraph stand out by adding `.lead`.
-
-<Example code={`<p class="lead">
- This is a lead paragraph. It stands out from regular paragraphs.
- </p>`} />
-
## Inline text elements
Styling for common inline HTML5 elements.
## Text utilities
-Change text alignment, transform, style, weight, line-height, decoration and color with our [text utilities]([[docsref:/utilities/text]]) and [color utilities]([[docsref:/utilities/colors]]).
+Utility classes are available for most common text-related CSS properties.
+
+- [Font family]([[docsref:/utilities/font-family]])
+- [Font size]([[docsref:/utilities/font-size]])
+- [Font style]([[docsref:/utilities/font-style]])
+- [Font weight]([[docsref:/utilities/font-weight]])
+- [Line height]([[docsref:/utilities/line-height]])
+- [Text alignment]([[docsref:/utilities/text-alignment])
+- [Text transform]([[docsref:/utilities/text-transform])
+- [Text decoration]([[docsref:/utilities/text-decoration])
+- [Text wrapping]([[docsref:/utilities/text-wrapping])
+- [Vertical alignment]([[docsref:/utilities/vertical-align]])
+
+Change text alignment, transform, style, weight, line-height, decoration and color with our text and [color utilities]([[docsref:/utilities/colors]]).
## Abbreviations
<div class="grid gap-0" style={{gridTemplateColumns: 'repeat(13, 1fr)', gap: '4px', minWidth: '0'}}>
{getData('colors').map((color) => {
return (
- <div class="d-contents grid-full">
- <h5 class="d-block text-capitalize grid-full">{color.name.replace('-', ' ')}</h5>
+ <div class="d-contents grid-cols-fill">
+ <h5 class="d-block text-capitalize grid-cols-fill">{color.name.replace('-', ' ')}</h5>
{["025", "050", ...getSequence(100, 900, 100), 950, 975].map((value) => {
return (
<div class="mb-3 font-monospace small">
<Swatch bg={`${color.name}-${value}`} size="medium" />
- <div class="text-center color-3">{value}</div>
+ <div class="text-center fg-3">{value}</div>
</div>
)
})}
)
})}
- <div class="d-contents grid-full">
- <h5 class="d-block text-capitalize grid-full">Additional</h5>
+ <div class="d-contents grid-cols-fill">
+ <h5 class="d-block text-capitalize grid-cols-fill">Additional</h5>
{additionalColors.map((color) => {
return (
<div class="mb-3 font-monospace small">
<Swatch bg={`${color}`} size="medium" />
- <div class="text-center color-3">{color}</div>
+ <div class="text-center fg-3">{color}</div>
</div>
)
})}
<BsTable class="table table-options">
| Variable | Values | Description |
| ------------------------------ | ---------------------------------- | -------------------------------------------------------------------------------------- |
-| `$spacer` | `1rem` (default), or any value > 0 | Specifies the default spacer value to programmatically generate our [spacer utilities]([[docsref:/utilities/spacing]]). |
+| `$spacer` | `1rem` (default), or any value > 0 | Specifies the default spacer value to programmatically generate our [margin]([[docsref:/utilities/margin]]), [padding]([[docsref:/utilities/padding]]), and [gap]([[docsref:/utilities/gap]]) utilities. |
| `$enable-dark-mode` | `true` (default) or `false` | Enables built-in [dark mode support]([[docsref:/customize/color-modes#dark-mode]]) across the project and its components. |
| `$enable-rounded` | `true` (default) or `false` | Enables predefined `border-radius` styles on various components. |
| `$enable-shadows` | `true` or `false` (default) | Enables predefined decorative `box-shadow` styles on various components. Does not affect `box-shadow`s used for focus states. |
| `$enable-button-pointers` | `true` (default) or `false` | Add “hand” cursor to non-disabled button elements. |
| `$enable-rfs` | `true` (default) or `false` | Globally enables [RFS]([[docsref:/getting-started/rfs]]). |
| `$enable-validation-icons` | `true` (default) or `false` | Enables `background-image` icons within textual inputs and some custom forms for validation states. |
-| `$enable-negative-margins` | `true` or `false` (default) | Enables the generation of [negative margin utilities]([[docsref:/utilities/spacing#negative-margin]]). |
+| `$enable-negative-margins` | `true` or `false` (default) | Enables the generation of [negative margin utilities]([[docsref:/utilities/margin#negative-margin]]). |
| `$enable-deprecation-messages` | `true` (default) or `false` | Set to `false` to hide warnings when using any of the deprecated mixins and functions that are planned to be removed in `v6`. |
| `$enable-smooth-scroll` | `true` (default) or `false` | Applies `scroll-behavior: smooth` globally, except for users asking for reduced motion through [`prefers-reduced-motion` media query]([[docsref:/getting-started/accessibility#reduced-motion]]) |
</BsTable>
<div class="grid gap-0" style={{gridTemplateColumns: 'repeat(9, 1fr)', gap: '8px', minWidth: '0'}}>
{getData('theme-colors').map((color) => {
return (
- <div class="d-contents grid-full">
- <h6 class="d-block text-capitalize grid-full">{color.title}</h6>
+ <div class="d-contents grid-cols-fill">
+ <h6 class="d-block text-capitalize grid-cols-fill">{color.title}</h6>
{themeTokens.map((token) => (
<div class="mb-3 font-monospace">
<Swatch bg={`${color.name}-${token}`} size="medium" />
- <div class="text-center small color-3">{token}</div>
+ <div class="text-center small fg-3">{token}</div>
</div>
))}
</div>
Not all colors can be used for all purposes due to accessibility, color contrast, and general aesthetic considerations. Here are some recommended pairings.
-- `color-body` works with all `bg` colors
-- `color-1` works with `bg-body`, `bg-1`, `bg-2`, and `bg-3`
-- `color-2` works with `bg-body`, `bg-1`, and `bg-2`
-- `color-3` works with `bg-body`, `bg-1`
+- `fg-body` works with all `bg` colors
+- `fg-1` works with `bg-body`, `bg-1`, `bg-2`, and `bg-3`
+- `fg-2` works with `bg-body`, `bg-1`, and `bg-2`
+- `fg-3` works with `bg-body`, `bg-1`
Here are some examples showing them together. Note
<Example code={`<div class="vstack gap-3">
- <div class="p-3 rounded-3 bg-body color-body border">
- color-body on bg-body
+ <div class="p-3 rounded-3 bg-body fg-body border">
+ fg-body on bg-body
</div>
- <div class="p-3 rounded-3 bg-1 color-3 border">
- color-3 on bg-1
+ <div class="p-3 rounded-3 bg-1 fg-3 border">
+ fg-3 on bg-1
</div>
- <div class="p-3 rounded-3 bg-2 color-2 border">
- color-2 on bg-2
+ <div class="p-3 rounded-3 bg-2 fg-2 border">
+ fg-2 on bg-2
</div>
- <div class="p-3 rounded-3 bg-3 color-1 border">
- color-1 on bg-3
+ <div class="p-3 rounded-3 bg-3 fg-1 border">
+ fg-1 on bg-3
</div>
</div>`} />
Danger callout
</Callout>
+## Details
+
+<Details summary="Click to expand inline content">
+ This is inline details content. It supports **markdown** formatting and will be hidden until clicked.
+</Details>
+
## Code example
```scss
## Utilities
-[Margin utilities]([[docsref:/utilities/spacing]]) are the easiest way to add some structure to forms. They provide basic grouping of labels, controls, optional form text, and form validation messaging. We recommend sticking to `margin-bottom` utilities, and using a single direction throughout the form for consistency.
+[Margin utilities]([[docsref:/utilities/margin]]) are the easiest way to add some structure to forms. They provide basic grouping of labels, controls, optional form text, and form validation messaging. We recommend sticking to `margin-bottom` utilities, and using a single direction throughout the form for consistency.
Feel free to build your forms however you like, with `<fieldset>`s, `<div>`s, or nearly any other element.
<Example code={getData('theme-colors').map((themeColor) => `<div class="text-bg-${themeColor.name} p-3">${themeColor.title} with contrasting color</div>`)} />
-<Callout name="warning-color-assistive-technologies" />
+<Details name="warning-color-assistive-technologies" />
## With components
`<p><a href="#" class="link-body-emphasis">Emphasis link</a></p>`
]} />
-<Callout name="warning-color-assistive-technologies" />
+<Details name="warning-color-assistive-technologies" />
## Link utilities
Stacks offer a shortcut for applying a number of flexbox properties to quickly and easily create layouts in Bootstrap. All credit for the concept and implementation goes to the open source [Pylon project](https://almonk.github.io/pylon/).
-<Callout type="warning">
-**Heads up!** Support for gap utilities with flexbox isn’t available in Safari prior to 14.5, so consider verifying your intended browser support. Grid layout should have no issues. [Read more](https://caniuse.com/flexbox-gap).
-</Callout>
-
## Vertical
Use `.vstack` to create vertical layouts. Stacked items are full-width by default. Use `.gap-*` utilities to add space between items.
Use `.vstack` to stack buttons and other elements:
<Example code={`<div class="vstack gap-2 col-md-5 mx-auto">
- <button type="button" class="btn btn-secondary">Save changes</button>
- <button type="button" class="btn btn-outline-secondary">Cancel</button>
+ <button type="button" class="btn-solid theme-primary">Save changes</button>
+ <button type="button" class="btn-outline theme-secondary">Cancel</button>
</div>`} />
Create an inline form with `.hstack`:
<Example code={`<div class="hstack gap-3">
<input class="form-control me-auto" type="text" placeholder="Add your item here..." aria-label="Add your item here...">
- <button type="button" class="btn btn-secondary">Submit</button>
- <div class="vr"></div>
- <button type="button" class="btn btn-outline-danger">Reset</button>
+ <button type="button" class="btn-solid theme-secondary">Submit</button>
+ <div class="vr my-2"></div>
+ <button type="button" class="btn-subtle theme-danger">Reset</button>
</div>`} />
## CSS
### Offsetting columns
-You can offset grid columns in two ways: our responsive `.offset-` grid classes and our [margin utilities]([[docsref:/utilities/spacing]]). Grid classes are sized to match columns while margins are more useful for quick layouts where the width of the offset is variable.
+You can offset grid columns in two ways: our responsive `.offset-` grid classes and our [margin utilities]([[docsref:/utilities/margin]]). Grid classes are sized to match columns while margins are more useful for quick layouts where the width of the offset is variable.
#### Offset classes
<div class="g-col-4">.g-col-4</div>
</div>`} />
+<Example class="bd-example-cssgrid" code={`<div class="grid text-center">
+ <div class="g-col-auto">.g-col-auto</div>
+ <div class="g-col-auto">.g-col-auto</div>
+ <div class="g-col-auto">.g-col-auto</div>
+ </div>`} />
+
### Responsive
Use responsive classes to adjust your layout across viewports. Here we start with two columns on the narrowest viewports, and then grow to three columns on medium viewports and above.
- **Columns are incredibly flexible.** There are 12 template columns available per row, allowing you to create different combinations of elements that span any number of columns. Column classes indicate the number of template columns to span (e.g., `col-4` spans four). `width`s are set in percentages so you always have the same relative sizing.
-- **Gutters are also responsive and customizable.** [Gutter classes are available]([[docsref:/layout/gutters]]) across all breakpoints, with all the same sizes as our [margin and padding spacing]([[docsref:/utilities/spacing]]). Change horizontal gutters with `.gx-*` classes, vertical gutters with `.gy-*`, or all gutters with `.g-*` classes. `.g-0` is also available to remove gutters.
+- **Gutters are also responsive and customizable.** [Gutter classes are available]([[docsref:/layout/gutters]]) across all breakpoints, with all the same sizes as our [margin]([[docsref:/utilities/margin]]) and [padding]([[docsref:/utilities/padding]]) utilities. Change horizontal gutters with `.gx-*` classes, vertical gutters with `.gy-*`, or all gutters with `.g-*` classes. `.g-0` is also available to remove gutters.
- **Sass variables, maps, and mixins power the grid.** If you don’t want to use the predefined grid classes in Bootstrap, you can use our [grid’s source Sass](#sass-variables) to create your own with more semantic markup. We also include some CSS custom properties to consume these Sass variables for even greater flexibility for you.
- **Gutters are the gaps between column content, created by horizontal `padding`.** We set `padding-right` and `padding-left` on each column, and use negative `margin` to offset that at the start and end of each row to align content.
-- **Gutters start at `1.5rem` (`24px`) wide.** This allows us to match our grid to the [padding and margin spacers]([[docsref:/utilities/spacing]]) scale.
+- **Gutters start at `1.5rem` (`24px`) wide.** This allows us to match our grid to the [margin]([[docsref:/utilities/margin]]) and [padding]([[docsref:/utilities/padding]]) utilities scale.
- **Gutters can be responsively adjusted.** Use breakpoint-specific gutter classes to modify horizontal gutters, vertical gutters, and all gutters.
## Margin and padding
-Use the `margin` and `padding` [spacing utilities]([[docsref:/utilities/spacing]]) to control how elements and components are spaced and sized. Bootstrap includes a six-level scale for spacing utilities, based on a `1rem` value default `$spacer` variable. Choose values for all viewports (e.g., `.me-3` for `margin-right: 1rem` in LTR), or pick responsive variants to target specific viewports (e.g., `.me-md-3` for `margin-right: 1rem` —in LTR— starting at the `md` breakpoint).
+Use the [margin]([[docsref:/utilities/margin]]) and [padding]([[docsref:/utilities/padding]]) utilities to control how elements and components are spaced and sized. Bootstrap includes a six-level scale for spacing utilities, based on a `1rem` value default `$spacer` variable. Choose values for all viewports (e.g., `.me-3` for `margin-right: 1rem` in LTR), or pick responsive variants to target specific viewports (e.g., `.me-md-3` for `margin-right: 1rem` —in LTR— starting at the `md` breakpoint).
## Toggle `visibility`
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
+utility:
+ - align-content
---
import { getData } from '@libs/data'
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
+utility:
+ - align-items
---
import { getData } from '@libs/data'
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
+utility:
+ - align-self
---
import { getData } from '@libs/data'
Use the `values` key to specify which values for the specified `property` should be used in the generated class names and rules. Can be a list or map (set in the utilities or in a Sass variable).
-As a list, like with [`text-decoration` utilities]([[docsref:/utilities/text#text-decoration]]):
+As a list, like with [`text-decoration` utilities]([[docsref:/utilities/text-decoration]]):
```scss
values: none underline line-through
description: Make elements maintain specific aspect ratios. Perfect for handling videos, slideshow embeds, and more based on the width of the parent.
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio
-reference:
- - class: ratio-auto
- styles:
- --bs-ratio: 'auto'
- - class: ratio-1x1
- styles:
- --bs-ratio: '1 / 1'
- - class: ratio-4x3
- styles:
- --bs-ratio: '4 / 3'
- - class: ratio-16x9
- styles:
- --bs-ratio: '16 / 9'
- - class: ratio-21x9
- styles:
- --bs-ratio: '21 / 9'
+utility:
+ - aspect-ratio
---
Use the ratio utility to manage the aspect ratios of content like `<iframe>`s, `<embed>`s, `<video>`s, and `<object>`s. These helpers also can be used on any standard HTML child element (e.g., a `<div>` or `<img>`). Customize the available aspect ratios with the Sass variable or the utility API.
description: Convey meaning through `background-color` and add decoration with gradients.
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/background-color
+utility:
+ - bg-color
+ - bg-color-muted
+ - bg-color-subtle
+ - bg-opacity
+ - gradient
---
import { getData } from '@libs/data'
-<Callout name="warning-color-assistive-technologies" />
+<Details name="warning-color-assistive-technologies" />
-## Background color
+## Colors
-Similar to the contextual text color classes, set the background of an element to any contextual class. Background utilities **do not set `color`**, so in some cases you’ll want to use `.text-*` [color utilities]([[docsref:/utilities/colors]]).
+Change the `background-color` using utilities built on our theme colors using `.bg-{color}`, `.bg-muted-{color}`, and `.bg-subtle-{color}`. All these background color utilities set the `background-color` property to a local CSS variable, `--bs-bg`, which has the value of the theme color. Most color values also use `light-dark()` to ensure sufficient contrast in both light and dark color modes.
-<Callout>
-Background utilities like `.bg-*` that generated from our original `$theme-colors` Sass map don’t yet respond to color modes, however, any `.bg-*-subtle` utility will. This will be resolved in v6.
-</Callout>
+For example, `.bg-primary` sets the `--bs-bg` variable to `var(--bs-primary-500)`:
+
+```css
+.bg-primary {
+ --bs-bg: var(--bs-primary-500);
+ background-color: var(--bs-bg);
+}
+```
+
+This approach allows us to also easily support translucency with our `.bg-{opacity}` utilities as we can use `color-mix()` with the CSS variable to generate the appropriate color. See the [opacity section](#opacity) for more details.
<Example code={[
- ...getData('theme-colors').map((themeColor) => `<div class="p-3 mb-2 bg-${themeColor.name} text-white">.bg-${themeColor.name}</div>
-<div class="p-3 mb-2 bg-${themeColor.name}-subtle text-${themeColor.name}-emphasis">.bg-${themeColor.name}-subtle</div>`),
- `<div class="p-3 mb-2 bg-body-secondary">.bg-body-secondary</div>
-<div class="p-3 mb-2 bg-body-tertiary">.bg-body-tertiary</div>
-<div class="p-3 mb-2 bg-body text-body">.bg-body</div>
+ ...getData('theme-colors').map((themeColor) => `<div class="p-3 mb-2 bg-${themeColor.name} color-on-${themeColor.name}">.bg-${themeColor.name}</div>
+<div class="p-3 mb-2 bg-muted-${themeColor.name} color-${themeColor.name}">.bg-muted-${themeColor.name}</div>
+<div class="p-3 mb-2 bg-subtle-${themeColor.name} color-${themeColor.name}">.bg-subtle-${themeColor.name}</div>`),
+ `<div class="p-3 mb-2 bg-body text-body">.bg-body</div>
<div class="p-3 mb-2 bg-black text-white">.bg-black</div>
<div class="p-3 mb-2 bg-white text-dark">.bg-white</div>
<div class="p-3 mb-2 bg-transparent text-body">.bg-transparent</div>`
## Opacity
-As of v5.1.0, `background-color` utilities are generated with Sass using CSS variables. This allows for real-time color changes without compilation and dynamic alpha transparency changes.
-
-### How it works
-
-Consider our default `.bg-success` utility.
-
-```css
-.bg-success {
- --bs-bg-opacity: 1;
- background-color: rgba(var(--bs-success-rgb), var(--bs-bg-opacity));
-}
-```
-
-We use an RGB version of our `--bs-success` (with the value of `25, 135, 84`) CSS variable and attached a second CSS variable, `--bs-bg-opacity`, for the alpha transparency (with a default value `1` thanks to a local CSS variable). That means anytime you use `.bg-success` now, your computed `color` value is `rgba(25, 135, 84, 1)`. The local CSS variable inside each `.bg-*` class avoids inheritance issues so nested instances of the utilities don’t automatically have a modified alpha transparency.
-
-### Example
-
-To change that opacity, override `--bs-bg-opacity` via custom styles or inline styles.
-
-<Example code={`<div class="bg-success p-2 text-white">This is default success background</div>
-<div class="bg-success p-2" style="--bs-bg-opacity: .5;">This is 50% opacity success background</div>`} />
-
-Or, choose from any of the `.bg-opacity` utilities:
-
-<Example code={`<div class="bg-success p-2 text-white">This is default success background</div>
-<div class="bg-success p-2 text-white bg-opacity-75">This is 75% opacity success background</div>
-<div class="bg-success p-2 text-dark bg-opacity-50">This is 50% opacity success background</div>
-<div class="bg-success p-2 text-dark bg-opacity-25">This is 25% opacity success background</div>
-<div class="bg-success p-2 text-dark bg-opacity-10">This is 10% opacity success background</div>`} />
+Change the opacity of a background color by using any of the `.bg-<percentage>` utilities which use `color-mix()` to mix the background color with `transparent`.
+
+<Example class="d-flex flex-column gap-2" code={`<div class="bg-success p-2 text-white">This is default success background</div>
+<div class="bg-success p-2 text-white bg-90">This is 90% opacity success background</div>
+<div class="bg-success p-2 text-white bg-80">This is 80% opacity success background</div>
+<div class="bg-success p-2 text-white bg-70">This is 70% opacity success background</div>
+<div class="bg-success p-2 text-white bg-60">This is 60% opacity success background</div>
+<div class="bg-success p-2 text-dark bg-50">This is 50% opacity success background</div>
+<div class="bg-success p-2 text-dark bg-40">This is 40% opacity success background</div>
+<div class="bg-success p-2 text-dark bg-30">This is 30% opacity success background</div>
+<div class="bg-success p-2 text-dark bg-20">This is 20% opacity success background</div>
+<div class="bg-success p-2 text-dark bg-10">This is 10% opacity success background</div>`} />
## CSS
--- /dev/null
+---
+title: Border color
+description: Utilities for controlling border color and opacity.
+toc: true
+alias:
+ - /docs/5.3/utilities/border-color/
+mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/border-color
+utility:
+ - border-color
+ - border-color-subtle
+ - border-opacity
+---
+
+import { getData } from '@libs/data'
+
+## Colors
+
+Change the `border-color` using utilities built on our theme colors using `.border-{color}` and `.border-subtle-{color}`. All these border color utilities set the `border-color` property to a local CSS variable, `--bs-border-color`, which has the value of the theme color. Color values also use `light-dark()` to ensure sufficient contrast in both light and dark color modes.
+
+For example, `.border-primary` sets the `--bs-border-color` variable to `var(--bs-blue-500)`:
+
+```css
+.border-primary {
+ --bs-border-color: var(--bs-blue-500);
+ border-color: var(--bs-border-color);
+}
+```
+
+This approach allows us to also easily support translucency with our `.border-{opacity}` utilities as we can use `color-mix()` with the CSS variable to generate the appropriate color. See the [opacity section](#opacity) for more details.
+
+<Example class="d-flex flex-column gap-2 bd-example-border-color-utils" code={[
+ ...getData('theme-colors').map((themeColor) => `<span class="border border-5 border-${themeColor.name}">${themeColor.name}</span>
+<span class="border border-5 border-subtle-${themeColor.name}">${themeColor.name} subtle</span>`),
+ `<span class="border border-5 border-bg">bg</span>
+ <span class="border border-5 border-body">body</span>
+ <span class="border border-5 border-muted">muted</span>
+ <span class="border border-5 border-subtle">subtle</span>
+ <span class="border border-5 border-emphasized">emphasized</span>
+ <span class="border border-5 border-black">black</span>
+<span class="border border-5 border-white">white</span>`
+]} />
+
+Or modify the default `border-color` of a component:
+
+<Example code={`<div class="mb-4">
+ <label for="exampleFormControlInput1" class="form-label">Email address</label>
+ <input type="email" class="form-control border-success" id="exampleFormControlInput1" placeholder="name@example.com">
+ </div>
+
+ <div class="h4 pb-2 mb-4 text-danger border-bottom border-danger">
+ Dangerous heading
+ </div>
+
+ <div class="p-3 bg-info bg-10 border border-info border-start-0 rounded-end">
+ Changing border color and width
+ </div>`} />
+
+## Opacity
+
+Change the opacity of a border color by using any of the `.border-<percentage>` utilities which use `color-mix()` to mix the border color with `transparent` thanks to the CSS variable approach mentioned above.
+
+<Example code={`<div class="border border-5 border-primary p-2 mb-2">Default border</div>
+<div class="border border-5 border-primary border-90 p-2 mb-2">90% opacity</div>
+<div class="border border-5 border-primary border-80 p-2 mb-2">80% opacity</div>
+<div class="border border-5 border-primary border-70 p-2 mb-2">70% opacity</div>
+<div class="border border-5 border-primary border-60 p-2 mb-2">60% opacity</div>
+<div class="border border-5 border-primary border-50 p-2 mb-2">50% opacity</div>
+<div class="border border-5 border-primary border-40 p-2 mb-2">40% opacity</div>
+<div class="border border-5 border-primary border-30 p-2 mb-2">30% opacity</div>
+<div class="border border-5 border-primary border-20 p-2 mb-2">20% opacity</div>
+<div class="border border-5 border-primary border-10 p-2">10% opacity</div>`} />
+
+## CSS
+
+### Variables
+
+<ScssDocs name="root-border-var" file="scss/_root.scss" />
+
+### Sass variables
+
+Variables for setting `border-color` in `.border-*-subtle` utilities in light and dark mode:
+
+{/* <ScssDocs name="theme-border-subtle-variables" file="scss/_variables.scss" /> */}
+
+{/* <ScssDocs name="theme-border-subtle-dark-variables" file="scss/_variables-dark.scss" /> */}
+
+### Sass utilities API
+
+Border color utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
+
+<ScssDocs name="utils-border-color" file="scss/_utilities.scss" />
description: Use border radius…
toc: true
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius
-reference:
- - class: rounded
- styles:
- border-radius: 'var(--bs-border-radius)'
- - class: rounded-top
- styles:
- border-top-left-radius: 'var(--bs-border-radius)'
- border-top-right-radius: 'var(--bs-border-radius)'
- - class: rounded-end
- styles:
- border-bottom-right-radius: 'var(--bs-border-radius)'
- border-top-right-radius: 'var(--bs-border-radius)'
- - class: rounded-bottom
- styles:
- border-bottom-left-radius: 'var(--bs-border-radius)'
- border-bottom-right-radius: 'var(--bs-border-radius)'
- - class: rounded-start
- styles:
- border-top-left-radius: 'var(--bs-border-radius)'
- border-bottom-left-radius: 'var(--bs-border-radius)'
- - class: rounded-0
- styles:
- border-radius: '0'
- - class: rounded-1
- styles:
- border-radius: 'var(--bs-border-radius-sm)'
- - class: rounded-2
- styles:
- border-radius: 'var(--bs-border-radius)'
+utility:
+ - border-radius
+ - rounded-top
+ - rounded-end
+ - rounded-bottom
+ - rounded-start
---
import { getData } from '@libs/data'
---
-title: Borders
+title: Border
description: Use border utilities to quickly style the border and border-radius of an element. Great for images, buttons, or any other element.
toc: true
alias:
- /docs/5.3/utilities/border/
mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/border
-reference:
- - class: border
- styles:
- border: 'var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)'
- - class: border-0
- styles:
- border: '0'
- - class: border-top
- styles:
- border-block-start: 'var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)'
- - class: border-top-0
- styles:
- border-block-start: '0'
- - class: border-end
- styles:
- border-inline-end: 'var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)'
- - class: border-end-0
- styles:
- border-inline-end: '0'
- - class: border-bottom
- styles:
- border-block-end: 'var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)'
- - class: border-bottom-0
- styles:
- border-block-end: '0'
- - class: border-start
- styles:
- border-inline-start: 'var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)'
- - class: border-start-0
- styles:
- border-inline-start: '0'
- - class: border-primary
- styles:
- --bs-border-opacity: '1'
- border-color: 'rgba(var(--bs-primary-rgb), var(--bs-border-opacity))'
- - class: border-secondary
- styles:
- --bs-border-opacity: '1'
- border-color: 'rgba(var(--bs-secondary-rgb), var(--bs-border-opacity))'
- - class: border-success
- styles:
- --bs-border-opacity: '1'
- border-color: 'rgba(var(--bs-success-rgb), var(--bs-border-opacity))'
- - class: border-info
- styles:
- --bs-border-opacity: '1'
- border-color: 'rgba(var(--bs-info-rgb), var(--bs-border-opacity))'
- - class: border-warning
- styles:
- --bs-border-opacity: '1'
- border-color: 'rgba(var(--bs-warning-rgb), var(--bs-border-opacity))'
- - class: border-danger
- styles:
- --bs-border-opacity: '1'
- border-color: 'rgba(var(--bs-danger-rgb), var(--bs-border-opacity))'
- - class: border-light
- styles:
- --bs-border-opacity: '1'
- border-color: 'rgba(var(--bs-light-rgb), var(--bs-border-opacity))'
- - class: border-dark
- styles:
- --bs-border-opacity: '1'
- border-color: 'rgba(var(--bs-dark-rgb), var(--bs-border-opacity))'
- - class: border-black
- styles:
- --bs-border-opacity: '1'
- border-color: 'rgba(var(--bs-black-rgb), var(--bs-border-opacity))'
- - class: border-white
- styles:
- --bs-border-opacity: '1'
- border-color: 'rgba(var(--bs-white-rgb), var(--bs-border-opacity))'
- - class: border-opacity-10
- styles:
- --bs-border-opacity: '0.1'
- - class: border-opacity-25
- styles:
- --bs-border-opacity: '0.25'
- - class: border-opacity-50
- styles:
- --bs-border-opacity: '0.5'
- - class: border-opacity-75
- styles:
- --bs-border-opacity: '0.75'
- - class: border-opacity-100
- styles:
- --bs-border-opacity: '1'
- - class: border-1
- styles:
- border-width: '1px'
- - class: border-2
- styles:
- border-width: '2px'
- - class: border-3
- styles:
- border-width: '3px'
- - class: border-4
- styles:
- border-width: '4px'
- - class: border-5
- styles:
- border-width: '5px'
+utility:
+ - border
+ - border-top
+ - border-end
+ - border-bottom
+ - border-start
+ - border-width
---
-import { getData } from '@libs/data'
-
## Border
-Use border utilities to add or remove an element’s borders. Choose from all borders or one at a time.
+Use border utilities to add or remove an element's borders. Choose from all borders or one at a time.
### Additive
<span class="border border-bottom-0"></span>
<span class="border border-start-0"></span>`} />
-## Color
-
-<Callout>
-Border utilities like `.border-*` that generated from our original `$theme-colors` Sass map don’t yet respond to color modes, however, any `.border-*-subtle` utility will. This will be resolved in v6.
-</Callout>
-
-Change the border color using utilities built on our theme colors.
-
-<Example class="bd-example-border-utils" code={[
- ...getData('theme-colors').map((themeColor) => `<span class="border border-${themeColor.name}"></span>
-<span class="border border-${themeColor.name}-subtle"></span>`),
- `<span class="border border-black"></span>
-<span class="border border-white"></span>`
-]} />
-
-Or modify the default `border-color` of a component:
-
-<Example code={`<div class="mb-4">
- <label for="exampleFormControlInput1" class="form-label">Email address</label>
- <input type="email" class="form-control border-success" id="exampleFormControlInput1" placeholder="name@example.com">
- </div>
-
- <div class="h4 pb-2 mb-4 text-danger border-bottom border-danger">
- Dangerous heading
- </div>
-
- <div class="p-3 bg-info bg-opacity-10 border border-info border-start-0 rounded-end">
- Changing border color and width
- </div>`} />
-
-## Opacity
-
-Bootstrap `border-{color}` utilities are generated with Sass using CSS variables. This allows for real-time color changes without compilation and dynamic alpha transparency changes.
-
-### How it works
-
-Consider our default `.border-success` utility.
-
-```css
-.border-success {
- --bs-border-opacity: 1;
- border-color: rgba(var(--bs-success-rgb), var(--bs-border-opacity));
-}
-```
-
-We use an RGB version of our `--bs-success` (with the value of `25, 135, 84`) CSS variable and attached a second CSS variable, `--bs-border-opacity`, for the alpha transparency (with a default value `1` thanks to a local CSS variable). That means anytime you use `.border-success` now, your computed `color` value is `rgba(25, 135, 84, 1)`. The local CSS variable inside each `.border-*` class avoids inheritance issues so nested instances of the utilities don’t automatically have a modified alpha transparency.
-
-### Example
-
-To change that opacity, override `--bs-border-opacity` via custom styles or inline styles.
-
-<Example code={`<div class="border border-success p-2 mb-2">This is default success border</div>
-<div class="border border-success p-2" style="--bs-border-opacity: .5;">This is 50% opacity success border</div>`} />
-
-Or, choose from any of the `.border-opacity` utilities:
-
-<Example code={`<div class="border border-success p-2 mb-2">This is default success border</div>
-<div class="border border-success p-2 mb-2 border-opacity-75">This is 75% opacity success border</div>
-<div class="border border-success p-2 mb-2 border-opacity-50">This is 50% opacity success border</div>
-<div class="border border-success p-2 mb-2 border-opacity-25">This is 25% opacity success border</div>
-<div class="border border-success p-2 border-opacity-10">This is 10% opacity success border</div>`} />
-
## Width
<Example class="bd-example-border-utils" code={`<span class="border border-1"></span>
<ScssDocs name="border-variables" file="scss/_variables.scss" />
-Variables for setting `border-color` in `.border-*-subtle` utilities in light and dark mode:
-
-{/* <ScssDocs name="theme-border-subtle-variables" file="scss/_variables.scss" /> */}
-
-{/* <ScssDocs name="theme-border-subtle-dark-variables" file="scss/_variables-dark.scss" /> */}
-
### Sass mixins
<ScssDocs name="border-radius-mixins" file="scss/mixins/_border-radius.scss" />
---
title: Colors
-description: Convey meaning through `color` with a handful of color utility classes. Includes support for styling links with hover states, too.
+description: Convey meaning through `color` with a handful of color utility classes, including built-in color mode adaptivity and support for translucency.
toc: true
+utility:
+ - fg
+ - fg-emphasis
+ - fg-opacity
+ - fg-contrast
---
import { getData } from '@libs/data'
-<Callout name="warning-color-assistive-technologies" />
+<Details name="warning-color-assistive-technologies" />
## Colors
-Colorize text with color utilities. If you want to colorize links, you can use the [`.link-*` helper classes]([[docsref:/helpers/colored-links]]) which have `:hover` and `:focus` states.
+Change the `color` using utilities built on our theme colors using `.fg-{color}` and `.fg-emphasis-{color}`. All these color utilities set the `color` property to a local CSS variable, `--bs-fg`, which has the value of the theme color. Color values also use `light-dark()` to ensure sufficient contrast in both light and dark color modes.
-<Callout>
-Color utilities like `.text-*` that generated from our original `$theme-colors` Sass map don’t yet respond to color modes, however, any `.text-*-emphasis` utility will. This will be resolved in v6.
-</Callout>
+For example, `.fg-primary` sets the `--bs-fg` variable to `light-dark(var(--bs-blue-600), var(--bs-blue-400))`:
+
+```css
+.fg-primary {
+ --bs-fg: light-dark(var(--bs-blue-600), var(--bs-blue-400));
+ color: var(--bs-fg);
+}
+```
+
+This approach allows us to also easily support translucency with our `.fg-{opacity}` utilities as we can use `color-mix()` with the CSS variable to generate the appropriate color. See the [opacity section](#opacity) for more details.
+
+If you want to colorize links, you can use the [`.link-*` helper classes]([[docsref:/helpers/colored-links]]) which have `:hover` and `:focus` states.
<Example code={[
- ...getData('theme-colors').map((themeColor) => `<p class="text-${themeColor.name}">.text-${themeColor.name}</p>
-<p class="text-${themeColor.name}-emphasis">.text-${themeColor.name}-emphasis</p>`),
+ ...getData('theme-colors').map((themeColor) => `<p class="fg-${themeColor.name}">.fg-${themeColor.name}</p>
+<p class="fg-emphasis-${themeColor.name}">.fg-emphasis-${themeColor.name}</p>`),
`
-<p class="text-body">.text-body</p>
-<p class="text-body-emphasis">.text-body-emphasis</p>
-<p class="text-body-secondary">.text-body-secondary</p>
-<p class="text-body-tertiary">.text-body-tertiary</p>
+<p class="fg-body">.fg-body</p>
+<p class="fg-1">.fg-1</p>
+<p class="fg-2">.fg-2</p>
+<p class="fg-3">.fg-3</p>
-<p class="text-black bg-white">.text-black</p>
-<p class="text-white bg-dark">.text-white</p>`
+<p class="fg-black bg-white">.fg-black</p>
+<p class="fg-white bg-dark">.fg-white</p>`
]} />
## Opacity
-As of v5.1.0, text color utilities are generated with Sass using CSS variables. This allows for real-time color changes without compilation and dynamic alpha transparency changes.
-
-### How it works
-
-Consider our default `.text-primary` utility.
-
-```css
-.text-primary {
- --bs-text-opacity: 1;
- color: rgba(var(--bs-primary-rgb), var(--bs-text-opacity));
-}
-```
-
-We use an RGB version of our `--bs-primary` (with the value of `13, 110, 253`) CSS variable and attached a second CSS variable, `--bs-text-opacity`, for the alpha transparency (with a default value `1` thanks to a local CSS variable). That means anytime you use `.text-primary` now, your computed `color` value is `rgba(13, 110, 253, 1)`. The local CSS variable inside each `.text-*` class avoids inheritance issues so nested instances of the utilities don’t automatically have a modified alpha transparency.
-
-### Example
+Change the opacity of a text color by using any of the `.fg-<percentage>` utilities which use `color-mix()` to mix the text color with `transparent` thanks to the CSS variable approach mentioned above.
-To change that opacity, override `--bs-text-opacity` via custom styles or inline styles.
+<Example class="d-flex flex-column gap-2" code={`<div class="fg-primary">This is default primary text</div>
+<div class="fg-primary fg-90">This is 90% opacity primary text</div>
+<div class="fg-primary fg-80">This is 80% opacity primary text</div>
+<div class="fg-primary fg-70">This is 70% opacity primary text</div>
+<div class="fg-primary fg-60">This is 60% opacity primary text</div>
+<div class="fg-primary fg-50">This is 50% opacity primary text</div>
+<div class="fg-primary fg-40">This is 40% opacity primary text</div>
+<div class="fg-primary fg-30">This is 30% opacity primary text</div>
+<div class="fg-primary fg-20">This is 20% opacity primary text</div>
+<div class="fg-primary fg-10">This is 10% opacity primary text</div>`} />
-<Example code={`<div class="text-primary">This is default primary text</div>
-<div class="text-primary" style="--bs-text-opacity: .5;">This is 50% opacity primary text</div>`} />
+## Reset color
-Or, choose from any of the `.text-opacity` utilities:
+Reset a text or link's color with `.text-reset`, so that it inherits the color from its parent.
-<Example code={`<div class="text-primary">This is default primary text</div>
-<div class="text-primary text-opacity-75">This is 75% opacity primary text</div>
-<div class="text-primary text-opacity-50">This is 50% opacity primary text</div>
-<div class="text-primary text-opacity-25">This is 25% opacity primary text</div>`} />
+<Example code={`<p class="fg-3">
+ Lighter body text with a <a href="#" class="text-reset">reset link</a>.
+ </p>`} />
## Specificity
---
title: Display property
-description: Quickly and responsively toggle the display value of components and more with our display utilities. Includes support for some of the more common values, as well as some extras for controlling display when printing.
+description: Quickly and responsively toggle the display value of components and more with our display utilities.
toc: true
-reference:
- - class: d-none
- styles:
- display: 'none'
- - class: d-inline
- styles:
- display: 'inline'
- - class: d-inline-block
- styles:
- display: 'inline-block'
- - class: d-block
- styles:
- display: 'block'
- - class: d-grid
- styles:
- display: 'grid'
- - class: d-inline-grid
- styles:
- display: 'inline-grid'
- - class: d-table
- styles:
- display: 'table'
- - class: d-table-row
- styles:
- display: 'table-row'
- - class: d-table-cell
- styles:
- display: 'table-cell'
- - class: d-flex
- styles:
- display: 'flex'
- - class: d-inline-flex
- styles:
- display: 'inline-flex'
- - class: d-flow-root
- styles:
- display: 'flow-root'
+utility:
+ - display
---
## How it works
## Clearfix
-There's no more clearfix helper in v6 as it's an outdated technique. Instead, use the `display: flow-root` utility, `.d-flow-root`. This forces a container element to create a new block formatting context without the clearfix.
+There's no more clearfix helper in Bootstrap 6 as it's an outdated technique. Instead, use the `display: flow-root` utility, `.d-flow-root`. This forces a container element to create a new block formatting context without the clearfix.
<Example code={`<div class="d-flow-root">
<div class="float-end px-3 py-2 border rounded-3">Floated element</div>
<Example code={`<div class="d-lg-none">hide on lg and wider screens</div>
<div class="d-none d-lg-block">hide on screens smaller than lg</div>`} />
-## Display in print
-
-Change the `display` value of elements when printing with our print display utility classes. Includes support for the same `display` values as our responsive `.d-*` utilities.
-
-- `.d-print-none`
-- `.d-print-inline`
-- `.d-print-inline-block`
-- `.d-print-block`
-- `.d-print-grid`
-- `.d-print-inline-grid`
-- `.d-print-table`
-- `.d-print-table-row`
-- `.d-print-table-cell`
-- `.d-print-flex`
-- `.d-print-inline-flex`
-
-The print and display classes can be combined.
-
-<Example code={`<div class="d-print-none">Screen Only (Hide on print only)</div>
-<div class="d-none d-print-block">Print Only (Hide on screen only)</div>
-<div class="d-none d-lg-block d-print-block">Hide up to large on screen, but always show on print</div>`} />
-
## CSS
### Sass utilities API
csstricks:
url: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
label: Flexbox Guide
+utility:
+ - flex
+ - flex-direction
+ - flex-grow
+ - flex-shrink
+ - flex-wrap
---
import { getData } from '@libs/data'
title: Float
description: Toggle floats on any element, across any breakpoint, using our responsive float utilities.
toc: true
-reference:
- - class: float-start
- styles:
- float: 'left'
- - class: float-end
- styles:
- float: 'right'
- - class: float-none
- styles:
- float: 'none'
+utility:
+ - float
---
import { getData } from '@libs/data'
--- /dev/null
+---
+title: Font family
+description: Utilities for controlling font family including monospace font stack.
+toc: true
+utility:
+ - font-family
+---
+
+import { getData } from '@libs/data'
+
+## Monospace
+
+Change a selection to our monospace font stack with `.font-monospace`.
+
+<Example code={`<p class="font-monospace">This is in monospace</p>`} />
+
+## Body
+
+Change a selection to our body font stack with `.font-body`, which defaults to sans-serif.
+
+<Example code={`<p class="font-body">This is in body</p>`} />
+
+## CSS
+
+### Sass utilities API
+
+Font family 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))
+),
+```
--- /dev/null
+---
+title: Font size
+description: Utilities for controlling text size, or `font-size` and `line-height` together, with responsive font sizing using `clamp()`.
+toc: true
+utility:
+ - font-size
+ - text-size
+---
+
+import { getData } from '@libs/data'
+
+<Callout type="info">
+Looking for heading classes? Head to our [headings documentation]([[docsref:/content/typography#headings]]).
+</Callout>
+
+## Font size
+
+Alternatively, you can change the `font-size` of text with `.fs-<size>` utilities. These classes only set `font-size` and offer a larger range of sizes than the heading classes.
+
+<Example code={`<div class="fs-xs">.fs-xs text</div>
+<div class="fs-sm">.fs-sm text</div>
+<div class="fs-md">.fs-md text</div>
+<div class="fs-lg">.fs-lg text</div>
+<div class="fs-xl">.fs-xl text</div>
+<div class="fs-2xl">.fs-2xl text</div>
+<div class="fs-3xl">.fs-3xl text</div>
+<div class="fs-4xl">.fs-4xl text</div>
+<div class="fs-5xl">.fs-5xl text</div>
+<div class="fs-6xl">.fs-6xl text</div>`} />
+
+## With `line-height`
+
+Swap the `.fs-*` utilities with the `.text-*` utilities to apply a `font-size` and `line-height` at the same time. These are configured from a single Sass map, `$font-sizes`.
+
+<Example code={`<div class="text-xs">.text-xs text</div>
+<div class="text-sm">.text-sm text</div>
+<div class="text-md">.text-md text</div>
+<div class="text-lg">.text-lg text</div>
+<div class="text-xl">.text-xl text</div>
+<div class="text-2xl">.text-2xl text</div>
+<div class="text-3xl">.text-3xl text</div>
+<div class="text-4xl">.text-4xl text</div>
+<div class="text-5xl">.text-5xl text</div>
+<div class="text-6xl">.text-6xl text</div>`} />
+
+## Responsive `font-size`
+
+Font sizes use CSS‘s `clamp()` to provide fluid, responsive sizing that scales between a minimum and maximum value based on the viewport width. **The `clamp()` function takes three parameters:**
+
+- a minimum value
+- a preferred value (calculated using viewport units)
+- and, a maximum value
+
+As the viewport changes, the font size smoothly transitions between the minimum and maximum values. Here's how each size scales at different viewport widths.
+
+<BsTable>
+| Size | Definition | Min | Max | @ 500px | @ 1400px |
+| ---- | ---------- | --- | --- | ------- | -------- |
+| `xs` | `clamp(.75rem, .7rem + .25vw, .875rem)` | 12px | 14px | 12.45px | 14px |
+| `sm` | `clamp(.875rem, .8rem + .375vw, 1rem)` | 14px | 16px | 14.675px | 16px |
+| `md` | `clamp(1rem, .9rem + .5vw, 1.125rem)` | 16px | 18px | 16.9px | 18px |
+| `lg` | `clamp(1.25rem, 1rem + .625vw, 1.5rem)` | 20px | 24px | 20px | 24px |
+| `xl` | `clamp(1.5rem, 1.1rem + .75vw, 1.75rem)` | 24px | 28px | 24px | 28px |
+| `2xl` | `clamp(1.75rem, 1.3rem + 1vw, 2.25rem)` | 28px | 36px | 28px | 34.8px |
+| `3xl` | `clamp(2rem, 1.5rem + 1.875vw, 2.5rem)` | 32px | 40px | 33.375px | 40px |
+| `4xl` | `clamp(2.25rem, 1.75rem + 2.5vw, 3rem)` | 36px | 48px | 40.5px | 48px |
+| `5xl` | `clamp(3rem, 2rem + 5vw, 4rem)` | 48px | 64px | 57px | 64px |
+| `6xl` | `clamp(3.75rem, 2.5rem + 6.25vw, 5rem)` | 60px | 80px | 71.25px | 80px |
+</BsTable>
+
+Customize your **available** `font-size`s by modifying the `$font-sizes` Sass map.
+
+## CSS
+
+### Variables
+
+Root font size variables are declared in our root file in `scss/_root.scss`.
+
+<ScssDocs name="root-font-size-variables" file="scss/_root.scss" />
+
+### Sass utilities API
+
+Font size utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
+
+<ScssDocs name="utils-font-size" file="scss/_utilities.scss" />
---
title: Font style
-description: Utilities for controlling font properties including size, weight, style, line height, and font family.
+description: Utilities for controlling font style including italic and normal styles.
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)'
+utility:
+ - font-style
---
import { getData } from '@libs/data'
-## Font size
+## Font style
-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.
+Quickly change the `font-style` of text with these utilities. `font-style` utilities are abbreviated as `.fst-*`.
-<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>
+<Example code={`<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,
- )
-),
```
--- /dev/null
+---
+title: Font weight
+description: Utilities for controlling font weight including bold, semibold, medium, normal, and light weights.
+toc: true
+utility:
+ - font-weight
+---
+
+import { getData } from '@libs/data'
+
+## Font weight
+
+Quickly change the `font-weight` of text with these utilities. `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>`} />
+
+## CSS
+
+### Sass utilities API
+
+Font weight 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-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
+ )
+),
+```
--- /dev/null
+---
+title: Gap
+description: Use gap utilities to control the space between elements in flexbox or grid layouts. Includes support for individual row and column gaps.
+toc: true
+mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/gap
+utility:
+ - gap
+ - row-gap
+ - column-gap
+---
+
+import { getData } from '@libs/data'
+
+## Overview
+
+Use gap utilities to control the space between children in flexbox and grid layouts. Gap utilities are built from a default Sass map ranging from `.25rem` to `3rem`. Use utilities like `.gap-3` and `.gap-5` to control the gap between all children:
+
+<Example class="d-flex align-items-center justify-content-center gap-4 text-center" showMarkup={false} code={`
+ <div class="d-flex gap-3 p-3 bd-pattern-diagonal rounded-3">
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 1</div>
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 2</div>
+ </div>
+ <div class="d-flex gap-5 p-3 bd-pattern-diagonal rounded-3">
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 1</div>
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 2</div>
+ </div>`} />
+
+```html
+<div class="d-flex gap-3">...</div>
+<div class="d-flex gap-5">...</div>
+```
+
+<Callout type="info">
+**Support note:** Gap utilities work with CSS Grid and Flexbox layouts. They are a modern alternative to margin utilities for spacing children within a container.
+</Callout>
+
+## Notation
+
+Gap 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}-{size}` for `xs` and `{property}-{breakpoint}-{size}` for `sm`, `md`, `lg`, `xl`, and `2xl`.
+
+Where *property* is one of:
+
+- `gap` - for classes that set `gap`
+- `row-gap` - for classes that set `row-gap`
+- `column-gap` - for classes that set `column-gap`
+
+Where *size* is one of:
+
+- `0` - for classes that eliminate the `gap` by setting it to `0`
+- `1` - (by default) for classes that set the `gap` to `$spacer * .25`
+- `2` - (by default) for classes that set the `gap` to `$spacer * .5`
+- `3` - (by default) for classes that set the `gap` to `$spacer`
+- `4` - (by default) for classes that set the `gap` to `$spacer * 1.5`
+- `5` - (by default) for classes that set the `gap` to `$spacer * 3`
+
+(You can add more sizes by adding entries to the `$spacers` Sass map variable.)
+
+## Examples
+
+### Flexbox gap
+
+Use `gap` utilities to control the space between children in a flexbox container:
+
+<Example showMarkup={false} class="d-flex align-items-center justify-content-center text-center" code={`
+ <div class="d-flex gap-4 bd-pattern-diagonal rounded-3">
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 1</div>
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 2</div>
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 3</div>
+ </div>`} />
+
+```html
+<div class="d-flex gap-4">
+ <div>Item 1</div>
+ <div>Item 2</div>
+ <div>Item 3</div>
+</div>
+```
+
+### Grid gap
+
+Gap utilities also work with CSS Grid layouts:
+
+<Example showMarkup={false} class="d-flex align-items-center justify-content-center text-center" code={`
+ <div class="d-grid gap-3 bd-pattern-diagonal rounded-3" style="grid-template-columns: 1fr 1fr;">
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 1</div>
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 2</div>
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 3</div>
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 4</div>
+ </div>`} />
+
+```html
+<div class="d-grid gap-3" style="grid-template-columns: 1fr 1fr;">
+ <div>Item 1</div>
+ <div>Item 2</div>
+ <div>Item 3</div>
+ <div>Item 4</div>
+</div>
+```
+
+### Row and column gaps
+
+Use `row-gap` and `column-gap` utilities to control the space between rows and columns independently:
+
+<Example showMarkup={false} class="d-flex align-items-center justify-content-center text-center" code={`
+ <div class="d-grid row-gap-4 column-gap-2 bd-pattern-diagonal rounded-3" style="grid-template-columns: 1fr 1fr 1fr;">
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 1</div>
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 2</div>
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 3</div>
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 4</div>
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 5</div>
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 6</div>
+ </div>`} />
+
+```html
+<div class="d-grid row-gap-4 column-gap-2" style="grid-template-columns: 1fr 1fr 1fr;">
+ <div>Item 1</div>
+ <div>Item 2</div>
+ <div>Item 3</div>
+ <div>Item 4</div>
+ <div>Item 5</div>
+ <div>Item 6</div>
+</div>
+```
+
+### Flexbox with wrapping
+
+You can also use `row-gap` and `column-gap` utilities with flexbox layouts that wrap:
+
+<Example showMarkup={false} class="d-flex align-items-center justify-content-center text-center" code={`
+ <div class="d-flex flex-wrap row-gap-3 column-gap-2 p-3 bd-pattern-diagonal rounded-3">
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 1</div>
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 2</div>
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 3</div>
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 4</div>
+ <div class="p-3 bg-subtle-accent fg-accent rounded-3">Item 5</div>
+ </div>`} />
+
+```html
+<div class="d-flex flex-wrap row-gap-3 column-gap-2">
+ <div>Item 1</div>
+ <div>Item 2</div>
+ <div>Item 3</div>
+ <div>Item 4</div>
+ <div>Item 5</div>
+</div>
+```
+
+## Responsive
+
+All gap utilities are responsive and include all breakpoints.
+
+<ul>
+{getData('breakpoints').map((breakpoint) => {
+ return (
+ <li><code>.gap{breakpoint.abbr}-0</code> through <code>.gap{breakpoint.abbr}-5</code></li>
+ )
+})}
+</ul>
+
+<ul>
+{getData('breakpoints').map((breakpoint) => {
+ return (
+ <li><code>.row-gap{breakpoint.abbr}-0</code> through <code>.row-gap{breakpoint.abbr}-5</code></li>
+ )
+})}
+</ul>
+
+<ul>
+{getData('breakpoints').map((breakpoint) => {
+ return (
+ <li><code>.column-gap{breakpoint.abbr}-0</code> through <code>.column-gap{breakpoint.abbr}-5</code></li>
+ )
+})}
+</ul>
+
+## CSS
+
+### Sass utilities API
+
+Gap 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
+"gap": (
+ responsive: true,
+ property: gap,
+ class: gap,
+ values: $spacers
+),
+"row-gap": (
+ responsive: true,
+ property: row-gap,
+ class: row-gap,
+ values: $spacers
+),
+"column-gap": (
+ responsive: true,
+ property: column-gap,
+ class: column-gap,
+ values: $spacers
+),
+```
--- /dev/null
+---
+title: Grid
+description: Utilities for controlling CSS Grid layout behavior including column counts, column behavior, and auto-placement options.
+toc: true
+mdn: https://developer.mozilla.org/en-US/docs/Web/CSS/grid
+utility:
+ - grid-column-counts
+ - grid-columns
+ - grid-auto-flow
+---
+
+import { getData } from '@libs/data'
+
+## Overview
+
+Use grid utilities to control CSS Grid layout behavior. These utilities work with Bootstrap's [CSS Grid layout system]([[docsref:/layout/css-grid]]) to manage column counts and auto-placement algorithms.
+
+<Callout type="info">
+**CSS Grid is opt-in.** To use these utilities, you need to enable the CSS Grid system by setting `$enable-cssgrid: true` in your Sass configuration. See our [CSS Grid documentation]([[docsref:/layout/css-grid]]) for more details.
+</Callout>
+
+## Column counts
+
+Use `grid-cols-{value}` utilities to set the number of columns in a CSS Grid container by modifying the `--bs-columns` CSS variable. Bootstrap's CSS Grid system supports 3, 4, and 6 column layouts out of the box.
+
+<Example class="bd-example-cssgrid" code={`<div class="grid text-center grid-cols-3">
+ <div>Column</div>
+ <div>Column</div>
+ <div>Column</div>
+ <div>Column</div>
+ <div>Column</div>
+ <div>Column</div>
+ </div>`} />
+
+<Example class="bd-example-cssgrid" code={`<div class="grid text-center grid-cols-4">
+ <div>Column</div>
+ <div>Column</div>
+ <div>Column</div>
+ <div>Column</div>
+ </div>`} />
+
+<Example class="bd-example-cssgrid" code={`<div class="grid text-center grid-cols-6">
+ <div>Column</div>
+ <div>Column</div>
+ <div>Column</div>
+ <div>Column</div>
+ <div>Column</div>
+ <div>Column</div>
+ </div>`} />
+
+These utilities set the `--bs-columns` CSS variable:
+
+```scss
+.grid-cols-3 {
+ --bs-columns: 3;
+}
+
+.grid-cols-4 {
+ --bs-columns: 4;
+}
+
+.grid-cols-6 {
+ --bs-columns: 6;
+}
+```
+
+## Fill columns
+
+Use `grid-cols-fill` to make a grid item span the entire width of the grid container by setting `grid-column: 1 / -1`.
+
+<Example class="bd-example-cssgrid" code={`<div class="grid text-center" style="--bs-columns: 4;">
+ <div>Column</div>
+ <div>Column</div>
+ <div>Column</div>
+ <div>Column</div>
+ <div class="grid-cols-fill">Full width column</div>
+ <div>Column</div>
+ <div>Column</div>
+ </div>`} />
+
+```html
+<div class="grid" style="--bs-columns: 4;">
+ <div>Column</div>
+ <div>Column</div>
+ <div>Column</div>
+ <div>Column</div>
+ <div class="grid-cols-fill">Full width column</div>
+ <div>Column</div>
+ <div>Column</div>
+</div>
+```
+
+## Auto flow
+
+Control how auto-placed items are inserted into the grid with `grid-auto-flow` utilities.
+
+### Row (default)
+
+Use `grid-auto-flow-row` to place items by filling each row in turn, adding new rows as necessary.
+
+<Example class="bd-example-cssgrid" code={`<div class="grid text-center grid-auto-flow-row" style="--bs-columns: 3;">
+ <div>Item 1</div>
+ <div>Item 2</div>
+ <div>Item 3</div>
+ <div>Item 4</div>
+ <div>Item 5</div>
+ </div>`} />
+
+### Column
+
+Use `grid-auto-flow-column` to place items by filling each column in turn, adding new columns as necessary.
+
+<Example class="bd-example-cssgrid" code={`<div class="grid text-center grid-auto-flow-column" style="--bs-rows: 3; --bs-columns: 3;">
+ <div>Item 1</div>
+ <div>Item 2</div>
+ <div>Item 3</div>
+ <div>Item 4</div>
+ <div>Item 5</div>
+ </div>`} />
+
+### Dense
+
+Use `grid-auto-flow-dense` to use the "dense" packing algorithm, which attempts to fill in holes earlier in the grid if smaller items come up later.
+
+<Example class="bd-example-cssgrid" code={`<div class="grid text-center grid-auto-flow-dense" style="--bs-columns: 3;">
+ <div class="g-col-2">Item 1 (spans 2)</div>
+ <div>Item 2</div>
+ <div>Item 3</div>
+ <div>Item 4</div>
+ <div class="g-col-2">Item 5 (spans 2)</div>
+ </div>`} />
+
+```scss
+.grid-auto-flow-row {
+ grid-auto-flow: row;
+}
+
+.grid-auto-flow-column {
+ grid-auto-flow: column;
+}
+
+.grid-auto-flow-dense {
+ grid-auto-flow: dense;
+}
+```
+
+## Responsive
+
+All grid utilities are responsive and include all breakpoints.
+
+### Column counts
+
+<ul>
+{getData('breakpoints').map((breakpoint) => {
+ return (
+ <Fragment>
+ <li><code>.grid-cols{breakpoint.abbr}-3</code></li>
+ <li><code>.grid-cols{breakpoint.abbr}-4</code></li>
+ <li><code>.grid-cols{breakpoint.abbr}-6</code></li>
+ <li><code>.grid-cols{breakpoint.abbr}-fill</code></li>
+ </Fragment>
+ )
+})}
+</ul>
+
+### Auto flow
+
+<ul>
+{getData('breakpoints').map((breakpoint) => {
+ return (
+ <Fragment>
+ <li><code>.grid-auto-flow{breakpoint.abbr}-row</code></li>
+ <li><code>.grid-auto-flow{breakpoint.abbr}-column</code></li>
+ <li><code>.grid-auto-flow{breakpoint.abbr}-dense</code></li>
+ </Fragment>
+ )
+})}
+</ul>
+
+## CSS
+
+### Sass utilities API
+
+Grid 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
+"grid-column-counts": (
+ responsive: true,
+ property: --#{$prefix}columns,
+ class: grid-cols,
+ values: (
+ 3,
+ 4,
+ 6
+ )
+),
+"grid-columns": (
+ responsive: true,
+ property: grid-column,
+ class: grid-cols,
+ values: (
+ fill: #{"1 / -1"},
+ )
+),
+"grid-auto-flow": (
+ responsive: true,
+ property: grid-auto-flow,
+ class: grid-auto-flow,
+ values: row column dense
+),
+```
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'
+utility:
+ - height
+ - max-height
+ - min-height
+ - viewport-height
+ - min-viewport-height
---
-## 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
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)
-),
-```
+<ScssDocs name="utils-height" file="scss/_utilities.scss" />
title: Interactions
description: Utility classes that change how users interact with contents of a website.
toc: false
-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'
- - class: pe-none
- styles:
- pointer-events: 'none'
- - class: pe-auto
- styles:
- pointer-events: 'auto'
+utility:
+ - user-select
+ - pointer-events
---
## Text selection
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
+utility:
+ - justify-content
---
import { getData } from '@libs/data'
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
+utility:
+ - justify-items
---
import { getData } from '@libs/data'
--- /dev/null
+---
+title: Line height
+description: Utilities for controlling line height including tight, normal, and loose spacing.
+toc: true
+utility:
+ - line-height
+---
+
+import { getData } from '@libs/data'
+
+## 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>`} />
+
+## CSS
+
+### Sass utilities API
+
+Line 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
+"line-height": (
+ property: line-height,
+ class: lh,
+ values: (
+ 1: 1,
+ sm: $line-height-sm,
+ base: $line-height-base,
+ lg: $line-height-lg,
+ )
+),
+```
---
title: Link
-description: Link utilities are used to stylize your anchors to adjust their color, opacity, underline offset, underline color, and more.
+description: Link utilities are used to stylize your anchors to adjust their color and opacity.
toc: true
+utility:
+ - link-opacity
---
import { getData } from '@libs/data'
Change the alpha opacity of the link `rgba()` color value with utilities. Please be aware that changes to a color’s opacity can lead to links with [*insufficient* contrast]([[docsref:getting-started/accessibility/#color-contrast]]).
-<Example code={`<p><a class="link-opacity-10" href="#">Link opacity 10</a></p>
-<p><a class="link-opacity-25" href="#">Link opacity 25</a></p>
-<p><a class="link-opacity-50" href="#">Link opacity 50</a></p>
-<p><a class="link-opacity-75" href="#">Link opacity 75</a></p>
-<p><a class="link-opacity-100" href="#">Link opacity 100</a></p>`} />
+<Example code={`<p><a class="link-10" href="#">Link opacity 10</a></p>
+<p><a class="link-20" href="#">Link opacity 20</a></p>
+<p><a class="link-30" href="#">Link opacity 30</a></p>
+<p><a class="link-40" href="#">Link opacity 40</a></p>
+<p><a class="link-50" href="#">Link opacity 50</a></p>
+<p><a class="link-60" href="#">Link opacity 60</a></p>
+<p><a class="link-70" href="#">Link opacity 70</a></p>
+<p><a class="link-80" href="#">Link opacity 80</a></p>
+<p><a class="link-90" href="#">Link opacity 90</a></p>
+<p><a class="link-100" href="#">Link opacity 100</a></p>`} />
You can even change the opacity level on hover.
-<Example code={`<p><a class="link-opacity-10-hover" href="#">Link hover opacity 10</a></p>
-<p><a class="link-opacity-25-hover" href="#">Link hover opacity 25</a></p>
-<p><a class="link-opacity-50-hover" href="#">Link hover opacity 50</a></p>
-<p><a class="link-opacity-75-hover" href="#">Link hover opacity 75</a></p>
-<p><a class="link-opacity-100-hover" href="#">Link hover opacity 100</a></p>`} />
-
-## Link underlines
-
-### Underline color
-
-Change the underline’s color independent of the link text color.
-
-<Example code={getData('theme-colors').map((themeColor) => `<p><a href="#" class="link-underline-${themeColor.name}">${themeColor.title} underline</a></p>`)} />
-
-### Underline offset
-
-Change the underline’s distance from your text. Offset is set in `em` units to automatically scale with the element’s current `font-size`.
-
-<Example code={`<p><a href="#">Default link</a></p>
-<p><a class="link-offset-1" href="#">Offset 1 link</a></p>
-<p><a class="link-offset-2" href="#">Offset 2 link</a></p>
-<p><a class="link-offset-3" href="#">Offset 3 link</a></p>`} />
-
-### Underline opacity
-
-Change the underline’s opacity. Requires adding `.link-underline` to first set an `rgba()` color we use to then modify the alpha opacity.
-
-<Example code={`<p><a class="link-offset-2 link-underline link-underline-opacity-0" href="#">Underline opacity 0</a></p>
-<p><a class="link-offset-2 link-underline link-underline-opacity-10" href="#">Underline opacity 10</a></p>
-<p><a class="link-offset-2 link-underline link-underline-opacity-25" href="#">Underline opacity 25</a></p>
-<p><a class="link-offset-2 link-underline link-underline-opacity-50" href="#">Underline opacity 50</a></p>
-<p><a class="link-offset-2 link-underline link-underline-opacity-75" href="#">Underline opacity 75</a></p>
-<p><a class="link-offset-2 link-underline link-underline-opacity-100" href="#">Underline opacity 100</a></p>`} />
-
-### Hover variants
-
-Just like the `.link-opacity-*-hover` utilities, `.link-offset` and `.link-underline-opacity` utilities include `:hover` variants by default. Mix and match to create unique link styles.
-
-<Example code={`<a class="link-offset-2 link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="#">
- Underline opacity 0
- </a>`} />
+<Example code={`<p><a class="link-10-hover" href="#">Link hover opacity 10</a></p>
+<p><a class="link-20-hover" href="#">Link hover opacity 20</a></p>
+<p><a class="link-30-hover" href="#">Link hover opacity 30</a></p>
+<p><a class="link-40-hover" href="#">Link hover opacity 40</a></p>
+<p><a class="link-50-hover" href="#">Link hover opacity 50</a></p>
+<p><a class="link-60-hover" href="#">Link hover opacity 60</a></p>
+<p><a class="link-70-hover" href="#">Link hover opacity 70</a></p>
+<p><a class="link-80-hover" href="#">Link hover opacity 80</a></p>
+<p><a class="link-90-hover" href="#">Link hover opacity 90</a></p>
+<p><a class="link-100-hover" href="#">Link hover opacity 100</a></p>`} />
## Colored links
-[Colored link helpers]([[docsref:/helpers/colored-links/]]) have been updated to pair with our link utilities. Use the new utilities to modify the link opacity, underline opacity, and underline offset.
+[Colored link helpers]([[docsref:/helpers/colored-links/]]) have been updated to pair with our link utilities. Use the new utilities to modify the link opacity.
<Example code={[
- ...getData('theme-colors').map((themeColor) => `<p><a href="#" class="link-${themeColor.name} link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover">${themeColor.title} link</a></p>`),
- `<p><a href="#" class="link-body-emphasis link-offset-2 link-underline-opacity-25 link-underline-opacity-75-hover">Emphasis link</a></p>`
+ ...getData('theme-colors').map((themeColor) => `<p><a href="#" class="link-${themeColor.name} underline-offset-2 underline-20 underline-100-hover">${themeColor.title} link</a></p>`)
]} />
-<Callout name="warning-color-assistive-technologies" />
+<Details name="warning-color-assistive-technologies" />
## CSS
---
title: Margin
-description: Use margin utilities to control the space around elements with responsive margin classes.
+description: Use margin utilities to responsively control the space around elements.
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'
+utility:
+ - margin
+ - margin-x
+ - margin-y
+ - margin-top
+ - margin-end
+ - margin-bottom
+ - margin-start
---
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`.
+Use margin utilities to control the outer space around elements. Margin utilities are built from a default Sass map ranging from `.25rem` to `3rem`. Use utilities like `.m-3` and `.m-5` to control the margin on all sides of an element:
+
+<Example class="d-flex align-items-center justify-content-center gap-4 text-center" showMarkup={false} code={`
+ <div class="bd-pattern-diagonal rounded-3">
+ <div class="w-12 p-3 m-3 bg-accent fg-contrast-accent rounded-3">
+ .m-3
+ </div>
+ </div>
+ <div class="bd-pattern-diagonal rounded-3">
+ <div class="w-12 p-3 m-5 bg-accent fg-contrast-accent rounded-3">
+ .m-5
+ </div>
+ </div>`} />
+
+```html
+<div class="m-3">.m-3</div>
+<div class="m-5">.m-5</div>
+```
<Callout>
-**Using the CSS Grid layout module?** Consider using [the gap utility]([[docsref:/utilities/spacing#gap]]) instead.
+**Using the CSS Grid layout module?** Consider using [the gap utility]([[docsref:/utilities/gap]]) instead.
</Callout>
## Notation
## Examples
-Here are some representative examples of these classes:
+### Single side
+
+Use utilities like `.mt-3`, `.me-2`, `.mb-4`, and `.ms-1` to control the margin on one side of an element:
+
+<Example showMarkup={false} class="d-flex flex-column align-items-center justify-content-center gap-4 text-center" code={`
+ <div class="bd-pattern-diagonal rounded-3 d-inline-block">
+ <div class="w-12 p-3 mt-4 bg-accent fg-contrast-accent rounded-3">
+ .mt-4
+ </div>
+ </div>
+ <div class="bd-pattern-diagonal rounded-3 d-inline-block">
+ <div class="w-12 p-3 me-4 bg-accent fg-contrast-accent rounded-3">
+ .me-4
+ </div>
+ </div>
+ <div class="bd-pattern-diagonal rounded-3 d-inline-block">
+ <div class="w-12 p-3 mb-4 bg-accent fg-contrast-accent rounded-3">
+ .mb-4
+ </div>
+ </div>
+ <div class="bd-pattern-diagonal rounded-3 d-inline-block">
+ <div class="w-12 p-3 ms-4 bg-accent fg-contrast-accent rounded-3">
+ .ms-4
+ </div>
+ </div>`} />
-```scss
-.mt-0 {
- margin-top: 0;
-}
+```html
+<div class="mt-4">.mt-4</div>
+<div class="me-4">.me-4</div>
+<div class="mb-4">.mb-4</div>
+<div class="ms-4">.ms-4</div>
+```
-.ms-1 {
- margin-left: ($spacer * .25);
-}
+### Horizontal margin
-.mx-2 {
- margin-left: ($spacer * .5);
- margin-right: ($spacer * .5);
-}
+Use utilities like `.mx-3` and `.mx-5` to control the horizontal margin of an element:
-.m-3 {
- margin: $spacer;
-}
+<Example showMarkup={false} class="d-flex flex-column align-items-center justify-content-center gap-4 text-center" code={`
+ <div class="bd-pattern-diagonal rounded-3 d-inline-block">
+ <div class="w-12 p-3 mx-3 bg-accent fg-contrast-accent rounded-3">
+ .mx-3
+ </div>
+ </div>
+ <div class="bd-pattern-diagonal rounded-3 d-inline-block">
+ <div class="w-12 p-3 mx-5 bg-accent fg-contrast-accent rounded-3">
+ .mx-5
+ </div>
+ </div>`} />
+
+```html
+<div class="mx-3">.mx-3</div>
+<div class="mx-5">.mx-5</div>
```
-## Horizontal centering
+### Vertical margin
+
+Use utilities like `.my-3` and `.my-5` to control the vertical margin of an element:
+
+<Example showMarkup={false} class="d-flex align-items-center justify-content-center gap-4 text-center" code={`
+ <div class="bd-pattern-diagonal rounded-3 d-inline-block">
+ <div class="w-12 p-3 my-3 bg-accent fg-contrast-accent rounded-3">
+ .my-3
+ </div>
+ </div>
+ <div class="bd-pattern-diagonal rounded-3 d-inline-block">
+ <div class="w-12 p-3 my-5 bg-accent fg-contrast-accent rounded-3">
+ .my-5
+ </div>
+ </div>`} />
+
+```html
+<div class="my-3">.my-3</div>
+<div class="my-5">.my-5</div>
+```
+
+### 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
+<Example showMarkup={false} class="d-flex align-items-center justify-content-center text-center" code={`
+ <div class="bd-pattern-diagonal rounded-3 w-100">
+ <div class="w-12 p-3 mx-auto bg-accent fg-contrast-accent rounded-3">
+ .mx-auto
+ </div>
</div>`} />
```html
-<div class="mx-auto p-2" style="width: 200px;">
+<div class="mx-auto" 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.
+In CSS, `margin` properties can utilize negative values (`padding` cannot). These negative margins are **disabled by default**, but can be enabled in Sass by setting `$enable-negative-margins: true`.
-<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>`} />
+The syntax is nearly the same as the default, positive margin utilities, but with the addition of `n` before the requested size. Here’s an example class that’s the opposite of `.mt-1`:
-```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>
+```scss
+.mt-n1 {
+ margin-top: -0.25rem !important;
+}
```
## Responsive
title: Object fit
description: Use the object fit utilities to modify how the content of a <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Replaced_element" target="_blank" rel="noopener noreferrer">replaced element</a>, such as an `<img>` or `<video>`, should be resized to fit its container.
toc: true
-reference:
- - class: object-fit-contain
- styles:
- object-fit: 'contain'
- - class: object-fit-cover
- styles:
- object-fit: 'cover'
- - class: object-fit-fill
- styles:
- object-fit: 'fill'
- - class: object-fit-scale
- styles:
- object-fit: 'scale-down'
- - class: object-fit-none
- styles:
- object-fit: 'none'
+utility:
+ - object-fit
---
## How it works
---
title: Opacity
description: Control the opacity of elements.
-reference:
- - class: opacity-0
- styles:
- opacity: '0'
- - class: opacity-25
- styles:
- opacity: '0.25'
- - class: opacity-50
- styles:
- opacity: '0.5'
- - class: opacity-75
- styles:
- opacity: '0.75'
- - class: opacity-100
- styles:
- opacity: '1'
+utility:
+ - opacity
---
The `opacity` property sets the opacity level for an element. The opacity level describes the transparency level, where `1` is not transparent at all, `.5` is 50% visible, and `0` is completely transparent.
title: Overflow
description: Use these shorthand utilities for quickly configuring how content overflows an element.
toc: true
-reference:
- - class: overflow-auto
- styles:
- overflow: 'auto'
- - class: overflow-hidden
- styles:
- overflow: 'hidden'
- - class: overflow-visible
- styles:
- overflow: 'visible'
- - class: overflow-scroll
- styles:
- overflow: 'scroll'
- - class: overflow-x-auto
- styles:
- overflow-x: 'auto'
- - class: overflow-x-hidden
- styles:
- overflow-x: 'hidden'
- - class: overflow-x-visible
- styles:
- overflow-x: 'visible'
- - class: overflow-x-scroll
- styles:
- overflow-x: 'scroll'
- - class: overflow-y-auto
- styles:
- overflow-y: 'auto'
- - class: overflow-y-hidden
- styles:
- overflow-y: 'hidden'
- - class: overflow-y-visible
- styles:
- overflow-y: 'visible'
- - class: overflow-y-scroll
- styles:
- overflow-y: 'scroll'
+utility:
+ - overflow
+ - overflow-x
+ - overflow-y
---
## Overflow
---
title: Padding
-description: Use padding utilities to control the inner space of elements with responsive padding classes.
+description: Use padding utilities to responsively control the inner spacing of elements.
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'
+utility:
+ - padding
+ - padding-x
+ - padding-y
+ - padding-top
+ - padding-end
+ - padding-bottom
+ - padding-start
---
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`.
+Use padding utilities to control the inner space within elements. Padding utilities are built from a default Sass map ranging from `.25rem` to `3rem`. Use utilities like `.p-3` and `.p-5` to control the padding on all sides of an element:
+
+<Example class="d-flex align-items-center justify-content-center gap-4 text-center" showMarkup={false} code={`
+ <div class="p-3 bg-primary bd-pattern-diagonal-inner fg-contrast-accent rounded-3">
+ <div class="p-3 bg-primary rounded-3">
+ .p-3
+ </div>
+ </div>
+ <div class="p-5 bg-primary bd-pattern-diagonal-inner fg-contrast-accent rounded-3">
+ <div class="p-3 bg-primary rounded-3">
+ .p-5
+ </div>
+ </div>`} />
+
+```html
+<div class="p-3">.p-3</div>
+<div class="p-5">.p-5</div>
+```
## Notation
## Examples
-Here are some representative examples of these classes:
+### Single side
-```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;
-}
+Use utilities like `.pt-4`, `.pe-4`, `.pb-4`, and `.ps-4` to control the padding on one side of an element:
+
+<Example showMarkup={false} class="d-flex align-items-center justify-content-center gap-4 text-center" code={`
+ <div class="pt-4 bg-primary bd-pattern-diagonal-inner fg-contrast-accent rounded-3">
+ <div class="p-3 bg-primary rounded-3">
+ .pt-4
+ </div>
+ </div>
+ <div class="pe-4 bg-primary bd-pattern-diagonal-inner fg-contrast-accent rounded-3">
+ <div class="p-3 bg-primary rounded-3">
+ .pe-4
+ </div>
+ </div>
+ <div class="pb-4 bg-primary bd-pattern-diagonal-inner fg-contrast-accent rounded-3">
+ <div class="p-3 bg-primary rounded-3">
+ .pb-4
+ </div>
+ </div>
+ <div class="ps-4 bg-primary bd-pattern-diagonal-inner fg-contrast-accent rounded-3">
+ <div class="p-3 bg-primary rounded-3">
+ .ps-4
+ </div>
+ </div>`} />
+
+```html
+<div class="pt-4">.pt-4</div>
+<div class="pe-4">.pe-4</div>
+<div class="pb-4">.pb-4</div>
+<div class="ps-4">.ps-4</div>
```
-## Basic usage
+### Horizontal padding
+
+Use utilities like `.px-3` and `.px-5` to control the horizontal padding of an element:
-<Example code={`<div class="p-3 mb-2 bg-light">
- Regular padding on all sides
+<Example showMarkup={false} class="d-flex flex-column align-items-center justify-content-center gap-4 text-center" code={`
+ <div class="px-3 bg-primary bd-pattern-diagonal-inner fg-contrast-accent rounded-3">
+ <div class="p-3 bg-primary rounded-3">
+ .px-3
+ </div>
</div>
- <div class="py-2 px-4 mb-2 bg-light">
- Horizontal and vertical padding
+ <div class="px-5 bg-primary bd-pattern-diagonal-inner fg-contrast-accent rounded-3">
+ <div class="p-3 bg-primary rounded-3">
+ .px-5
+ </div>
+ </div>`} />
+
+```html
+<div class="px-3">.px-3</div>
+<div class="px-5">.px-5</div>
+```
+
+### Vertical padding
+
+Use utilities like `.py-3` and `.py-5` to control the vertical padding of an element:
+
+<Example showMarkup={false} class="d-flex align-items-center justify-content-center gap-4 text-center" code={`
+ <div class="py-3 bg-primary bd-pattern-diagonal-inner fg-contrast-accent rounded-3">
+ <div class="p-3 bg-primary rounded-3">
+ .py-3
+ </div>
</div>
- <div class="pt-4 mb-2 bg-light">
- Top padding only
+ <div class="py-5 bg-primary bd-pattern-diagonal-inner fg-contrast-accent rounded-3">
+ <div class="p-3 bg-primary rounded-3">
+ .py-5
+ </div>
</div>`} />
+```html
+<div class="py-3">.py-3</div>
+<div class="py-5">.py-5</div>
+```
+
## Responsive
All padding utilities are responsive and include all breakpoints.
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
+utility:
+ - place-items
---
import { getData } from '@libs/data'
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'
+utility:
+ - pointer-events
---
## Overview
title: Position
description: Use these shorthand utilities for quickly configuring the position of an element.
toc: true
-reference:
- - class: position-static
- styles:
- position: 'static'
- - class: position-relative
- styles:
- position: 'relative'
- - class: position-absolute
- styles:
- position: 'absolute'
- - class: position-fixed
- styles:
- position: 'fixed'
- - class: position-sticky
- styles:
- position: 'sticky'
- - class: top-0
- styles:
- top: '0'
- - class: top-50
- styles:
- top: '50%'
- - class: top-100
- styles:
- top: '100%'
- - class: bottom-0
- styles:
- bottom: '0'
- - class: bottom-50
- styles:
- bottom: '50%'
- - class: bottom-100
- styles:
- bottom: '100%'
- - class: start-0
- styles:
- left: '0'
- - class: start-50
- styles:
- left: '50%'
- - class: start-100
- styles:
- left: '100%'
- - class: end-0
- styles:
- right: '0'
- - class: end-50
- styles:
- right: '50%'
- - class: end-100
- styles:
- right: '100%'
- - class: translate-middle
- styles:
- transform: 'translate(-50%, -50%)'
- - class: translate-middle-x
- styles:
- transform: 'translateX(-50%)'
- - class: translate-middle-y
- styles:
- transform: 'translateY(-50%)'
+utility:
+ - position
+ - top
+ - bottom
+ - start
+ - end
+ - translate-middle
---
## Position values
title: Shadows
description: Add or remove shadows to elements with box-shadow utilities.
toc: true
-reference:
- - class: shadow-none
- styles:
- box-shadow: 'none'
- - class: shadow-sm
- styles:
- box-shadow: 'var(--bs-box-shadow-sm)'
- - class: shadow
- styles:
- box-shadow: 'var(--bs-box-shadow)'
- - class: shadow-lg
- styles:
- box-shadow: 'var(--bs-box-shadow-lg)'
+utility:
+ - shadow
---
## Examples
+++ /dev/null
----
-title: Sizing
-description: Easily make an element as wide or as tall with our width and height utilities.
-toc: true
-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'
- - 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'
----
-
-## Relative to the parent
-
-Width and height utilities are generated from the utility API in `_utilities.scss`. Includes support for `25%`, `50%`, `75%`, `100%`, and `auto` by default. Modify those values as you need to generate different utilities here.
-
-<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>`} />
-
-<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>`} />
-
-You can also use `max-width: 100%;` and `max-height: 100%;` utilities as needed.
-
-<Example class="bd-example-flex" code={`<div style="width: 50%; height: 100px;">
- <div class="max-w-100" style="width: 200%;">Max-width 100%</div>
- </div>`} />
-
-<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>`} />
-
-## Relative to the viewport
-
-You can also use utilities to set the width and height relative to the viewport.
-
-```html
-<div class="min-vw-100">Min-width 100vw</div>
-<div class="min-vh-100">Min-height 100vh</div>
-<div class="vw-100">Width 100vw</div>
-<div class="vh-100">Height 100vh</div>
-```
-
-## CSS
-
-### Sass utilities API
-
-Sizing utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
-
-<ScssDocs name="utils-sizing" file="scss/_utilities.scss" />
+++ /dev/null
----
-title: Spacing
-description: Bootstrap includes a wide range of shorthand responsive margin, padding, and gap utility classes to modify an element's appearance.
-toc: true
-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'
- - 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'
- - class: gap-0
- styles:
- gap: '0'
- - class: gap-1
- styles:
- gap: '0.25rem'
- - class: gap-2
- styles:
- gap: '0.5rem'
- - class: gap-3
- styles:
- gap: '1rem'
- - class: gap-4
- styles:
- gap: '1.5rem'
- - class: gap-5
- styles:
- gap: '3rem'
----
-
-## Margin and padding
-
-Assign responsive-friendly `margin` or `padding` values to an element or a subset of its sides with shorthand classes. Includes support for individual properties, all properties, and vertical and horizontal properties. Classes are built from a default Sass map ranging from `.25rem` to `3rem`.
-
-<Callout>
-**Using the CSS Grid layout module?** Consider using [the gap utility](#gap) instead.
-</Callout>
-
-### Notation
-
-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 `2xl`.
-
-Where *property* is one of:
-
-- `m` - for classes that set `margin`
-- `p` - for classes that set `padding`
-
-Where *sides* is one of:
-
-- `t` - for classes that set `margin-top` or `padding-top`
-- `b` - for classes that set `margin-bottom` or `padding-bottom`
-- `s` - (start) for classes that set `margin-left` or `padding-left` in LTR, `margin-right` or `padding-right` in RTL
-- `e` - (end) for classes that set `margin-right` or `padding-right` in LTR, `margin-left` or `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 `margin` or `padding` on all 4 sides of the element
-
-Where *size* is one of:
-
-- `0` - for classes that eliminate the `margin` or `padding` by setting it to `0`
-- `1` - (by default) for classes that set the `margin` or `padding` to `$spacer * .25`
-- `2` - (by default) for classes that set the `margin` or `padding` to `$spacer * .5`
-- `3` - (by default) for classes that set the `margin` or `padding` to `$spacer`
-- `4` - (by default) for classes that set the `margin` or `padding` to `$spacer * 1.5`
-- `5` - (by default) for classes that set the `margin` or `padding` 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);
-}
-
-.px-2 {
- padding-left: ($spacer * .5);
- padding-right: ($spacer * .5);
-}
-
-.p-3 {
- padding: $spacer;
-}
-```
-
-### Horizontal centering
-
-Additionally, Bootstrap also 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
-
-In CSS, `margin` properties can utilize negative values (`padding` cannot). These negative margins are **disabled by default**, but can be enabled in Sass by setting `$enable-negative-margins: true`.
-
-The syntax is nearly the same as the default, positive margin utilities, but with the addition of `n` before the requested size. Here’s an example class that’s the opposite of `.mt-1`:
-
-```scss
-.mt-n1 {
- margin-top: -0.25rem;
-}
-```
-
-## Gap
-
-When using `display: grid` or `display: flex`, you can make use of `gap` utilities on the parent element. This can save on having to add margin utilities to individual children of a grid or flex container. Gap utilities are responsive by default, and are generated via our utilities API, based on the `$spacers` Sass map.
-
-<Example class="bd-example-cssgrid" code={`<div style="grid-template-columns: 1fr 1fr;" class="d-grid gap-3">
- <div class="p-2">Grid item 1</div>
- <div class="p-2">Grid item 2</div>
- <div class="p-2">Grid item 3</div>
- <div class="p-2">Grid item 4</div>
- </div>`} />
-
-Support includes responsive options for all of Bootstrap’s grid breakpoints, as well as six sizes from the `$spacers` map (`0`–`5`). There is no `.gap-auto` utility class as it’s effectively the same as `.gap-0`.
-
-### row-gap
-
-`row-gap` sets the vertical space between children items in the specified container.
-
-<Example class="bd-example-cssgrid" code={`<div style="grid-template-columns: 1fr 1fr;" class="d-grid gap-0 row-gap-3">
- <div class="p-2">Grid item 1</div>
- <div class="p-2">Grid item 2</div>
- <div class="p-2">Grid item 3</div>
- <div class="p-2">Grid item 4</div>
- </div>`} />
-
-### column-gap
-
-`column-gap` sets the horizontal space between children items in the specified container.
-
-<Example class="bd-example-cssgrid" code={`<div style="grid-template-columns: 1fr 1fr;" class="d-grid gap-0 column-gap-3">
- <div class="p-2">Grid item 1</div>
- <div class="p-2">Grid item 2</div>
- <div class="p-2">Grid item 3</div>
- <div class="p-2">Grid item 4</div>
- </div>`} />
-
-## CSS
-
-### Sass maps
-
-Spacing utilities are declared via Sass map and then generated with our utilities API.
-
-<ScssDocs name="spacer-variables-maps" file="scss/_variables.scss" />
-
-### Sass utilities API
-
-Spacing utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
-
-<ScssDocs name="utils-spacing" file="scss/_utilities.scss" />
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'
+utility:
+ - text-align
---
import { getData } from '@libs/data'
-## Overview
+## Alignment
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>
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'
+utility:
+ - underline-offset
+ - underline-color
+ - underline-opacity
+ - underline-thickness
+ - text-decoration
---
+import { getData } from '@libs/data'
+
## Text decoration
Decorate text in components with text decoration classes.
<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
+## Underline
+
+### Offset
+
+Change the underline's distance from your text. Offset is set in `em` units to automatically scale with the element's current `font-size`.
+
+<Example code={`<p><a href="#">Default link</a></p>
+<p><a class="underline-offset-1" href="#">Offset 1 link</a></p>
+<p><a class="underline-offset-2" href="#">Offset 2 link</a></p>
+<p><a class="underline-offset-3" href="#">Offset 3 link</a></p>`} />
+
+### Color
+
+Change the underline's color independent of the text color.
+
+<Example code={getData('theme-colors').map((themeColor) => `<p><a href="#" class="underline-${themeColor.name}">${themeColor.title} underline</a></p>`)} />
+
+### Opacity
+
+Change the underline's opacity. Requires adding `.underline-{color}` to first set an `rgba()` color we use to then modify the alpha opacity.
+
+<Example code={`<p><a class="underline-10" href="#">Underline opacity 10</a></p>
+<p><a class="underline-20" href="#">Underline opacity 20</a></p>
+<p><a class="underline-30" href="#">Underline opacity 30</a></p>
+<p><a class="underline-40" href="#">Underline opacity 40</a></p>
+<p><a class="underline-50" href="#">Underline opacity 50</a></p>
+<p><a class="underline-60" href="#">Underline opacity 60</a></p>
+<p><a class="underline-70" href="#">Underline opacity 70</a></p>
+<p><a class="underline-80" href="#">Underline opacity 80</a></p>
+<p><a class="underline-90" href="#">Underline opacity 90</a></p>
+<p><a class="underline-100" href="#">Underline opacity 100</a></p>`} />
-Transform text in components with our text capitalization classes: `text-lowercase`, `text-uppercase` or `text-capitalize`.
+### Thickness
-<Example code={`<p class="text-lowercase">Lowercased text.</p>
-<p class="text-uppercase">Uppercased text.</p>
-<p class="text-capitalize">CapiTaliZed text.</p>`} />
+Change the thickness of the underline.
-Note how `.text-capitalize` only changes the first letter of each word, leaving the case of any other letters unaffected.
+<Example code={`<p><a href="#">Default link</a></p>
+<p><a class="underline-thickness-1" href="#">Thickness 1 link</a></p>
+<p><a class="underline-thickness-2" href="#">Thickness 2 link</a></p>
+<p><a class="underline-thickness-3" href="#">Thickness 3 link</a></p>
+<p><a class="underline-thickness-4" href="#">Thickness 4 link</a></p>
+<p><a class="underline-thickness-5" href="#">Thickness 5 link</a></p>`} />
-## Reset color
+### Hover variants
-Reset a text or link's color with `.text-reset`, so that it inherits the color from its parent.
+The `.underline-offset`, `.underline-{N}`, and `.underline-thickness` utilities include `:hover` variants by default. Mix and match to create unique link styles.
-<Example code={`<p class="text-body-secondary">
- Secondary body text with a <a href="#" class="text-reset">reset link</a>.
- </p>`} />
+<Example code={`<a class="underline-offset-2 underline-offset-3-hover underline-10 underline-50-hover underline-thickness-2-hover" href="#">
+ Underline with offset and opacity changes on hover
+ </a>`} />
## CSS
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
-),
-```
+<ScssDocs name="utils-underline" file="scss/_utilities.scss" />
--- /dev/null
+---
+title: Text transform
+description: Transform text in components with text capitalization utilities.
+toc: true
+utility:
+ - text-transform
+---
+
+Transform text in components with text capitalization classes.
+
+<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.
+
+## CSS
+
+### Sass utilities API
+
+Text transform utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
+
+<ScssDocs name="utils-text-transform" file="scss/_utilities.scss" />
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'
+utility:
+ - text-wrap
+ - word-wrap
---
-## 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>`} />
+## Wrapping
+
+Control how text wraps inside an element with `text-wrap` utilities. This is a newer CSS property that replaces the older `white-space` property and adds new functionality.
+
+<Example class="d-flex flex-column gap-3" code={`<div class="w-12 p-3 bg-subtle-accent text-wrap">
+ This text should wrap across multiple lines within the parent element.
+ </div>
+ <div class="w-12 p-3 bg-subtle-accent text-nowrap">
+ This text should not wrap across multiple lines within the parent element.
+ </div>
+ <div class="w-12 p-3 bg-subtle-accent text-balance">
+ This text should wrap in a balanced way across multiple lines within the parent element.
+ </div>
+ <div class="w-12 p-3 bg-subtle-accent text-pretty">
+ This text should wrap in a pretty way across multiple lines within the parent element.
+ </div>`} customMarkup={`<div class="text-wrap">…</div>
+ <div class="text-nowrap">…</div>
+ <div class="text-balance">…</div>
+ <div class="text-pretty">…</div>`} />
## Word break
+++ /dev/null
----
-title: Text
-description: Documentation and examples for common text utilities to control alignment, wrapping, weight, and more.
-toc: true
-reference:
- - class: text-start
- styles:
- text-align: 'left'
- - class: text-center
- styles:
- text-align: 'center'
- - class: text-end
- styles:
- text-align: 'right'
- - 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'
- - class: font-monospace
- styles:
- font-family: 'var(--bs-font-monospace)'
- - class: fs-1
- styles:
- font-size: 'calc(1.375rem + 1.5vw)'
- - class: fs-2
- styles:
- font-size: 'calc(1.325rem + 0.9vw)'
- - class: fs-3
- styles:
- font-size: 'calc(1.3rem + 0.6vw)'
- - class: fs-4
- styles:
- font-size: 'calc(1.275rem + 0.3vw)'
- - class: fs-5
- styles:
- font-size: '1.25rem'
- - class: fs-6
- styles:
- font-size: '1rem'
- - class: fst-italic
- styles:
- font-style: 'italic'
- - class: fst-normal
- styles:
- font-style: 'normal'
- - class: fw-lighter
- styles:
- font-weight: 'lighter'
- - class: fw-light
- styles:
- font-weight: '300'
- - class: fw-normal
- styles:
- font-weight: '400'
- - class: fw-medium
- styles:
- font-weight: '500'
- - class: fw-semibold
- styles:
- font-weight: '600'
- - class: fw-bold
- styles:
- font-weight: '700'
- - class: fw-bolder
- styles:
- font-weight: 'bolder'
- - class: lh-1
- styles:
- line-height: '1'
- - class: lh-sm
- styles:
- line-height: '1.25'
- - class: lh-base
- styles:
- line-height: '1.5'
- - class: lh-lg
- styles:
- line-height: '1.75'
- - class: text-decoration-none
- styles:
- text-decoration: 'none'
- - class: text-decoration-underline
- styles:
- text-decoration: 'underline'
- - class: text-decoration-line-through
- styles:
- text-decoration: 'line-through'
- - class: text-lowercase
- styles:
- text-transform: 'lowercase'
- - class: text-uppercase
- styles:
- text-transform: 'uppercase'
- - class: text-capitalize
- styles:
- text-transform: 'capitalize'
----
-
-## Text alignment
-
-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.
-
-<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-2xl-end">End aligned text on viewports sized 2XL (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>
-
-## 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>
-
-## 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.
-
-## 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>`} />
-
-## Monospace
-
-Change a selection to our monospace font stack with `.font-monospace`.
-
-<Example code={`<p class="font-monospace">This is in monospace</p>`} />
-
-## 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>`} />
-
-## 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>`} />
-
-## CSS
-
-### Sass variables
-
-Default type and font related Sass variables:
-
-<ScssDocs name="font-variables" file="scss/_variables.scss" />
-
-### Sass maps
-
-Font-size utilities are generated from this map, in combination with our utilities API.
-
-<ScssDocs name="font-sizes" file="scss/_variables.scss" />
-
-### Sass utilities API
-
-Font and text utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
-
-<ScssDocs name="utils-text" file="scss/_utilities.scss" />
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'
+utility:
+ - user-select
---
## Overview
---
title: Vertical alignment
description: Easily change the vertical alignment of inline, inline-block, inline-table, and table cell elements.
-reference:
- - class: align-baseline
- styles:
- vertical-align: 'baseline'
- - class: align-top
- styles:
- vertical-align: 'top'
- - class: align-middle
- styles:
- vertical-align: 'middle'
- - class: align-bottom
- styles:
- vertical-align: 'bottom'
- - class: align-text-bottom
- styles:
- vertical-align: 'text-bottom'
- - class: align-text-top
- styles:
- vertical-align: 'text-top'
+utility:
+ - align
---
Change the alignment of elements with the [`vertical-alignment`](https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align) utilities. Please note that vertical-align only affects inline, inline-block, inline-table, and table cell elements.
---
title: Visibility
description: Control the visibility of elements, without modifying their display, with visibility utilities.
-reference:
- - class: visible
- styles:
- visibility: 'visible'
- - class: invisible
- styles:
- visibility: 'hidden'
+utility:
+ - visibility
---
Set the `visibility` of elements with our visibility utilities. These utility classes do not modify the `display` value at all and do not affect layout – `.invisible` elements still take up space in the page.
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'
+utility:
+ - width
+ - max-width
+ - min-width
+ - viewport-width
+ - min-viewport-width
---
-## 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.
+Use width utilities to set the width of elements. Width utilities are generated from the utility API and include support for a preset scale, percentage values, intrinsic sizing keywords, and viewport units.
+
+## Width
+
+Set width using `.w-{size}` utilities for any size from `1` to `12`. These classes are generated from the utility API based on the `$sizes` map in `_variables.scss`. Each number is a multiple of the `$spacer` variable, which defaults to `1rem`.
+
+<Example
+ class="bd-example-flex"
+ code={`<div class="w-12 p-3">Width 12</div>`}
+ customMarkup={`<div class="d-flex flex-column gap-3">
+ <div class="w-1">…</div>
+ <div class="w-2">…</div>
+ <div class="w-3">…</div>
+ <div class="w-4">…</div>
+ <div class="w-5">…</div>
+ <div class="w-6">…</div>
+ <div class="w-7">…</div>
+ <div class="w-8">…</div>
+ <div class="w-9">…</div>
+ <div class="w-10">…</div>
+ <div class="w-11">…</div>
+ <div class="w-12">…</div>
+ </div>`} />
## Relative width
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)
-),
-```
+<ScssDocs name="utils-width" file="scss/_utilities.scss" />
--- /dev/null
+---
+title: Word break
+description: Prevent long strings of text from breaking your components' layout by using word break utilities.
+toc: true
+utility:
+ - word-wrap
+---
+
+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
+
+Word break utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]([[docsref:/utilities/api#using-the-api]])
+
+<ScssDocs name="utils-text-break" file="scss/_utilities.scss" />
title: Z-index
description: Use our low-level `z-index` utilities to quickly change the stack level of an element or component.
toc: true
-reference:
- - class: z-n1
- styles:
- z-index: '-1'
- - class: z-0
- styles:
- z-index: '0'
- - class: z-1
- styles:
- z-index: '1'
- - class: z-2
- styles:
- z-index: '2'
- - class: z-3
- styles:
- z-index: '3'
+utility:
+ - z-index
---
## Example
import DocsSidebar from '@components/DocsSidebar.astro'
import TableOfContents from '@components/TableOfContents.astro'
import ReferenceTable from '@components/ReferenceTable.astro'
+import UtilityReferenceTable from '@components/UtilityReferenceTable.astro'
+import HelperReferenceTable from '@components/HelperReferenceTable.astro'
import { getData } from '@libs/data'
import GitHubIcon from '@components/icons/GitHubIcon.astro'
import MdnIcon from '@components/icons/MdnIcon.astro'
let prevPage: NavigationPage | undefined
let nextPage: NavigationPage | undefined
-// Create a flat array of all pages with their groups
-const allPages = sidebar.flatMap((group) => {
+// Create a flat array of all pages with their groups, handling nested groups
+const allPages: NavigationPage[] = sidebar.flatMap((group) => {
if (!group.pages) return []
- return group.pages.map((page) => ({
- title: page.title,
- url: `/docs/${getConfig().docs_version}/${getSlug(group.title)}/${getSlug(page.title)}/`,
- groupTitle: group.title
- }))
+ return group.pages.flatMap((item: any) => {
+ // Handle nested groups (e.g., Utilities > Borders > Border)
+ if (item.group && item.pages) {
+ return item.pages.map((page: any) => ({
+ title: page.title,
+ url: `/docs/${getConfig().docs_version}/${getSlug(group.title)}/${getSlug(page.title)}/`,
+ groupTitle: item.group
+ }))
+ }
+ // Handle direct pages
+ if (item.title) {
+ return [{
+ title: item.title,
+ url: `/docs/${getConfig().docs_version}/${getSlug(group.title)}/${getSlug(item.title)}/`,
+ groupTitle: group.title
+ }]
+ }
+ return []
+ })
})
// Find the current page index
)
}
+ {
+ frontmatter.utility && (
+ <div class="mb-5">
+ <UtilityReferenceTable utility={frontmatter.utility} />
+ </div>
+ )
+ }
+
+ {
+ frontmatter.classes && (
+ <div class="mb-5">
+ <HelperReferenceTable classes={frontmatter.classes} />
+ </div>
+ )
+ }
+
<slot />
<nav class="bd-links-nav py-5 mt-5 border-top">
- <div class="d-flex flex-column flex-md-row justify-content-between">
+ <div class="d-flex flex-column flex-md-row justify-content-stretch gap-3 gap-md-5">
{
prevPage && (
- <a href={prevPage.url} class="d-block p-3 text-decoration-none rounded-3">
- <div class="text-secondary small">← Previous</div>
- <div class="fw-semibold">{prevPage.title}</div>
- <div class="text-secondary small">{prevPage.groupTitle}</div>
+ <a href={prevPage.url} class="d-block p-3 text-decoration-none border rounded-3 flex-grow-1">
+ <div class="fg-3">← Previous</div>
+ <div class="fs-5 fw-semibold">{prevPage.title}</div>
+ <div class="fg-3">{prevPage.groupTitle}</div>
</a>
)
}
{
nextPage && (
- <a href={nextPage.url} class="d-block p-3 text-decoration-none text-end bg-1 rounded-3">
- <div class="color-3">Next →</div>
+ <a href={nextPage.url} class="d-block p-3 text-decoration-none text-end border rounded-3 flex-grow-1">
+ <div class="fg-3">Next →</div>
<div class="fs-5 fw-semibold">{nextPage.title}</div>
- <div class="color-3">{nextPage.groupTitle}</div>
+ <div class="fg-3">{nextPage.groupTitle}</div>
</a>
)
}
-import { getCollection, getEntryBySlug } from 'astro:content'
+import { getCollection, getEntry, getEntryBySlug } from 'astro:content'
export const docsPages = await getCollection('docs')
export const callouts = await getCollection('callouts')
+export const details = await getCollection('details')
export const aliasedDocsPages = await getCollection('docs', ({ data }) => {
return data.aliases !== undefined
export function getCalloutByName(name: string) {
return getEntryBySlug('callouts', name)
}
+
+export function getDetailsByName(name: string) {
+ return getEntry('details', name)
+}
}
}
+ .bd-example-border-color-utils {
+ [class^="border"] {
+ padding: .5rem .75rem;
+ }
+ }
+
.bd-example-rounded-utils {
[class*="rounded"] {
margin: .25rem;
--- /dev/null
+@use "../../../scss/config" as *;
+@use "../../../scss/colors" as *;
+@use "../../../scss/mixins/border-radius" as *;
+@use "../../../scss/mixins/transition" as *;
+
+@layer custom {
+ .bd-details {
+ margin-block: 1.25rem;
+ color: var(--bs-fg-3);
+ background-color: var(--bs-bg-1);
+ @include border-radius(var(--bs-border-radius-lg));
+
+ &:hover,
+ &[open] {
+ color: var(--bs-fg-body);
+ background-color: var(--bs-bg-2);
+ }
+
+ .bd-details-summary {
+ display: flex;
+ gap: .25rem;
+ align-items: center;
+ padding: 1rem 1.25rem;
+ font-weight: 600;
+ list-style: none;
+ cursor: pointer;
+ user-select: none;
+
+ &::-webkit-details-marker {
+ display: none;
+ }
+
+ &::marker {
+ display: none;
+ }
+ }
+
+ .bd-details-icon {
+ flex-shrink: 0;
+ @include transition(transform .2s ease-in-out);
+ }
+
+ &[open] .bd-details-icon {
+ transform: rotate(90deg);
+ }
+
+ .bd-details-content {
+ padding: 0 1.25rem 1.25rem;
+
+ a { font-weight: 500; }
+
+ > :last-child {
+ margin-bottom: 0;
+ }
+ }
+ }
+}
--- /dev/null
+// Background patterns for documentation examples
+
+// Diagonal stripe pattern
+// 1px stroke, 5px gap, 45deg angle
+.bd-pattern-diagonal {
+ --bd-fill: color-mix(in oklch, var(--bs-fg-body) 10%, transparent);
+ --bd-border: color-mix(in oklch, var(--bs-fg-body) 8%, transparent);
+ background-image: repeating-linear-gradient(-45deg, var(--bd-fill) 0 1px, transparent 0 50%);
+ background-clip: padding-box;
+ background-size: 8px 8px;
+ border: 1px solid var(--bd-border);
+}
+
+.bd-pattern-diagonal-inner {
+ --bd-fill: color-mix(in oklch, var(--bs-bg-body) 35%, transparent);
+ background-image: repeating-linear-gradient(45deg, var(--bd-fill) 0 1px, transparent 0 50%);
+ background-size: 8px 8px;
+}
+
+// Staggered dot grid pattern
+// 1x1px dots, 4-5px spacing between
+// Even rows shifted half a space for brick-like effect
+.bd-pattern-dots {
+ --bd-size: 5px;
+ --bd-dot: .5px;
+ --bd-fill: color-mix(in oklch, var(--bs-fg-3) 20%, transparent);
+ background-image: radial-gradient(circle, var(--bd-fill) var(--bd-dot), transparent var(--bd-dot)), radial-gradient(circle, var(--bd-fill) var(--bd-dot), transparent var(--bd-dot));
+ background-position: 0 0, calc(var(--bd-size) / 2) calc(var(--bd-size) / 2);
+ background-size: var(--bd-size) var(--bd-size);
+ border: 1px solid var(--bd-fill);
+}
.bd-links-heading {
color: var(--bs-emphasis-color);
}
+ .bd-links-heading .bi {
+ width: 16px;
+ height: 16px;
+ }
.bd-links-subgroup {
- margin-left: 1.625rem;
+ margin-left: 1.5rem;
color: var(--bs-emphasis-color);
}
.bd-links-link {
padding: .1875rem .5rem;
margin-top: .125rem;
- margin-left: 1.125rem;
+ margin-left: 1rem;
font-size: .875rem;
color: var(--bs-body-color);
- text-decoration: if($link-decoration == none, null, none);
+ text-decoration: none;
&:hover,
&:focus,
&.active {
color: var(--bs-emphasis-color);
- text-decoration: if($link-hover-decoration == underline, none, null);
background-color: var(--bd-sidebar-link-bg);
}
@use "component-examples";
@use "buttons";
@use "callouts";
+@use "details";
@use "brand";
@use "colors";
@use "clipboard-js";
@use "placeholder-img";
@use "scrolling";
+@use "patterns";
// Load docs dependencies
@use "syntax";
export const CalloutDeprecatedDarkVariants: typeof import('@shortcodes/CalloutDeprecatedDarkVariants.astro').default
export const Code: typeof import('@shortcodes/Code.astro').default
export const DeprecatedIn: typeof import('@shortcodes/DeprecatedIn.astro').default
+ export const Details: typeof import('@shortcodes/Details.astro').default
export const Example: typeof import('@shortcodes/Example.astro').default
export const JsDismiss: typeof import('@shortcodes/JsDismiss.astro').default
export const JsDocs: typeof import('@shortcodes/JsDocs.astro').default