Skip to content

Commit 580bee0

Browse files
authored
Merge pull request #11436 from ncoden/feat/js-media-query-down-breakpoint-11122
feat: add support for "down" media queries in "MediaQuery.is()" #11122
2 parents 71f8586 + c857bc2 commit 580bee0

9 files changed

+603
-108
lines changed

docs/pages/grid.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ In order to work around browsers' different rounding behaviors, Foundation will
360360

361361
#### Responsive Gutters
362362

363-
The grid *gutter*—the space between two columns in a row, and the space between the edge of a grid and the edge of the page—is responsive, and becomes wider on larger screens.
363+
The grid *gutter*—the space between two columns in a row, and the space between the edge of a grid and the edge of the page—is responsive, and becomes larger on larger screens.
364364

365365
Breakpoint | Gutter Size
366366
-----------|------------

docs/pages/media-queries.md

+16-14
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ tags:
1818
Foundation for Sites has three core breakpoints:
1919

2020
- **Small:** any screen.
21-
- **Medium:** any screen 640 pixels or wider.
22-
- **Large:** any screen 1024 pixels or wider.
21+
- **Medium:** any screen 640 pixels or larger.
22+
- **Large:** any screen 1024 pixels or larger.
2323

2424
Many components can be modified at different screen sizes using special *breakpoint classes*. The grid is the most obvious example. In the code below, the left-hand column is six columns wide on small screens, hence `.small-6`. On medium-sized screens, the class `.medium-4` overrides the small style, changing the column to be four wide.
2525

@@ -197,22 +197,24 @@ Get the name of the current breakpoint with `MediaQuery.current`.
197197
Foundation.MediaQuery.current // => 'small', 'medium', etc.
198198
```
199199

200-
To see if the screen is currently a certain breakpoint or larger, use `MediaQuery.atLeast`.
201-
200+
You can use `MediaQuery.is()` to check the breakpoint the screen is at.
202201
```js
203-
if (Foundation.MediaQuery.atLeast('medium')) {
204-
// True if medium or large
205-
// False if small
206-
}
202+
Foundation.MediaQuery.is('medium') // => True for "medium" or larger
207203
```
208204

209-
To see if the screen is currently a certain breakpoint, use `MediaQuery.is`.
210-
205+
You can also use the `up` (default), `only` and `down` modifiers like in Sass, or use the equivalent `MediaQuery.atLeast()`, `MediaQuery.only()` and `MediaQuery.upTo()`.
211206
```js
212-
if (Foundation.MediaQuery.is('small only')) {
213-
// True if small
214-
// False if medium or large
215-
}
207+
// ↑ True for "medium" or larger (by default)
208+
Foundation.MediaQuery.is('medium up');
209+
Foundation.MediaQuery.atLeast('medium');
210+
211+
// → True for "medium" only
212+
Foundation.MediaQuery.is('medium only');
213+
Foundation.MediaQuery.only('medium');
214+
215+
// ↓ True for "medium" or larger
216+
Foundation.MediaQuery.is('medium down');
217+
Foundation.MediaQuery.upTo('medium');
216218
```
217219

218220
To get the media query of a breakpoint, use `MediaQuery.get`.

docs/pages/prototyping-utilities.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ This creates a tiny separator below the heading of an element and is usually use
304304

305305
## Font Styling
306306

307-
You can use font styling to style your text. You can change the font styling by adding `font-normal`, `font-bold`, `font-italic` to an element. You can also wider the text of an element with `font-wide`.
307+
You can use font styling to style your text. You can change the font styling by adding `font-normal`, `font-bold`, `font-italic` to an element. You can also larger the text of an element with `font-wide`.
308308

309309
```html_example
310310
<p class="font-wide">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>

docs/pages/typography-base.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ Foundation includes styles for all headings&mdash;they're balanced and sized alo
6161

6262
### Header Styles
6363

64-
The framework includes two typographic scales&mdash;one uses a narrow range of sizes for small-sized screens, and the other uses a wider range of sizes for medium- and larger-sized screens. You can change these scales, or add new ones for other breakpoints, by editing the `$header-styles` map in your project's <a href="sass.html#the-settings-file">Settings File</a>.
64+
The framework includes two typographic scales&mdash;one uses a narrow range of sizes for small-sized screens, and the other uses a larger range of sizes for medium- and larger-sized screens. You can change these scales, or add new ones for other breakpoints, by editing the `$header-styles` map in your project's <a href="sass.html#the-settings-file">Settings File</a>.
6565

6666
<a class="" data-open-video="1:28"><img src="{{root}}assets/img/icons/watch-video-icon.svg" class="video-icon" height="30" width="30" alt=""> Watch this part in video</a>
6767

