Web Design Engineering With the New CSS

A presentation at CSS Day in June 2024 in Amsterdam, Netherlands by Matthias Ott

Slide 1

Slide 1

Web Design Engineering With The New CSS →Matthias Ott CSS Day 2024

Slide 2

Slide 2

👋 Matthias Ott User Experience Designer Web Design Engineer @matthiasott@mastodon.social https://matthiasott.com

Slide 3

Slide 3

ow n e t i s . b e w yo u r

Slide 4

Slide 4

Slide 5

Slide 5

Slide 6

Slide 6

Slide 7

Slide 7

CSS is not the same anymore.

Slide 8

Slide 8

Slide 9

Slide 9

:has() Container Queries min(), max(), clamp() Custom Properties Intrinsic Sizing Keywords Trigonometric Functions Subgrid ViewTransitions Blend Modes Logical Properties CSS Filter Effects Popover API aspect-ratio :is() and :where() @property conic-gradient() Animation-start linear() Easing Function CSS Motion Path Anchor Positioning color() color-mix() Scroll Snap CSS Nesting light-dark() overscroll-behavior touch-action scroll-behavior scrollbar-gutter Variable Fonts font-palette text-wrap: balance

Slide 10

Slide 10

CSS is now the most powerful design tool for the Web.

Slide 11

Slide 11

https://vasilis.nl/nerd/our-web-design-tools-areholding-us-back/ https://www.oddbird.net/2022/11/11/platform-tools/

Slide 12

Slide 12

What designers design What’s possible with CSS

Slide 13

Slide 13

Photo: Brad Frost, 2012

Slide 14

Slide 14

Slide 15

Slide 15

viewports.fyi

Slide 16

Slide 16

Slide 17

Slide 17

Slide 18

Slide 18

Slide 19

Slide 19

We are still static painting pretty pictures of websites.

Slide 20

Slide 20

STILL PAINTING PRETTY PICTURES OF WEBSITES Soon (?) on webbed-briefs.teemill.com

Slide 21

Slide 21

If we are not using the platform as our design material, we are breaking the feedback loop.

Slide 22

Slide 22

“ What would happen if we stopped treating the Web like a blank canvas to paint on, and started treating it like a material to build with?” Frank Chimero, “The Web’s Grain” https://frankchimero.com/blog/2015/the-webs-grain/

Slide 23

Slide 23

CSS as a design “material”?

Slide 24

Slide 24

Intrinsic Web Design “Everything You Know About Web Design Just Changed” Jen Simmons, 2018 Photo by Jeffrey Zeldman

Slide 25

Slide 25

“ If you use style sheets properly, to suggest the appearance of a page, not to control the appearance of a page, and you don’t rely on your style sheet to convey information, then your pages will work fine in any browser, past or future.” John Allsopp, “A Dao of Web Design” https://alistapart.com/article/dao/

Slide 26

Slide 26

Declarative Design Photo by Stefan Nitzsche

Slide 27

Slide 27

Typography

Slide 28

Slide 28

Fluid Web Typography

Slide 29

Slide 29

Slide 30

Slide 30

font-size: clamp(1rem, 0.6522rem + 1.7391vw, 2rem); min preferred max

Slide 31

Slide 31

clamp() 96.3 % https://caniuse.com/css-math-functions

Slide 32

Slide 32

a a a a a a a a a a a a aa aaaaa 6 7 8 9 10 11 12 14 16 18 20 22 24 28 32 36 40 44 48 aaaaa 56 64 72 80 88 a 96

Slide 33

Slide 33

modularscale.com

Slide 34

Slide 34

Interpolation between two typographic scales by viewport width Source: Utopia.fyi

Slide 35

Slide 35

utopia.fyi

Slide 36

Slide 36

utopia.fyi

Slide 37

Slide 37

https://utopia.fyi/

Slide 38

Slide 38

Interpolation between two typographic scales by viewport width

Slide 39

Slide 39

sin(x)

Slide 40

Slide 40

1 y sin(x) 0 x ½π

Slide 41

Slide 41

1 y sin(x) 0 min x max

Slide 42

Slide 42

