Skip to content

Commit 235be68

Browse files
mdoCopilot
andcommitted
v6: Range media queries (#41786)
* wip Co-Authored-By: mdo <98681+mdo@users.noreply.github.com> * linty linterton --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: mdo <98681+mdo@users.noreply.github.com>
1 parent 53d1cdb commit 235be68

File tree

5 files changed

+128
-35
lines changed

5 files changed

+128
-35
lines changed

scss/layout/_breakpoints.scss

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map.keys($breakpoints)) {
2222
$n: list.index($breakpoint-names, $name);
2323
@if not $n {
24-
@error "breakpoint `#{$name}` not found in `#{$breakpoints}`";
24+
@error "breakpoint `#{$name}` not found in `#{$breakpoint-names}`";
2525
}
2626
@return if($n < list.length($breakpoint-names), list.nth($breakpoint-names, $n + 1), null);
2727
}
@@ -35,18 +35,19 @@
3535
@return if($min != 0, $min, null);
3636
}
3737

38-
// Maximum breakpoint width.
39-
// The maximum value is reduced by 0.02px to work around the limitations of
40-
// `min-` and `max-` prefixes and viewports with fractional widths.
41-
// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max
42-
// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.
43-
// See https://bugs.webkit.org/show_bug.cgi?id=178261
38+
// Maximum breakpoint width for range media queries.
39+
// Returns the breakpoint value to use as an upper bound in range queries.
4440
//
45-
// >> breakpoint-max(md, (xs: 0, sm: 576px, md: 768px, lg: 1024px, xl: 1280px, 2xl: 1536px))
46-
// 767.98px
41+
// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 1024px, xl: 1280px, 2xl: 1536px))
42+
// 576px
43+
// >> breakpoint-max(xxl, (xs: 0, sm: 576px, md: 768px, lg: 1024px, xl: 1280px, 2xl: 1536px))
44+
// null
4745
@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {
46+
@if $name == null {
47+
@return null;
48+
}
4849
$max: map.get($breakpoints, $name);
49-
@return if($max and $max > 0, $max - .02, null);
50+
@return if($max and $max > 0, $max, null);
5051
}
5152