js/foundation.util.mediaQuery.js

+88-11
Original file line numberDiff line numberDiff line change
@@ -142,20 +142,64 @@ var MediaQuery = {
142142
return false;
143143
},
144144

145+
/**
146+
* Checks if the screen is within the given breakpoint.
147+
* If smaller than the breakpoint of larger than its upper limit it returns false.
148+
* @function
149+
* @param {String} size - Name of the breakpoint to check.
150+
* @returns {Boolean} `true` if the breakpoint matches, `false` otherwise.
151+
*/
152+
only(size) {
153+
return size === this._getCurrentSize();
154+
},
155+
156+
/**
157+
* Checks if the screen is within a breakpoint or smaller.
158+
* @function
159+
* @param {String} size - Name of the breakpoint to check.
160+
* @returns {Boolean} `true` if the breakpoint matches, `false` if it's larger.
161+
*/
162+
upTo(size) {
163+
const nextSize = this.next(size);
164+
165+
// If the next breakpoint does not match, the screen is smaller than
166+
// the upper limit of this breakpoint.
167+
if (nextSize) {
168+
return !this.atLeast(nextSize);
169+
}
170+
171+
// If there is no next breakpoint, the "size" breakpoint does not have
172+
// an upper limit and the screen will always be within it or smaller.
173+
return true;
174+
},
175+
145176
/**
146177
* Checks if the screen matches to a breakpoint.
147178
* @function
148179
* @param {String} size - Name of the breakpoint to check, either 'small only' or 'small'. Omitting 'only' falls back to using atLeast() method.
149180
* @returns {Boolean} `true` if the breakpoint matches, `false` if it does not.
150181
*/
151182
is(size) {
152-
size = size.trim().split(' ');
153-
if(size.length > 1 && size[1] === 'only') {
154-
if(size[0] === this._getCurrentSize()) return true;
155-
} else {
156-
return this.atLeast(size[0]);
183+
const parts = size.trim().split(' ').filter(p => !!p.length);
184+
const [bpSize, bpModifier = ''] = parts;
185+
186+
// Only the breakpont
187+
if (bpModifier === 'only') {
188+
return this.only(bpSize);
157189
}
158-
return false;
190+
// Up to the breakpoint (included)
191+
if (bpModifier === 'down') {
192+
return this.atLeast(bpSize);
193+
}
194+
// At leat the breakpoint (included)
195+
if (!bpModifier || bpModifier === 'up') {
196+
return this.upTo(bpSize);
197+
}
198+
199+
throw new Error(`
200+
Invalid breakpoint passed to MediaQuery.is().
201+
Expected a breakpoint name formatted like "<size> <modifier>", got "${size}".
202+
`);
159203
},
160204

161205
/**
@@ -175,6 +219,43 @@ var MediaQuery = {
175219
return null;
176220
},
177221

222+
/**
223+
* Get the breakpoint following the given breakpoint.
224+
* @function
225+
* @param {String} size - Name of the breakpoint.
226+
* @returns {String|null} - The name of the following breakpoint, or `null` if the passed breakpoint was the last one.
227+
*/
228+
next(size) {
229+
const queryIndex = this.queries.findIndex((q) => this._getQueryName(q) === size);
230+
if (queryIndex === -1) {
231+
throw new Error(`
232+
Unknown breakpoint "${size}" passed to MediaQuery.next().
233+
Ensure it is present in your Sass "$breakpoints" setting.
234+
`);
235+
}
236+
237+
const nextQuery = this.queries[queryIndex + 1];
238+
return nextQuery ? nextQuery.name : null;
239+
},
240+
241+
/**
242+
* Returns the name of the breakpoint related to the given value.
243+
* @function
244+
* @private
245+
* @param {String|Object} value - Breakpoint name or query object.
246+
* @returns {String} Name of the breakpoint.
247+
*/
248+
_getQueryName(value) {
249+
if (typeof value === 'string')
250+
return value;
251+
if (typeof value === 'object')
252+
return value.name;
253+
throw new TypeError(`
254+
Invalid value passed to MediaQuery._getQueryName().
255+
Expected a breakpoint name (String) or a breakpoint query (Object), got "${value}" (${typeof value})
256+
`);
257+
},
258+
178259
/**
179260
* Gets the current breakpoint name by testing every breakpoint and returning the last one to match (the biggest one).
180261
* @function
@@ -192,11 +273,7 @@ var MediaQuery = {
192273
}
193274
}
194275

195-
if (typeof matched === 'object') {
196-
return matched.name;
197-
} else {
198-
return matched;
199-
}
276+
return matched && this._getQueryName(matched);
200277
},
201278

202279
/**

0 commit comments

Comments
 (0)