sin(), cos(), tan(), asin(), acos(), atan(), and atan2() Baseline 2023 111 111 108 15.4

Slide 43

Slide 43

sin(x * pi / 2)

Slide 44

Slide 44

sin(x * pi / 2)

Slide 45

Slide 45

calc(100vw / 1vw)

Slide 46

Slide 46

calc(100vw / 1vw) X X X X

Slide 47

Slide 47

Slide 48

Slide 48

https://dev.to/janeori/css-type-casting-to-numeric-tanatan2-scalars-582j

Slide 49

Slide 49

(x,y) θ=atan2(y,x) atan2()

Slide 50

Slide 50

atan2(100vw, 1px) ✅

Slide 51

Slide 51

tan(atan2(100vw, 1px))

Slide 52

Slide 52

:root { /* Current viewport width in pixels without a unit */ —currentWidth: tan(atan2(var(100vw), 1px)); }

Slide 53

Slide 53

@property Limited availability 85 85 Nightly 16.4

Slide 54

Slide 54

@property —100vw { syntax: “<length>”; initial-value: 0px; inherits: false; } :root { —100vw: 100vw; /* Current viewport width in pixels without a unit */ —currentWidth: tan(atan2(var(—100vw), 1px)); }

Slide 55

Slide 55

@property —100vw { syntax: “<length>”; initial-value: 0px; inherits: false; } :root { —minWidth: 320; —maxWidth: 1600; —100vw: 100vw; /* Current viewport width in pixels without a unit / —currentWidth: tan(atan2(var(—100vw), 1px)); / This normalizes the value between 0 and 1 */ —x: clamp(0, calc((var(—currentWidth) - var(—minWidth)) / (var(—maxWidth) - var(—minWidth))), 1); }

Slide 56

Slide 56

@property —100vw { syntax: “<length>”; initial-value: 0px; inherits: false; } :root { —minWidth: 320; —maxWidth: 1600; —100vw: 100vw; /* Current viewport width in pixels without a unit / —currentWidth: tan(atan2(var(—100vw), 1px)); / This normalizes the value between 0 and 1 / —x: clamp(0, calc((var(—currentWidth) - var(—minWidth)) / (var(—maxWidth) - var(—minWidth))), 1); / Now we can put our x into the sine function */ —easeOutSine: sin(var(—x) * pi / 2); }

Slide 57

Slide 57

:root { —minWidth: 320; —maxWidth: 1600; —100vw: 100vw; —font-size-min: 1rem; —font-size-max: 1.5rem; /* Current viewport width in pixels without a unit / —currentWidth: tan(atan2(var(—100vw), 1px)); / This normalizes the value between 0 and 1 / —x: clamp(0, calc((var(—currentWidth) - var(—minWidth)) / (var(—maxWidth) - var(—minWidth))), 1); / Now we can put our x into the sine function / —easeOutSine: sin(var(—x) * pi) / 2); / And calculate our font-size */ —fluid-font-size: clamp(var(—font-size-min), var(—font-size-min) + ( var(—easeOutSine) * (var(—font-size-max) - var(—font-size-min)) ), var(—font-size-max)); }

Slide 58

Slide 58

Slide 59

Slide 59

Color

Slide 60

Slide 60

fuchsia purple blue navy teal lime green aqua yellow olive black red maroon silver gray white

Slide 61

Slide 61

Slide 62

Slide 62

rebeccapurple #E646AE rgb(230 70 174) rgba(0.6 153 153 / 0.9) hsl(233.16deg 100% 69.2%) hwb(35.05deg 36.4% 0%)

Slide 63

Slide 63

Slide 64

Slide 64

CIE 1931

Slide 65

Slide 65

CIE 1931 sRGB

Slide 66

Slide 66

CIE 1931 P3 sRGB

Slide 67

Slide 67

Slide 68

Slide 68

oklch

Slide 69

Slide 69

oklch(70% 0.325 341.79) oklch(70% 0.325 341.79 / 50%)

Slide 70

Slide 70

:root { —pool-water: rgb(0 128 250); } @supports (color: oklch(61% 0.206 255)) { :root { —pool-water: oklch(61% 0.206 255); } } .pool { —background-color: var(—pool-water); }

