Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scss/_card.scss
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ $card-tokens: defaults(
//

// Card groups lay out their cards in a row using a container query, so wrap the
// group in a query container (e.g., the `.contains-inline` utility) for the row
// group in a query container (e.g., the `.container-inline` utility) for the row
// layout to take effect. Without a query container the cards remain stacked.
.card-group {
// The child selector allows nested `.card` within `.card-group`
Expand Down
2 changes: 1 addition & 1 deletion scss/_config.scss
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ $spacers: (

$negative-spacers: (
"-1": $spacer * -.25,
"-2": $spacer * -.5,
"-2": $spacer * -.375,
) !default;
// scss-docs-end spacer-variables-maps

Expand Down
1 change: 1 addition & 0 deletions scss/_dialog.scss
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ $dialog-sizes: defaults(
--dialog-width: 100vw;
--dialog-margin: 0;
--dialog-border-radius: 0;
--dialog-border-width: 0;

width: 100%;
max-width: none;
Expand Down
2 changes: 1 addition & 1 deletion scss/_list-group.scss
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ $list-group-tokens: defaults(
//
// Change the layout of list group items from vertical (default) to horizontal.
// The responsive variants use container queries, so wrap the list group in a
// query container (e.g., the `.contains-inline` utility) for them to take effect.
// query container (e.g., the `.container-inline` utility) for them to take effect.

@include loop-breakpoints-up() using ($breakpoint, $prefix) {
.#{$prefix}list-group-horizontal {
Expand Down
4 changes: 3 additions & 1 deletion scss/_utilities.scss
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,16 @@ $utilities: map.merge(
values: auto hidden visible scroll,
),
// scss-docs-end utils-overflow
// scss-docs-start utils-container
"container": (
property: container-type,
class: contains,
class: container,
values: (
"inline": inline-size,
"size": size,
)
),
// scss-docs-end utils-container
// scss-docs-start utils-display
"display": (
responsive: true,
Expand Down
2 changes: 2 additions & 0 deletions scss/content/_reboot.scss
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ $reboot-mark-tokens: defaults(
background-color: var(--bg-body); // 2
-webkit-text-size-adjust: 100%; // 3
-webkit-tap-highlight-color: transparent; // 4
container-type: inline-size;
container-name: body;
}
// scss-docs-end reboot-body-rules

Expand Down
2 changes: 2 additions & 0 deletions scss/layout/_containers.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
// 100% wide container at all breakpoints
.container-fluid {
@include make-container();
container-type: inline-size;
container-name: layout;
}

// Responsive containers that are 100% wide until a breakpoint
Expand Down
4 changes: 3 additions & 1 deletion scss/layout/_grid.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@use "../config" as *;
@use "breakpoints" as *;
@use "../mixins/grid" as *;

// TODO: check gap utilities as replacement for gutter classes from v5
Expand All @@ -22,11 +23,12 @@
--rows: 1;
--gap: #{$grid-gutter-x};

@include set-container();

display: grid;
grid-template-rows: repeat(var(--rows), 1fr);
grid-template-columns: repeat(var(--columns), 1fr);
gap: var(--gap);

}

@include make-cssgrid();
Expand Down
7 changes: 5 additions & 2 deletions scss/mixins/_grid.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
@mixin make-row($gutter-x: $grid-gutter-x, $gutter-y: $grid-gutter-y) {
--gutter-x: #{$gutter-x};
--gutter-y: #{$gutter-y};

@include set-container();

display: flex;
flex-wrap: wrap;
// TODO: Revisit calc order after https://github.com/react-bootstrap/react-bootstrap/issues/6039 is fixed
Expand Down Expand Up @@ -75,7 +78,7 @@
@each $breakpoint in map.keys($breakpoints) {
$prefix: breakpoint-prefix($breakpoint, $breakpoints);

@include media-breakpoint-up($breakpoint, $breakpoints) {
@include container-breakpoint-up($breakpoint, $breakpoints: $breakpoints) {
.#{$prefix}col {
flex: 1 0 0;
}
Expand Down Expand Up @@ -135,7 +138,7 @@
@each $breakpoint in map.keys($breakpoints) {
$prefix: breakpoint-prefix($breakpoint, $breakpoints);

@include media-breakpoint-up($breakpoint, $breakpoints) {
@include container-breakpoint-up($breakpoint, $breakpoints: $breakpoints) {
@if $columns > 0 {
@for $i from 1 through $columns {
.#{$prefix}g-col-#{$i} {
Expand Down
3 changes: 3 additions & 0 deletions site/data/sidebar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@
- group: Layout
pages:
- title: Aspect ratio
- title: Container
meta:
- added: 6.0.0
- title: Display
- title: Float
- title: Object fit
Expand Down
55 changes: 54 additions & 1 deletion site/src/components/shortcodes/ResizableExample.astro
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ interface Props {
* @default true
*/
showMarkup?: boolean
/**
* Whether to show a floating badge indicating the active container query
* breakpoint for the resized container.
* @default false
*/
showBreakpoint?: boolean
}

const {
Expand All @@ -38,7 +44,8 @@ const {
className,
initialWidth = '100%',
minWidth = '200px',
showMarkup = true
showMarkup = true,
showBreakpoint = false
} = Astro.props

// Support both class and className props
Expand Down Expand Up @@ -69,7 +76,53 @@ const simplifiedMarkup = markup.replace(
style={`width: ${initialWidth}; min-width: ${minWidth};`}
>
<Fragment set:html={previewMarkup} />
{showBreakpoint && <output class="bd-resizable-badge" data-resizable-badge aria-live="polite" />}
</div>
</div>
{showMarkup && <Code code={simplifiedMarkup} lang="html" nestedInExample={true} />}
</div>

<script>
// Breakpoints mirror `$breakpoints` in scss/_config.scss. Container queries are
// evaluated against the content-box inline size of the nearest query container.
const breakpoints = [
{ name: 'xs', min: 0 },
{ name: 'sm', min: 576 },
{ name: 'md', min: 768 },
{ name: 'lg', min: 1024 },
{ name: 'xl', min: 1280 },
{ name: '2xl', min: 1536 }
]

function activeBreakpoint(width: number) {
let active = breakpoints[0]
for (const bp of breakpoints) {
if (width >= bp.min) active = bp
}
return active
}

document.querySelectorAll<HTMLElement>('[data-resizable-badge]').forEach((badge) => {
const container = badge.closest<HTMLElement>('.bd-resizable-container')
if (!container) return

// Measure the actual query container (e.g. `.grid`) when present so the badge
// matches what `@container` evaluates; otherwise fall back to the container.
const target = container.querySelector<HTMLElement>(':scope > *:not(.bd-resizable-badge)') ?? container

const update = (width: number) => {
const bp = activeBreakpoint(width)
badge.dataset.breakpoint = bp.name
badge.textContent = `${bp.name} · ${Math.round(width)}px`
}

const observer = new ResizeObserver((entries) => {
for (const entry of entries) {
const inlineSize = entry.contentBoxSize?.[0]?.inlineSize ?? entry.contentRect.width
update(inlineSize)
}
})

observer.observe(target, { box: 'content-box' })
})
</script>
2 changes: 1 addition & 1 deletion site/src/components/shortcodes/SpacingNotation.astro
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ const capitalizedNoun = noun.charAt(0).toUpperCase() + noun.slice(1)
// Multipliers for sizes `1` through `9`, mirroring the default `$spacers` map.
const sizeValues = [
'$spacer * .25',
'$spacer * .375',
'$spacer * .5',
'$spacer * .75',
'$spacer',
'$spacer * 1.25',
'$spacer * 1.5',
'$spacer * 2',
'$spacer * 2.5',
'$spacer * 3'
]
---
Expand Down
6 changes: 3 additions & 3 deletions site/src/content/docs/components/card.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -431,9 +431,9 @@ In addition to styling the content within cards, Bootstrap includes a few option

Use card groups to render cards as a single, attached element with equal width and height columns. Card groups start off stacked and use `display: flex;` to become attached with uniform dimensions starting at the `sm` breakpoint.

This layout uses [container queries]([[docsref:/layout/breakpoints#container-queries]]), so wrap the card group in a query container—add the `.contains-inline` utility to a parent element—for the row layout to take effect. Without a query container, the cards remain stacked.
This layout uses [container queries]([[docsref:/layout/breakpoints#container-queries]]), so wrap the card group in a query container—add the `.container-inline` utility to a parent element—for the row layout to take effect. Without a query container, the cards remain stacked.

<ResizableExample code={`<div class="contains-inline">
<ResizableExample code={`<div class="container-inline">
<div class="card-group">
<div class="card">
<Placeholder width="100%" height="180" class="card-img-top" text="Image cap" />
Expand Down Expand Up @@ -464,7 +464,7 @@ This layout uses [container queries]([[docsref:/layout/breakpoints#container-que

When using card groups with footers, their content will automatically line up.

<Example code={`<div class="contains-inline">
<Example code={`<div class="container-inline">
<div class="card-group">
<div class="card">
<Placeholder width="100%" height="180" class="card-img-top" text="Image cap" />
Expand Down
6 changes: 3 additions & 3 deletions site/src/content/docs/components/list-group.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,13 @@ These work great with custom content as well.

Add `.list-group-horizontal` to change the layout of list group items from vertical to horizontal across all container sizes. Alternatively, choose a responsive variant `.{sm|md|lg|xl|2xl}:list-group-horizontal` to make a list group horizontal starting at that breakpoint’s width.

The responsive variants use [container queries]([[docsref:/layout/breakpoints#container-queries]]), so wrap the list group in a query container—add the `.contains-inline` utility to a parent element—for them to take effect. Currently **horizontal list groups cannot be combined with flush list groups.**
The responsive variants use [container queries]([[docsref:/layout/breakpoints#container-queries]]), so wrap the list group in a query container—add the `.container-inline` utility to a parent element—for them to take effect. Currently **horizontal list groups cannot be combined with flush list groups.**

**ProTip:** Want equal-width list group items when horizontal? Add `.flex-fill` to each list group item.

<Example
class="vstack gap-3"
code={getData('breakpoints').map((breakpoint) => `<div class="contains-inline">
code={getData('breakpoints').map((breakpoint) => `<div class="container-inline">
<ul class="list-group ${breakpoint.abbr}list-group-horizontal">
<li class="list-group-item">An item</li>
<li class="list-group-item">A second item</li>
Expand All @@ -132,7 +132,7 @@ The responsive variants use [container queries]([[docsref:/layout/breakpoints#co

Drag the handle to resize the container below and watch the list group switch between vertical and horizontal layouts as the container—not the viewport—crosses the `md` breakpoint.

<ResizableExample code={`<div class="contains-inline">
<ResizableExample code={`<div class="container-inline">
<ul class="list-group md:list-group-horizontal">
<li class="list-group-item">An item</li>
<li class="list-group-item">A second item</li>
Expand Down
4 changes: 2 additions & 2 deletions site/src/content/docs/components/stepper.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ Here’s a simple example of a vertical stepper.

### Responsive

Steppers can be made horizontal at specific breakpoints using the `contains-inline` utility on a parent element and by adding the responsive `.stepper-horizontal-{breakpoint}` modifier classes on the stepper. The extra parent element is required when using container queries.
Steppers can be made horizontal at specific breakpoints using the `container-inline` utility on a parent element and by adding the responsive `.stepper-horizontal-{breakpoint}` modifier classes on the stepper. The extra parent element is required when using container queries.

<ResizableExample code={`<div class="contains-inline">
<ResizableExample code={`<div class="container-inline">
<ol class="stepper sm:stepper-horizontal">
<li class="stepper-item active">Create account</li>
<li class="stepper-item active">Confirm email</li>
Expand Down
2 changes: 1 addition & 1 deletion site/src/content/docs/getting-started/browsers-devices.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ The table below lists the platform features v6 relies on and how each behaves at
| --- | --- | --- |
| `light-dark()` | [Color modes]([[docsref:/customize/color-modes]]), all theme tokens | Defines the support floor; no fallback below it |
| `oklch()`, `color-mix()` | [Color system]([[docsref:/customize/color]]), theme variants | Fully supported above the floor |
| Container queries (`@container`) | [Card groups]([[docsref:/components/card#card-groups]]), [horizontal list groups]([[docsref:/components/list-group#horizontal]]) | Fully supported above the floor; these components also require an ancestor query container (`.contains-inline`)—without one they stay stacked |
| Container queries (`@container`) | [Card groups]([[docsref:/components/card#card-groups]]), [horizontal list groups]([[docsref:/components/list-group#horizontal]]) | Fully supported above the floor; these components also require an ancestor query container (`.container-inline`)—without one they stay stacked |
| `:has()` | Forms, button groups with menus, and other contextual styling | Fully supported above the floor |
| Native `<dialog>` | [Dialog]([[docsref:/components/dialog]]), [Drawer]([[docsref:/components/drawer]]) | Fully supported above the floor; focus containment and `inert` behavior come from the browser |
| `<details name="…">` | [Exclusive accordions]([[docsref:/components/accordion]]) | Fully supported above the floor; in older, unsupported browsers accordion items degrade gracefully to independently openable `<details>` elements |
Expand Down
Loading