Skip to content

Commit 518c2fa

Browse files
feat(containers): Added container queries (#620)
1 parent 56c4462 commit 518c2fa

File tree

12 files changed

+214
-10
lines changed

12 files changed

+214
-10
lines changed

.changeset/tall-lions-give.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"atomizer": minor
3+
---
4+
5+
feat: Added container queries support

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Before you can contribute to the codebase, you will need to fork the repo. The f
2626
cd atomizer
2727
```
2828
3. Install dependencies by running `npm install` This repository is a [monorepo] that leverages npm's [workspaces] to build and test packages together.
29-
4. Verify you've got everything set up for local development by running `npm test`
29+
4. Verify you've got everything set up for local development by running `npm run build` then `npm test`
3030

3131
## Development
3232

app/assets/css/custom.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ li.selected a {
153153
}
154154

155155
.noteBox strong {
156-
color: #000000;
156+
font-weight: bold;
157157
}
158158

159159
.important {

atomizer.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ module.exports = {
44
sm: '@media screen and (min-width:700px)',
55
md: '@media screen and (min-width:999px)',
66
lg: '@media screen and (min-width:1200px)',
7+
contmw300: '@container width300 (max-width: 300px)',
78
},
89
content: ['app/components/', 'app/assets/js', 'docs/'],
910
custom: {
@@ -36,5 +37,6 @@ module.exports = {
3637
twoColEvenGrid: 'repeat(2, minmax(20px, 1fr))',
3738
twoColNamedGrid:
3839
'[#{colMain}-start] repeat(9,minmax(0,1fr)) [#{colMain}-end #{colAside}-start] repeat(3,minmax(0,1fr)) [#{colAside}-end]',
40+
width300: 'width300',
3941
},
4042
};

docs/breakpoints.md

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ section: docs
55
title: Breakpoints
66
---
77

8-
You can define your breakpoints as media queries in the config object and then apply those breakpoints to your Atomizer classes through <a href="{% link guides/syntax.md %}#breakpoint_identifier">the breakpoint suffix</a> or automatic breakpoints.
8+
You can define your breakpoints as media or container queries in the config object and then apply those breakpoints to your Atomizer classes through <a href="{% link guides/syntax.md %}#breakpoint_identifier">the breakpoint suffix</a> or automatic breakpoints.
99

1010
## Setting up Breakpoints
1111

12-
Pick the breakpoint names and media queries you want, for example:
12+
Pick the breakpoint names and whichever media or container queries you want, for example:
1313

1414
```js
1515
breakPoints: {
@@ -21,7 +21,7 @@ breakPoints: {
2121

2222
Breakpoints may be named anything you want, as long as the characters are valid for use in classnames.
2323

24-
## Usage
24+
## Media Queries
2525

2626
There are two ways to make use of breakpoints in your Atomizer classes: explicitly and automatically.
2727

@@ -72,7 +72,7 @@ In this example, the class `P(logo)` will style a box with a `padding` of `10px`
7272

7373
Likewise, any class that uses the variable `gutter` will receive different values depending on the currently active breakpoint.
7474

75-
## Examples
75+
### Examples
7676

7777
When using explicit breakpoints, use multiple classes to have styles applied in the context of various breakpoints, for example:
7878

@@ -97,3 +97,85 @@ When using explicit breakpoints, use multiple classes to have styles applied in
9797
<div class="Bxz(bb) W(50%)--sm W(25%)--lg P(20px) Bgc(--color-blue-2)">3</div>
9898
<div class="Bxz(bb) W(50%)--sm W(25%)--lg P(20px) Bgc(--color-blue-1)">4</div>
9999
</div>
100+
101+
## Container Queries
102+
103+
We have added support for container queries using the same syntax as media queries, since you are able to define what the rule is, just ensure the names are different to the media query rules.
104+
105+
```js
106+
breakPoints: {
107+
sm: '@media screen and (min-width: 700px)',
108+
mw300: '@container (max-width: 300px)',
109+
},
110+
```
111+
112+
Same logic as above - append `--<breakpoint name>` to any Atomizer class to associate that styling with the breakpoint of your choice. For example, `Fz(1rem)--mw300` will create the following rule in the related container query:
113+
114+
```css
115+
@container (max-width: 300px) {
116+
#atomic .Fz(1rem)--mw300 {
117+
font-size: 1rem;
118+
}
119+
}
120+
```
121+
122+
### Named containers
123+
124+
It requires an additional config step if you are using [named containers](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries#naming_containment_contexts) which is better suited to atomic anyway.
125+
126+
<p class="noteBox info">the custom value of `width300` matches the named container</p>
127+
128+
```js
129+
breakPoints: {
130+
contmw300: '@container width300 (max-width: 300px)',
131+
},
132+
custom: {
133+
width300: 'width300',
134+
},
135+
```
136+
137+
You can define a container and its type by using `ContType()` & `ContName()`, using the named container above, your markup would look something like this:
138+
139+
```html
140+
<div class="ContType(is) ContName(width300)">
141+
<h2 class="Fz(2rem) Fz(1rem)--contmw300">Heading</h2>
142+
```
143+
144+
This will output the following CSS
145+
146+
```css
147+
@container width300 (max-width: 300px) {
148+
.Fz(1rem)--contmw300 {
149+
font-size: 1rem;
150+
}
151+
}
152+
```
153+
154+
This example shows how you could change layout and properties in a named container.
155+
156+
```html
157+
<div class="ContType(is) ContName(width300)">
158+
<div class="D(f) Fxd(r) Fxd(c)--contmw300 Gp(20px)">
159+
<div class="W(75%) W(100%)--contmw300">
160+
<h1 class="Fz(2.5rem) Fz(1.5rem)--contmw300 ">Resize me</h1>
161+
...
162+
</div>
163+
</div>
164+
</div>
165+
```
166+
167+
- Below 300px on the container DIV the boxes are displayed on top of each other (`Fxd(c)--contmw300`)
168+
- Below 300px on the container DIV the headline size will be (`Fz(1.5rem)`)
169+
170+
<p class="noteBox info">The example below is resizable <strong>Give it a try, resize by dragging the bottom right corner of the rounded box</strong></p>
171+
172+
<div class="ContType(is) ContName(width300) W(50%) Mx(a) P(10px) Bdc(--color-blue-1) Bdw(1px) Bds(s) Bdrs(5px) Rsz(h) Ov(a)">
173+
<div class="D(f) Fxd(r) Fxd(c)--contmw300 Gp(20px)">
174+
<div class="W(25%) W(100%)--contmw300 Mih(100%) H(40px)--contmw300 Bgc(--color-blue-4)"></div>
175+
<div class="D(f) Gp(20px) Fxd(c) W(75%) W(100%)--contmw300">
176+
<h1 class="C(--color-blue-1) Fz(2.5rem) Fz(1.5rem)--contmw300 M(0)">Resize me</h1>
177+
<div class="P(10px) Bgc(--color-blue-1)"></div>
178+
<div class="P(10px) Bgc(--color-blue-1)"></div>
179+
</div>
180+
</div>
181+
</div>

examples/atomizer.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module.exports = {
1616
padding: '#{standardPadding} 5px #{standardPadding} 20px', // custom value substitution is supported via #{} syntax
1717
threeColGrid: 'repeat(3, minmax(20px, 1fr))',
1818
twoCol: '1 / span 2',
19+
width300: 'width300', // value is the name for a named container
1920
},
2021
// breakpoints define media queries and is used to contain the style of a class
2122
// only when that media query is active.
@@ -26,6 +27,7 @@ module.exports = {
2627
sm: '@media(min-width:500px)', // breakpoint 1 (see classNames below)
2728
md: '@media(min-width:900px)', // breakpoint 2
2829
lg: '@media(min-width:1200px)', // breakpoint 3
30+
contmw300: '@container width300 (max-width: 300px)', // named container matches custom name above
2931
},
3032
// this is the list of atomic class names your project uses.
3133
// you don't have to explictly declare them like this since atomizer can parse

examples/breakpoints.html

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<!DOCTYPE html>
2+
<html lang="en-US">
3+
<head>
4+
<meta charset="utf-8" />
5+
6+
<title>Atomizer: Breakpoints</title>
7+
<style>
8+
:root {
9+
--color-blue-1: #0280ae;
10+
--color-blue-2: #0280aee6;
11+
--color-blue-3: #0280aeb3;
12+
--color-blue-4: #0280ae80;
13+
}
14+
</style>
15+
<link rel="stylesheet" href="css/base.css" />
16+
<link rel="stylesheet" href="css/atomic.css" />
17+
</head>
18+
<body>
19+
<main>
20+
<h1>Breakpoints</h1>
21+
22+
<p>This examples shows different ways to use breakpoints in atomic.</p>
23+
24+
<h2>Media Queries</h2>
25+
<p>Below 700px, the boxes are displayed on top of each other (D(f)--sm on applies over this width)</p>
26+
<p>Above 999px, the boxes are displayed on 2 rows, 2 by 2 (W(50%)--sm)</p>
27+
<p>Above 1200px, the boxes are displayed side-by-side, on a single row (W(25%)--lg)</p>
28+
<div class="D(f)--sm Fxw(w)">
29+
<div class="W(50%)--sm W(25%)--lg P(20px) Bgc(--color-blue-1)">1</div>
30+
<div class="W(50%)--sm W(25%)--lg P(20px) Bgc(--color-blue-2)">2</div>
31+
<div class="W(50%)--sm W(25%)--lg P(20px) Bgc(--color-blue-3)">3</div>
32+
<div class="W(50%)--sm W(25%)--lg P(20px) Bgc(--color-blue-4)">4</div>
33+
</div>
34+
<h2>Container Queries</h2>
35+
<p>Below 300px on the container DIV the boxes are displayed on top of each other Fxd(c)--contmw300</p>
36+
<p>Below 300px on the container DIV the headline size will be 1.5rem</p>
37+
<p>note: you can resize this container by dragging the corner</p>
38+
<div
39+
class="ContType(is) ContName(width300) W(50%) Mx(a) P(10px) Bdc(--color-blue-1) Bdw(1px) Bds(s) Bdrs(5px) Rsz(h) Ov(a)"
40+
>
41+
<div class="D(f) Fxd(r) Fxd(c)--contmw300 Gp(20px)">
42+
<div class="W(25%) W(100%)--contmw300 Mih(100%) H(40px)--contmw300 Bgc(--color-blue-4)"></div>
43+
<div class="D(f) Gp(20px) Fxd(c) W(75%) W(100%)--contmw300">
44+
<h1 class="C(--color-blue-1) Fz(3rem) Fz(1.5rem)--contmw300 M(0)">Resize me</h1>
45+
<div class="P(10px) Bgc(--color-blue-1)"></div>
46+
<div class="P(10px) Bgc(--color-blue-1)"></div>
47+
</div>
48+
</div>
49+
</div>
50+
</main>
51+
52+
<!-- this is just to reload the page if you make any changes to the html -->
53+
<script src="//localhost:35729/livereload.js"></script>
54+
</body>
55+
</html>

examples/index.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ <h1>Atomizer Examples</h1>
2626
</li>
2727
<li><a href="grid.html">Css Grid</a> - How to use grid for layout in Atomizer</li>
2828
<li><a href="layout.html">Layout</a> - A useful page to see different ways to markup layouts.</li>
29+
<li>
30+
<a href="breakpoints.html">Breakpoints</a> - How to use breakpoints (Media Queries and Container
31+
queries) in Atomizer
32+
</li>
2933
</ul>
3034
</main>
3135

packages/atomizer/src/atomizer.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -509,8 +509,8 @@ Atomizer.prototype.getCss = function (config, options) {
509509
/* istanbul ignore else */
510510
if (_.size(config.breakPoints) > 0) {
511511
for (const bp in config.breakPoints) {
512-
if (!/^@media/.test(config.breakPoints[bp])) {
513-
throw new Error(`Breakpoint \`${bp}\` must start with \`@media\`.`);
512+
if (!/^@media|@container/.test(config.breakPoints[bp])) {
513+
throw new Error(`Breakpoint \`${bp}\` must start with \`@media\` or \`@container\`.`);
514514
} else {
515515
// eslint-disable-next-line prefer-destructuring
516516
breakPoints = config.breakPoints;

packages/atomizer/src/lib/jss.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ JSS.flattenSelectors = function (newJss /*:Jss*/, jss /*:Jss*/, parent /*:string
2222
// prop is not a prop
2323
if (typeof value === 'object') {
2424
// prop is a media query
25-
if (/^@media|@supports/.test(prop)) {
25+
if (/^@media|@supports|@container/.test(prop)) {
2626
if (!newJss[prop]) {
2727
newJss[prop] = {};
2828
}
@@ -54,7 +54,7 @@ JSS.extractProperties = function (extracted /*:Extracted*/, jss /*:JssFlat*/, bl
5454
for (const selector in jss) {
5555
props = jss[selector];
5656
// if selector is a media query
57-
if (/^@media|@supports/.test(selector)) {
57+
if (/^@media|@supports|@container/.test(selector)) {
5858
JSS.extractProperties(extracted, props, selector);
5959
} else {
6060
for (prop in props) {

0 commit comments

Comments
 (0)