Slide 71

Slide 71

Slide 72

Slide 72

Slide 73

Slide 73

oklch.com

Slide 74

Slide 74

huetone.ardov.me

Slide 75

Slide 75

atmos.style https://huetone.ardov.me/

Slide 76

Slide 76

color-mix() Baseline 2023 111 111 113 16.2

Slide 77

Slide 77

—indigo: oklch(56.6% 0.27 274); —light-grey: oklch(75% 0 274); —light-indigo: color-mix(in oklch, var(—indigo), var(—light-grey));

Slide 78

Slide 78

Relative Colors Limited availability 119 119 126 16.4

Slide 79

Slide 79

Relative Colors Limited availability 119 119 126 127 16.4

Slide 80

Slide 80

Relative Colors Limited availability 119 119 126 127 128 16.4

Slide 81

Slide 81

oklch(from var(—indigo) l c h); oklch(from var(—indigo) l c h / 50%);

Slide 82

Slide 82

—indigo: oklch(56.6% 0.27 274); —indigo-10: —indigo-20: —indigo-30: —indigo-40: —indigo-50: —indigo-60: —indigo-70: —indigo-80: —indigo-90: —indigo-100: oklch(from oklch(from oklch(from oklch(from oklch(from oklch(from oklch(from oklch(from oklch(from oklch(from var(—indigo) var(—indigo) var(—indigo) var(—indigo) var(—indigo) var(—indigo) var(—indigo) var(—indigo) var(—indigo) var(—indigo) 10% c h); 20% c h); 30% c h); 40% c h); 50% c h); 60% c h); 70% c h); 80% c h); 90% c h); 100% c h);

Slide 83

Slide 83

Slide 84

Slide 84

sin(x)

Slide 85

Slide 85

—indigo: oklch(56.6% 0.27 274); —c-base: 0.05; —indigo-10: —indigo-20: —indigo-30: —indigo-40: —indigo-50: —indigo-60: —indigo-70: —indigo-80: —indigo-90: —indigo-100: oklch(from oklch(from oklch(from oklch(from oklch(from oklch(from oklch(from oklch(from oklch(from oklch(from var(—indigo) var(—indigo) var(—indigo) var(—indigo) var(—indigo) var(—indigo) var(—indigo) var(—indigo) var(—indigo) var(—indigo) 10% 20% 30% 40% 50% 60% 70% 80% 90% 100% calc(var(—c-base) calc(var(—c-base) calc(var(—c-base) calc(var(—c-base) calc(var(—c-base) calc(var(—c-base) calc(var(—c-base) calc(var(—c-base) calc(var(—c-base) calc(var(—c-base)

(sin(0.09 (sin(0.18 (sin(0.27 (sin(0.36 (sin(0.45 (sin(0.54 (sin(0.63 (sin(0.72 (sin(0.81 (sin(0.90


pi) pi) pi) pi) pi) pi) pi) pi) pi) pi)


c)) c)) c)) c)) c)) c)) c)) c)) c)) c)) h); h); h); h); h); h); h); h); h); h);

Slide 86

Slide 86

Slide 87

Slide 87

https://lea.verou.me/blog/2024/contrast-color/

Slide 88

Slide 88

https://ericportis.com/posts/2024/okay-color-spaces/

Slide 89

Slide 89

https://ericportis.com/posts/2024/okay-color-spaces/

Slide 90

Slide 90

Layout

Slide 91

Slide 91

Tables with spacer GIFs Writing modes Locigal properties Transforms Alignment :has() Floats Flexbox Multi-column layout Aspect-ratio min(), max(), and clamp() Custom properties New sizing values CSS Grid Object-fit Subgrid Clip-path Cascade layers Container queries

Slide 92

Slide 92

CSS Grid

Slide 93

Slide 93

Slide 94

Slide 94

grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));

Slide 95

Slide 95

grid-template-columns: 100px 1fr 1fr minmax(40ch, 65ch) 1fr;

Slide 96

Slide 96

Example: CSS Grid @jensimmons youtube.com/layoutland

Slide 97

Slide 97

https://labs.jensimmons.com/

