Skip to content

Commit 366fc2a

Browse files
authored
Cloud Cover and standardized Container padding (#1027)
1 parent e8ecf87 commit 366fc2a

22 files changed

+734
-13
lines changed

.changeset/cool-squids-allow.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@cloudfour/patterns': minor
3+
---
4+
5+
Add standard padding modifiers for container object

.changeset/purple-beers-rhyme.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@cloudfour/patterns': minor
3+
---
4+
5+
Add Cloud Cover component

package-lock.json

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
"npm-run-all": "4.1.5",
8686
"postcss-inline-svg": "4.1.0",
8787
"postcss-loader": "3.0.0",
88+
"postcss-media-minmax": "4.0.0",
8889
"prettier": "2.1.2",
8990
"raw-loader": "4.0.2",
9091
"remark-preset-lint-recommended": "4.0.1",

postcss.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ module.exports = {
33
require('postcss-inline-svg')({
44
paths: ['./src/assets'],
55
}),
6+
require('postcss-media-minmax')(),
67
],
78
};

src/assets/clouds/large.svg

Lines changed: 4 additions & 0 deletions
Loading

src/assets/clouds/medium.svg

Lines changed: 4 additions & 0 deletions
Loading

src/assets/clouds/small.svg

Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
@use "../../design-tokens/breakpoint.yml";
2+
@use "../../design-tokens/colors.yml";
3+
@use "../../mixins/ms";
4+
5+
/// We can't use `grid-gap` exclusively due to some containers only being present
6+
/// some of the time, so we re-use this value for `grid-gap` and for `margin`
7+
/// later on.
8+
///
9+
/// @type Number
10+
/// @access private
11+
12+
$_gap: ms.step(1);
13+
14+
/// The ideal cloud size is a factor of both the viewport width and height, and
15+
/// we size other elements based on factors of this value. This function returns
16+
/// that size as a `calc`, optionally with an `$amount` for partial or multiple
17+
/// instances of that value.
18+
///
19+
/// This really wouldn't be necessary if Sass would play nice with a variable
20+
/// declaration for `(14vh + 4vw)` (without `calc`), but it always tries to
21+
/// crunch those numbers together.
22+
///
23+
/// @param {Number} $amount [1] - Optional multiplier for default space.
24+
/// @param {Number} $vh [14vh] - Amount of horizontal space in the result.
25+
/// @param {Number} $vw [14vw] - Amount of vertical space in the result.
26+
/// @return {Calc}
27+
/// @access private
28+
29+
@function _cloud-space($amount: 1, $vh: 14vh, $vw: 4vw) {
30+
@if $amount == 1 {
31+
@return calc(#{$vh} + #{$vw});
32+
}
33+
34+
@return calc((#{$vh} + #{$vw}) * #{$amount});
35+
}
36+
37+
/**
38+
* The topmost containing element for this component. We keep most layout logic
39+
* off of this so it can be used with `o-container`.
40+
*
41+
* 1. This is only required to prevent Safari from showing subpixel artifacts
42+
* at the bottom of bottom-aligned imagery (specifically the clouds).
43+
* 2. Allows us to position clouds absolutely relative to this container.
44+
*/
45+
46+
.c-cloud-cover {
47+
overflow: hidden; /* 1 */
48+
position: relative; /* 2 */
49+
}
50+
51+
/**
52+
* The pseudo elements for background and foreground clouds.
53+
*
54+
* 1. Safari often renders subpixel artifacts on the bottom edge, causing a
55+
* visible line below the clouds. As long as the container has `overflow:
56+
* hidden` set, this should prevent that from being visible.
57+
*/
58+
59+
.c-cloud-cover::before,
60+
.c-cloud-cover::after {
61+
background-position: bottom right;
62+
background-repeat: no-repeat;
63+
bottom: -1px; /* 1 */
64+
content: '';
65+
height: _cloud-space();
66+
pointer-events: none;
67+
position: absolute;
68+
right: 0;
69+
width: 100%;
70+
71+
@media (width >= breakpoint.$m) {
72+
width: 50%;
73+
}
74+
}
75+
76+
/**
77+
* The background clouds. We adjust the colors and viewboxes here rather than
78+
* in the SVG to give us better control of the style and
79+
* composition in this context.
80+
*
81+
* 1. These sizes correspond to the cloud's proportion to the largest cloud.
82+
*/
83+
84+
.c-cloud-cover::before {
85+
background-image: svg-load(
86+
'clouds/medium.svg',
87+
fill=colors.$primary-brand-lighter,
88+
width= '480',
89+
height= '220',
90+
viewBox= '0 0 480 220'
91+
),
92+
svg-load(
93+
'clouds/small.svg',
94+
fill=colors.$primary-brand-light,
95+
width= '580',
96+
height= '140',
97+
viewBox= '0 0 580 140'
98+
);
99+
background-size: auto (220 / 300 * 100%), auto (140 / 300 * 100%); /* 1 */
100+
}
101+
102+
/**
103+
* The foreground cloud.
104+
*/
105+
106+
.c-cloud-cover::after {
107+
background-image: svg-load(
108+
'clouds/large.svg',
109+
fill=colors.$text-light-emphasis,
110+
width= '320',
111+
height= '300',
112+
viewBox= '0 0 320 300'
113+
);
114+
background-position: bottom right;
115+
background-size: auto 100%;
116+
z-index: 2;
117+
}
118+
119+
/**
120+
* This element is where the layout is defined. It's most likely the
121+
* `max-width` container (if present), which may already include horizontal
122+
* whitespace.
123+
*
124+
* 1. We use rows instead of padding/margin for whitespace to allow some scenes
125+
* to overlap the clouds.
126+
* 2. We want this content to cover the background clouds, but not the
127+
* foreground clouds.
128+
*/
129+
130+
.c-cloud-cover__inner {
131+
align-items: center;
132+
display: grid;
133+
grid-column-gap: $_gap;
134+
grid-template-areas:
135+
'.'
136+
'scene'
137+
'content'
138+
'extra'
139+
'.';
140+
grid-template-rows:
141+
_cloud-space(0.5)
142+
repeat(3, auto)
143+
_cloud-space(); /* 1 */
144+
position: relative; /* 2 */
145+
z-index: 1; /* 2 */
146+
147+
/**
148+
* 1. At larger sizes when the scene imagery occupies the rightmost column,
149+
* we establish rows that are half the height of the clouds to allow more
150+
* overlap.
151+
*/
152+
153+
@media (width >= breakpoint.$m) {
154+
grid-template-areas:
155+
'. .'
156+
'. scene'
157+
'content extra'
158+
'. .'
159+
'. .';
160+
grid-template-columns: repeat(2, 1fr);
161+
grid-template-rows:
162+
repeat(2, _cloud-space(0.5))
163+
auto
164+
repeat(2, _cloud-space(0.5)); /* 1 */
165+
}
166+
}
167+
168+
/**
169+
* For scenes that are meant to intersect with the horizon, we extend the
170+
* scene area to the bottom row. (We have to do things a bit differently at
171+
* larger sizes, which you'll see later.)
172+
*/
173+
174+
.c-cloud-cover--horizon-scene .c-cloud-cover__inner {
175+
@media (width < breakpoint.$m) {
176+
grid-template-areas:
177+
'.'
178+
'content'
179+
'extra'
180+
'scene'
181+
'scene';
182+
}
183+
}
184+
185+
/**
186+
* The content container.
187+
*/
188+
189+
.c-cloud-cover__content {
190+
grid-area: content;
191+
}
192+
193+
/**
194+
* The optional _extra_ content container, intended for things like forms or
195+
* other calls to action.
196+
*/
197+
198+
.c-cloud-cover__extra {
199+
grid-area: extra;
200+
201+
/**
202+
* Because we don't want lingering row gaps when there is no extra, we must
203+
* use margin to avoid this running up against adjacent content.
204+
*/
205+
206+
@media (width < breakpoint.$m) {
207+
margin-top: $_gap;
208+
}
209+
}
210+
211+
/**
212+
* The optional scene, where any visual objects in the sky will be displayed.
213+
*
214+
* 1. To avoid content jumps as images load, we'll be absolute-positioning the
215+
* visual objects within this element.
216+
* 2. Without this, a cell with only absolute-positioned elements may take up
217+
* zero space.
218+
*/
219+
220+
.c-cloud-cover__scene {
221+
grid-area: scene;
222+
position: relative; /* 1 */
223+
width: 100%; /* 2 */
224+
225+
/**
226+
* At smaller breakpoints, we size the scene so that it is always twice as
227+
* large as the clouds.
228+
*/
229+
230+
@media (width < breakpoint.$m) {
231+
height: _cloud-space(2);
232+
margin-bottom: $_gap;
233+
}
234+
235+
/**
236+
* At larger breakpoints, we allow more overlap between the clouds and imagery
237+
* and size based on available space.
238+
*/
239+
240+
@media (width >= breakpoint.$m) {
241+
grid-row-end: span 3;
242+
height: 100%;
243+
}
244+
}
245+
246+
/**
247+
* Scene adjustments for when the scene is intended to intersect with the
248+
* horizon.
249+
*/
250+
251+
.c-cloud-cover--horizon-scene .c-cloud-cover__scene {
252+
/**
253+
* At smaller sizes we increase the height to account for the additional
254+
* cloud overlap, and swap the edge of the gap (since the content order is
255+
* the reverse of the default).
256+
*/
257+
258+
@media (width < breakpoint.$m) {
259+
height: _cloud-space(3);
260+
margin-bottom: 0;
261+
margin-top: $_gap;
262+
}
263+
264+
/**
265+
* At larger sizes all we have to do is increase the row span. We can't rely
266+
* on areas alone to do this since the `scene` and `extra` areas overlap.
267+
*/
268+
269+
@media (width >= breakpoint.$m) {
270+
grid-row-end: span 4;
271+
}
272+
}
273+
274+
/**
275+
* The actual object within the scene, for example an `img` or `svg`.
276+
*
277+
* 1. Cover and fill the entire scene.
278+
* 2. Adjust and reposition the image within that container.
279+
*/
280+
281+
.c-cloud-cover__scene-object {
282+
height: 100%; /* 1 */
283+
left: 0; /* 1 */
284+
object-fit: contain; /* 2 */
285+
object-position: center; /* 2 */
286+
position: absolute; /* 1 */
287+
top: 0; /* 1 */
288+
width: 100%; /* 1 */
289+
290+
/**
291+
* At larger sizes, it looks a bit more balanced to start adding more space
292+
* to the right rather than on both sides.
293+
*/
294+
295+
@media (width >= breakpoint.$m) {
296+
object-position: left center;
297+
}
298+
}
299+
300+
/**
301+
* When the scene is intended to intersect with the horizon, the object must
302+
* be positioned along the bottom.
303+
*/
304+
305+
.c-cloud-cover--horizon-scene .c-cloud-cover__scene-object {
306+
object-position: center bottom;
307+
308+
@media (width >= breakpoint.$m) {
309+
object-position: left bottom;
310+
}
311+
}

0 commit comments

Comments
 (0)