5253
// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.
@@ -65,7 +66,7 @@
6566
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
6667
$min: breakpoint-min($name, $breakpoints);
6768
@if $min {
68-
@media (min-width: $min) {
69+
@media (width >= $min) {
6970
@content;
7071
}
7172
} @else {
@@ -78,7 +79,7 @@
7879
@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {
7980
$max: breakpoint-max($name, $breakpoints);
8081
@if $max {
81-
@media (max-width: $max) {
82+
@media (width < $max) {
8283
@content;
8384
}
8485
} @else {
@@ -93,7 +94,7 @@
9394
$max: breakpoint-max($upper, $breakpoints);
9495

9596
@if $min != null and $max != null {
96-
@media (min-width: $min) and (max-width: $max) {
97+
@media (width >= $min) and (width < $max) {
9798
@content;
9899
}
99100
} @else if $max == null {
@@ -116,7 +117,7 @@
116117
$max: breakpoint-max($next, $breakpoints);
117118

118119
@if $min != null and $max != null {
119-
@media (min-width: $min) and (max-width: $max) {
120+
@media (width >= $min) and (width < $max) {
120121
@content;
121122
}
122123
} @else if $max == null {
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
@import "true";
2+
@import "../../mixins/breakpoints";
3+
4+
// Test breakpoint functions and mixins for range media query syntax
5+
6+
@include test-module("Breakpoint Functions") {
7+
$test-breakpoints: (
8+
xs: 0,
9+
sm: 576px,
10+
md: 768px,
11+
lg: 1024px,
12+
xl: 1280px,
13+
xxl: 1536px
14+
);
15+
16+
@include test("breakpoint-max with range syntax") {
17+
@include assert-equal(breakpoint-max(xs, $test-breakpoints), null);
18+
@include assert-equal(breakpoint-max(sm, $test-breakpoints), 576px);
19+
@include assert-equal(breakpoint-max(md, $test-breakpoints), 768px);
20+
@include assert-equal(breakpoint-max(lg, $test-breakpoints), 1024px);
21+
@include assert-equal(breakpoint-max(xl, $test-breakpoints), 1280px);
22+
@include assert-equal(breakpoint-max(xxl, $test-breakpoints), 1536px);
23+
}
24+
}
25+
26+
@include test-module("Media Query Mixins - Range Syntax") {
27+
$test-breakpoints: (
28+
xs: 0,
29+
sm: 576px,
30+
md: 768px,
31+
lg: 1024px,
32+
xl: 1280px,
33+
xxl: 1536px
34+
);
35+
36+
@include test("media-breakpoint-up generates range syntax") {
37+
@include assert() {
38+
@include output() {
39+
@include media-breakpoint-up(sm, $test-breakpoints) {
40+
.test { color: #f00; }
41+
}
42+
}
43+
@include expect() {
44+
@media (width >= 576px) {
45+
.test { color: #f00; }
46+
}
47+
}
48+
}
49+
}
50+
51+
@include test("media-breakpoint-down generates range syntax") {
52+
@include assert() {
53+
@include output() {
54+
@include media-breakpoint-down(md, $test-breakpoints) {
55+
.test { color: #00f; }
56+
}
57+
}
58+
@include expect() {
59+
@media (width < 768px) {
60+
.test { color: #00f; }
61+
}
62+
}
63+
}
64+
}
65+
66+
@include test("media-breakpoint-between generates range syntax") {
67+
@include assert() {
68+
@include output() {
69+
@include media-breakpoint-between(sm, lg, $test-breakpoints) {
70+
.test { color: #0f0; }
71+
}
72+
}
73+
@include expect() {
74+
@media (width >= 576px) and (width < 1024px) {
75+
.test { color: #0f0; }
76+
}
77+
}
78+
}
79+
}
80+
81+
@include test("media-breakpoint-only generates range syntax") {
82+
@include assert() {
83+
@include output() {
84+
@include media-breakpoint-only(md, $test-breakpoints) {
85+
.test { color: #ff0; }
86+
}
87+
}
88+
@include expect() {
89+
@media (width >= 768px) and (width < 1024px) {
90+
.test { color: #ff0; }
91+
}
92+
}
93+
}
94+
}
95+
}

scss/tests/utilities/_api.test.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ $utilities: ();
5353
font-size: 1.25rem !important;
5454
}
5555

56-
@media (min-width: 333px) {
56+
@media (width >= 333px) {
5757
.padding-sm-1rem {
5858
padding: 1rem !important;
5959
}
6060
}
6161

62-
@media (min-width: 666px) {
62+
@media (width >= 666px) {
6363
.padding-md-1rem {
6464
padding: 1rem !important;
6565
}

site/src/content/callouts/info-mediaqueries-breakpoints.md

Lines changed: 0 additions & 1 deletion
This file was deleted.

site/src/content/docs/layout/breakpoints.mdx

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,19 @@ These Sass mixins translate in our compiled CSS using the values declared in our
7474
// No media query for `xs` since this is the default in Bootstrap
7575

7676
// Small devices (landscape phones, 576px and up)
77-
@media (min-width: 576px) { ... }
77+
@media (width >= 576px) { ... }
7878

7979
// Medium devices (tablets, 768px and up)
80-
@media (min-width: 768px) { ... }
80+
@media (width >= 768px) { ... }
8181

8282
// Large devices (desktops, 1024px and up)
83-
@media (min-width: 1024px) { ... }
83+
@media (width >= 1024px) { ... }
8484

8585
// X-Large devices (large desktops, 1280px and up)
86-
@media (min-width: 1280px) { ... }
86+
@media (width >= 1280px) { ... }
8787

8888
// XX-Large devices (larger desktops, 1536px and up)
89-
@media (min-width: 1536px) { ... }
89+
@media (width >= 1536px) { ... }
9090
```
9191

9292
### Max-width
@@ -109,30 +109,28 @@ We occasionally use media queries that go in the other direction (the given scre
109109
}
110110
```
111111

112-
These mixins take those declared breakpoints, subtract `.02px` from them, and use them as our `max-width` values. For example:
112+
These mixins use the breakpoint values to create `max-width` media queries using modern range syntax. For example:
113113

114114
```scss
115115
// `xs` returns only a ruleset and no media query
116116
// ... { ... }
117117

118118
// `sm` applies to x-small devices (portrait phones, less than 576px)
119-
@media (max-width: 575.98px) { ... }
119+
@media (width < 576px) { ... }
120120

121121
// `md` applies to small devices (landscape phones, less than 768px)
122-
@media (max-width: 767.98px) { ... }
122+
@media (width < 768px) { ... }
123123

124-
// `lg` applies to medium devices (tablets, less than 992px)
125-
@media (max-width: 991.98px) { ... }
124+
// `lg` applies to medium devices (tablets, less than 1024px)
125+
@media (width < 1024px) { ... }
126126

127-
// `xl` applies to large devices (desktops, less than 1200px)
128-
@media (max-width: 1199.98px) { ... }
127+
// `xl` applies to large devices (desktops, less than 1280px)
128+
@media (width < 1280px) { ... }
129129

130-
// `2xl` applies to x-large devices (large desktops, less than 1600px)
131-
@media (max-width: 1599.98px) { ... }
130+
// `2xl` applies to x-large devices (large desktops, less than 1536px)
131+
@media (width < 1536px) { ... }
132132
```
133133

134-
<Callout name="info-mediaqueries-breakpoints" type="warning" />
135-
136134
### Single breakpoint
137135

138136
There are also media queries and mixins for targeting a single segment of screen sizes using the minimum and maximum breakpoint widths.
@@ -149,7 +147,7 @@ There are also media queries and mixins for targeting a single segment of screen
149147
For example the `@include media-breakpoint-only(md) { ... }` will result in :
150148

151149
```scss
152-
@media (min-width: 768px) and (max-width: 991.98px) { ... }
150+
@media (width >= 768px) and (width < 992px) { ... }
153151
```
154152

155153
### Between breakpoints
@@ -165,5 +163,5 @@ Which results in:
165163
```scss
166164
// Example
167165
// Apply styles starting from medium devices and up to extra large devices
168-
@media (min-width: 768px) and (max-width: 1199.98px) { ... }
166+
@media (width >= 768px) and (width < 1200px) { ... }
169167
```

0 commit comments

Comments
 (0)