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

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

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

✋

CSS is not the same anymore.

: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

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

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

What designers design What’s possible with CSS

Photo: Brad Frost, 2012

viewports.fyi

We are still static painting pretty pictures of websites.

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

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

“ 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/

CSS as a design “material”?

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

“ 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/

Declarative Design Photo by Stefan Nitzsche

Typography

Fluid Web Typography

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

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

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

modularscale.com

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

utopia.fyi

utopia.fyi

https://utopia.fyi/

Interpolation between two typographic scales by viewport width

sin(x)

1 y sin(x) 0 x ½π

1 y sin(x) 0 min x max

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

sin(x * pi / 2)

sin(x * pi / 2)

calc(100vw / 1vw)

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

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

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

atan2(100vw, 1px) ✅

tan(atan2(100vw, 1px))

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

@property Limited availability 85 85 Nightly 16.4

@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)); }

@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); }

@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); }

: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)); }

Color

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

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%)

CIE 1931

CIE 1931 sRGB

CIE 1931 P3 sRGB

oklch

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

: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); }

oklch.com

huetone.ardov.me

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

color-mix() Baseline 2023 111 111 113 16.2

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

Relative Colors Limited availability 119 119 126 16.4

Relative Colors Limited availability 119 119 126 127 16.4

Relative Colors Limited availability 119 119 126 127 128 16.4

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

—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);

sin(x)

—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);

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

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

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

Layout

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

CSS Grid

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

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

Example: CSS Grid @jensimmons youtube.com/layoutland

https://labs.jensimmons.com/

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

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

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

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

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

Subgrid

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

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

Container Queries

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

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

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

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

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

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

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

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

Container Queries (Size) Baseline 2023 106 106 100 16

Container Queries (Size) 90.92 %

f min-content max-content it-content

:has() Baseline 2023 105 105 121 15.4

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

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

Animation

linear()

Scroll-driven Animations

Viewtransitions

Anchor Positioning

😅

& Learn teach

Use CSS much earlier in the design process

Make CSS an essential part of the design process

Decide in the browser

Build Prototypes

Improve collaboration between design and development

Form interdisciplinary teams

Let the devs design with CSS

Let the designers write CSS

Let the designers write CSS

Design Engineering

Design Engineering Web

Web Design Engineering

Web Engineering Design

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