bootstrap
bootstrap copied to clipboard
Grid System should support CSS Container Queries for responsive column sizing
Prerequisites
- [X] I have searched for duplicate or closed feature requests
- [X] I have read the contributing guidelines
Proposal
CSS Container Queries are becoming widely supported.
- https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries
- https://caniuse.com/css-container-queries
Proposal: _breakpoints.scss
should be extended to be configurable to use container queries, perhaps defaulting to the body or falling back to media queries where appropriate for backwards compatibility.
Motivation and context
I have pages that can be displayed in either modal or full-page and currently there isn't a good way to wire up this sort of functionality.
Layouts with collapsible side navigation or modal dialogs would benefit from Container Queries instead of using normal Media Queries for responsive widths.
I'm having the same issue, with grid layouts that get squished when rendered inside modals. Here's a quick hack that just stacks grid columns inside modals:
// Stack grid columns when displayed in a modal
@each $breakpoint in map-keys($grid-breakpoints) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
@for $i from 1 through $grid-columns {
.modal .col#{$infix}-#{$i} {
width: 100%;
}
}
}
Adding this, any .col-BP-I
class inside a modal will just stretch to full-width. It's a bit brutal but it works well. And it doesn't even need container queries, making it compatible with older browsers 😉
Thanks @goulvench this is a nice workaround, but doesn't fully solve the need. For instance, if we have a shared component inside one of bootstrap's various modal sizes: https://getbootstrap.com/docs/5.3/components/modal/#optional-sizes
An additional scenario I'm trying to support is a layout with a side nav menu that can be expanded or collapsed. I'd like the grid system to be based on the width of the "main" component rather than the whole page width.
I solved my problem (which was that i wanted to be responsive against the size of my content-container) with patch-package with the following patch (named patches/bootstrap+5.2.3.patch) :
The following Code does not set breakpoints relative to @media but relative to the element you add a specific class to.
diff --git a/node_modules/bootstrap/scss/mixins/_breakpoints.scss b/node_modules/bootstrap/scss/mixins/_breakpoints.scss
index 286be89..f80a7ea 100644
--- a/node_modules/bootstrap/scss/mixins/_breakpoints.scss
+++ b/node_modules/bootstrap/scss/mixins/_breakpoints.scss
@@ -61,7 +61,7 @@
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
$min: breakpoint-min($name, $breakpoints);
@if $min {
- @media (min-width: $min) {
+ @container #{$containerName} (min-width: #{$min}) {
@content;
}
} @else {
@@ -74,7 +74,7 @@
@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {
$max: breakpoint-max($name, $breakpoints);
@if $max {
- @media (max-width: $max) {
+ @container #{$containerName} (max-width: #{$max}) {
@content;
}
} @else {
@@ -89,7 +89,7 @@
$max: breakpoint-max($upper, $breakpoints);
@if $min != null and $max != null {
- @media (min-width: $min) and (max-width: $max) {
+ @container #{$containerName} (min-width: #{$min}) and (max-width: #{$max}) {
@content;
}
} @else if $max == null {
@@ -112,7 +112,7 @@
$max: breakpoint-max($next, $breakpoints);
@if $min != null and $max != null {
- @media (min-width: $min) and (max-width: $max) {
+ @container #{$containerName} (min-width: #{$min}) and (max-width: #{$max}) {
@content;
}
} @else if $max == null {
and an additional styling:
$containerName: mainSection;
// to have a fallback if certain elements are not inside the .breakpoint-container class (like modals or notifications)
body{
container-type: inline-size;
container-name: $containerName;
}
.breakpoint-container {
container-type: inline-size;
container-name: $containerName;
}
and used like this:
...
<app-sidebar ></app-sidebar>
<div>
<app-header></app-header>
<section class="breakpoint-container">
...
</section>
<app-footer ></app-footer>
</div>
...
But i hope it gets built in in some form!
EDIT: added fallback to body container
@Joniras where did you add the additional styling? Could you create a Repository or something like that for your fix?
Thank you!
@Schwarcelo The additional styling has to be applied on a global level. It has to be included before the bootstrap scss because the scss variable is defined in the additional styling and used in the (changed) bootstrap mixins.
+1 for that feature. E.g. creating cards or square-tiles holding lots of content (e.g. header, sub-header, text, buttons, ...) where the font-size should be scaled beside being rendered in 1-4 responsive columns depending on the parents width, is a huge mess just using breakpoints.
Bootstrap are in dire need of adding this, it is such a basic necessity, that columns should be based on the container that they're in and not the device width. iFrames, modals, even just adding in an aside to a page stuffs up all of your bootstrap responsive classes.
### PLEASE ADD THIS IN ASAP!!!!!!!!!!!!!!!!!!!!!!
I have added this to my scss for the time being:
.cq {
display: flex;
flex-wrap: wrap;
container-type: inline-size;
& > * {
flex: 0 0 auto;
width: 100cqw;
}
}
@each $infix, $breakpoint in $grid-breakpoints {
@container (min-width: #{$breakpoint}) {
.cq-#{$infix}-1 {
width: 8.33333333cqw;
}
.cq-#{$infix}-2 {
width: 16.66666667cqw;
}
.cq-#{$infix}-3 {
width: 25cqw;
}
.cq-#{$infix}-4 {
width: 33.33333333cqw;
}
.cq-#{$infix}-5 {
width: 41.66666667cqw;
}
.cq-#{$infix}-6 {
width: 50cqw;
}
.cq-#{$infix}-7 {
width: 58.33333333cqw;
}
.cq-#{$infix}-8 {
width: 66.66666667cqw;
}
.cq-#{$infix}-9 {
width: 75cqw;
}
.cq-#{$infix}-10 {
width: 83.33333333cqw;
}
.cq-#{$infix}-11 {
width: 91.66666667cqw;
}
.cq-#{$infix}-12 {
width: 100cqw;
}
}
}
so you can use it like row/col:
<div class="cq">
<div class="cq-sm-6 cq-lg-4">Hello</div>
<div class="cq-sm-6 cq-lg-4">Hello</div>
<div class="cq-sm-6 cq-lg-4">Hello</div>
</div>
I have started a repo to try implementing container queries in the bootstrap way, but it's still work in progress: https://github.com/bastienmoulia/bootstrap-container-queries PR welcomed 😉