Slide 98

Slide 98

https://labs.jensimmons.com/ Example: CSS Grid

Slide 99

Slide 99

https://codepen.io/matthiasott/pen/oNyqMgp

Slide 100

Slide 100

fl Flexbox and grid adoption by year 2019 2020 2021 2022 100 74 % 75 50 12 % 25 0 exbox grid Source: Web Almanac 2022

Slide 101

Slide 101

CSS Grid 97.94 % https://caniuse.com/css-grid

Slide 102

Slide 102

The majority of designers still has no idea of what’s possible with CSS Grid.

Slide 103

Slide 103

Subgrid

Slide 104

Slide 104

https://codepen.io/matthiasott/pen/JjqNPEN

Slide 105

Slide 105

Subgrid 88.29 % https://caniuse.com/css-subgrid

Slide 106

Slide 106

Container Queries

Slide 107

Slide 107

https://codepen.io/matthiasott/pen/pomNgKJ

Slide 108

Slide 108

.main { container-type: inline-size; }

Slide 109

Slide 109

.main { container-type: inline-size; } .component { color: red; } @container (min-width: 40em) { .component { color: blue; } }

Slide 110

Slide 110

.main { container-type: inline-size; container-name: main; } .component { color: red; } @container (min-width: 40em) { .component { color: blue; } }

Slide 111

Slide 111

.main { container-type: inline-size; container-name: main; } .component { color: red; } @container main (min-width: 40em) { .component { color: blue; } }

Slide 112

Slide 112

.main { container: main / inline-size; } .component { color: red; } @container main (min-width: 40em) { .component { color: blue; } }

Slide 113

Slide 113

.main { container: main / inline-size; } .component { color: red; @container main (min-width: 40em) { color: blue; } }

Slide 114

Slide 114

Unit Relative to cqb 1% of a query container’s block size cqh 1% of a query container’s height cqi 1% of a query container’s inline size cqmax The larger value of cqi or cqb cqmin The smaller value of cqi or cqb cqw 1% of a query container’s width

Slide 115

Slide 115

Slide 116

Slide 116

Container Queries (Size) Baseline 2023 106 106 100 16

Slide 117

Slide 117

Container Queries (Size) 90.92 %

Slide 118

Slide 118

f min-content max-content it-content

Slide 119

Slide 119

:has() Baseline 2023 105 105 121 15.4

Slide 120

Slide 120

.card { —_columns: 1fr; display: grid; grid-template-columns: var(—_cols, 1fr); } .card:has(figure) { —_columns: minmax(240px, 1fr) 1fr; }

Slide 121

Slide 121

mask Baseline 2023 120 120 53 15.4 https://codepen.io/matthiasott/pen/yLwGoQv

Slide 122

Slide 122

Animation

Slide 123

Slide 123

linear()

Slide 124

Slide 124

Scroll-driven Animations

Slide 125

Slide 125

Viewtransitions

Slide 126

Slide 126

Anchor Positioning

Slide 127

Slide 127

😅

Slide 128

Slide 128

& Learn teach

Slide 129

Slide 129

Use CSS much earlier in the design process

Slide 130

Slide 130

Make CSS an essential part of the design process

Slide 131

Slide 131

Decide in the browser

Slide 132

Slide 132

Build Prototypes

Slide 133

Slide 133

Improve collaboration between design and development

Slide 134

Slide 134

Slide 135

Slide 135

Form interdisciplinary teams

Slide 136

Slide 136

Let the devs design with CSS

Slide 137

Slide 137

Let the designers write CSS

Slide 138

Slide 138

Let the designers write CSS

Slide 139

Slide 139

Design Engineering

Slide 140

Slide 140

Design Engineering Web

Slide 141

Slide 141

Web Design Engineering

Slide 142

Slide 142

Web Engineering Design

Slide 143

Slide 143

Slide 144

Slide 144

Thank you! 💚 Slides: https://noti.st/matthiasott/JrA84R 👉 ownyourweb.site 👈 Typefaces: NaN Tresor by Christoph Koeberlin, NaN Tragedy by Jean-Baptiste Morizot, Input Mono by David Jonathan Ross