# data[].attributes.blurb.html
Today’s Web is more complex, unpredictable, dynamic, and powerful than ever. Yet, 25 years after “A Dao of Web Design” we still approach building for the Web with a mindset of control, using linear workflows and static design tools that often don’t reflect the Web’s true nature and potential. The canvas we work on has transformed, the materials we use have changed. Together, we’ll explore how we can use web design engineering to start painting with the Web and create designs that are resilient, accessible, and true to the Web’s greatest strength: its inherent flexibility.

# data[].attributes.slidedeck.data[].slides[].desc.html
Painting Painting With With the theWeb Web →Matthias Ott TYPO3 Developer Days Karlsruhe 2026

# data[].attributes.slidedeck.data[].slides[].desc.html
Matthias Ott Web Design Engineer User Experience Designer Teacher for Interface Prototyping, Muthesius University of Fine Arts and Design @matthiasott@mastodon.social https://matthiasott.com

# data[].attributes.slidedeck.data[].slides[].desc.html
OWN YOUR WEB -> ownyourweb.site

# data[].attributes.slidedeck.data[].slides[].desc.html
The ultimate creative process. A constant conversation.

# data[].attributes.slidedeck.data[].slides[].desc.html
The Canvas

# data[].attributes.slidedeck.data[].slides[].desc.html
Photo: Brad Frost, 2012

# data[].attributes.slidedeck.data[].slides[].desc.html
viewports.fyi

# data[].attributes.slidedeck.data[].slides[].desc.html
https://alistapart.com/article/responsive-web-design/

# data[].attributes.slidedeck.data[].slides[].desc.html
We are still painting static pictures of websites

# data[].attributes.slidedeck.data[].slides[].desc.html
We are still painting static pictures of components

# data[].attributes.slidedeck.data[].slides[].desc.html
The Material

# data[].attributes.slidedeck.data[].slides[].desc.html
We have a broken relationship with the material

# data[].attributes.slidedeck.data[].slides[].desc.html
We are breaking the feedback loop

# data[].attributes.slidedeck.data[].slides[].desc.html
: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

# data[].attributes.slidedeck.data[].slides[].desc.html
CSS is now CSS is now the most powerful design tool for the Web.

# data[].attributes.slidedeck.data[].slides[].desc.html
What designers design What’s possible with the Web platform today

# data[].attributes.slidedeck.data[].slides[].desc.html
What designers design What’s possible with the Web platform today

# data[].attributes.slidedeck.data[].slides[].desc.html
“ 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/

# data[].attributes.slidedeck.data[].slides[].desc.html
The Web as a design material?

# data[].attributes.slidedeck.data[].slides[].desc.html
Tim Berners-Lee

# data[].attributes.slidedeck.data[].slides[].desc.html
TBL’s room at CERN

# data[].attributes.slidedeck.data[].slides[].desc.html
Tim Berners-Lee We should work toward a universal linked information system, in which generality and portability are more important than fancy graphics techniques and complex extra facilities. Information Management: A Proposal, 1989

# data[].attributes.slidedeck.data[].slides[].desc.html
Tim Berners-Lee

# data[].attributes.slidedeck.data[].slides[].desc.html
Tim Berners-Lee Håkon Wium Lie

# data[].attributes.slidedeck.data[].slides[].desc.html
https://www.w3.org/People/howcome/p/cascade.html

# data[].attributes.slidedeck.data[].slides[].desc.html
“Negotiating between the needs and wishes of readers and authors was one of the main ambitions of CSS. If successful, authors would get their fair share of influence over the presentation and would not feel compelled to use presentational HTML and other tricks. Readers, on the other hand, would be served documents in a form in which they could choose between accepting the author’s suggested presentation or specify their own.” Håkon Wium Lie Cascading Style Sheets (PhD Thesis) https://www.wiumlie.no/2006/phd/

# data[].attributes.slidedeck.data[].slides[].desc.html
h1.font.size = 24pt 100%

# data[].attributes.slidedeck.data[].slides[].desc.html
24pt 100%

# data[].attributes.slidedeck.data[].slides[].desc.html
User Author Font o——-x———————o Color o-x—————————o Margin o——————-x———o Volume o————-x—————o 64% 90% 37% 50%

# data[].attributes.slidedeck.data[].slides[].desc.html
Author control becomes shared author/user influence

# data[].attributes.slidedeck.data[].slides[].desc.html
The browser The user Web authors

# data[].attributes.slidedeck.data[].slides[].desc.html
“ 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/

# data[].attributes.slidedeck.data[].slides[].desc.html
Declarative Design Jeremy Keith Photo by Stefan Nitzsche

# data[].attributes.slidedeck.data[].slides[].desc.html
ARIA javascript() .css <html>

# data[].attributes.slidedeck.data[].slides[].desc.html
Typography

# data[].attributes.slidedeck.data[].slides[].desc.html
font-family: Tausend, Helvetica, Arial, sans-serif;

# data[].attributes.slidedeck.data[].slides[].desc.html
Fluid Web Typography

# data[].attributes.slidedeck.data[].slides[].desc.html
font-size: clamp(1rem, 0.6522rem + 1.7391vw, 2rem); min preferred max

# data[].attributes.slidedeck.data[].slides[].desc.html
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

# data[].attributes.slidedeck.data[].slides[].desc.html
Octave 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 ×2 ×2 36 40 44 48 ×2 aaaaa 56 64 72 80 88 a 96

# data[].attributes.slidedeck.data[].slides[].desc.html
Perfect Fifth 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 × 1.5 × 1.5 × 1.5 × 1.5 36 40 44 × 1.5 48 aaaa 54 64 72 × 1.5 81 aa 88 96

# data[].attributes.slidedeck.data[].slides[].desc.html
Interpolation between two typographic scales by viewport width Source: Utopia.fyi

# data[].attributes.slidedeck.data[].slides[].desc.html
utopia.fyi

# data[].attributes.slidedeck.data[].slides[].desc.html
utopia.fyi

# data[].attributes.slidedeck.data[].slides[].desc.html
Interpolation between two typographic scales by viewport width

# data[].attributes.slidedeck.data[].slides[].desc.html
sin(x)

# data[].attributes.slidedeck.data[].slides[].desc.html
1 sin(x) 0 min max

# data[].attributes.slidedeck.data[].slides[].desc.html
sin(), cos(), tan(), asin(), acos(), atan(), and atan2() Baseline 2023 111 111 108 15.4

# data[].attributes.slidedeck.data[].slides[].desc.html
: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)); }

# data[].attributes.slidedeck.data[].slides[].desc.html
Painting always has reality Portrait Painting always has reality Landscape

# data[].attributes.slidedeck.data[].slides[].desc.html
Painting always has reality vw vh sqrt(100vw * 100vh)

# data[].attributes.slidedeck.data[].slides[].desc.html
Painting always has reality vw vh

# data[].attributes.slidedeck.data[].slides[].desc.html
Color

# data[].attributes.slidedeck.data[].slides[].desc.html
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%)

# data[].attributes.slidedeck.data[].slides[].desc.html
CIE 1931

# data[].attributes.slidedeck.data[].slides[].desc.html
CIE 1931 sRGB

# data[].attributes.slidedeck.data[].slides[].desc.html
CIE 1931 P3 sRGB

# data[].attributes.slidedeck.data[].slides[].desc.html
oklch

# data[].attributes.slidedeck.data[].slides[].desc.html
oklch(0.7 0.3357 340.8854) oklch(0.7 0.3357 340.8854 / 50%)

# data[].attributes.slidedeck.data[].slides[].desc.html
:root { —pink: rgb(255 26 211); } @supports (color: oklch(0.7 0.3357 340.8854)) { :root { —pink: oklch(0.7 0.3357 340.8854); } } .pool { —background-color: var(—pink); }

# data[].attributes.slidedeck.data[].slides[].desc.html
oklch.com

# data[].attributes.slidedeck.data[].slides[].desc.html
atmos.style https://huetone.ardov.me/

# data[].attributes.slidedeck.data[].slides[].desc.html
Relative Colors Baseline 2024 119 119 128 16.4

# data[].attributes.slidedeck.data[].slides[].desc.html
oklch(from var(—indigo) l c h); oklch(from var(—indigo) l c h / 50%);

# data[].attributes.slidedeck.data[].slides[].desc.html
—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);

# data[].attributes.slidedeck.data[].slides[].desc.html
https://ericportis.com/posts/2024/okay-color-spaces/

# data[].attributes.slidedeck.data[].slides[].desc.html
https://ericportis.com/posts/2024/okay-color-spaces/

# data[].attributes.slidedeck.data[].slides[].desc.html
Layout

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

# data[].attributes.slidedeck.data[].slides[].desc.html
CSS Grid

# data[].attributes.slidedeck.data[].slides[].desc.html
The majority of designers still has no idea of what’s possible with CSS Grid.

# data[].attributes.slidedeck.data[].slides[].desc.html
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));

# data[].attributes.slidedeck.data[].slides[].desc.html
Example: CSS Grid @jensimmons youtube.com/layoutland

# data[].attributes.slidedeck.data[].slides[].desc.html
https://labs.jensimmons.com/

# data[].attributes.slidedeck.data[].slides[].desc.html
https://labs.jensimmons.com/ Example: CSS Grid

# data[].attributes.slidedeck.data[].slides[].desc.html
https://codepen.io/matthiasott/pen/oNyqMgp

# data[].attributes.slidedeck.data[].slides[].desc.html
CSS Grid 98.38 % https://caniuse.com/css-grid

# data[].attributes.slidedeck.data[].slides[].desc.html
Subgrid

# data[].attributes.slidedeck.data[].slides[].desc.html
https://codepen.io/matthiasott/pen/JjqNPEN

# data[].attributes.slidedeck.data[].slides[].desc.html
Container Queries

# data[].attributes.slidedeck.data[].slides[].desc.html
https://codepen.io/matthiasott/pen/pomNgKJ

# data[].attributes.slidedeck.data[].slides[].desc.html
Accessibility Forms Interactivity Responsiveness Animation Performance

# data[].attributes.slidedeck.data[].slides[].desc.html
What is our toolset?

# data[].attributes.slidedeck.data[].slides[].desc.html
Use HTML and CSS much earlier in the process

# data[].attributes.slidedeck.data[].slides[].desc.html
Prototyping

# data[].attributes.slidedeck.data[].slides[].desc.html
high Fidelity low narrow Scope wide

# data[].attributes.slidedeck.data[].slides[].desc.html
Decide in the browser

# data[].attributes.slidedeck.data[].slides[].desc.html
Design Engineering

# data[].attributes.slidedeck.data[].slides[].desc.html
Design Engineering

# data[].attributes.slidedeck.data[].slides[].desc.html
Web Design Engineering

# data[].attributes.slidedeck.data[].slides[].desc.html
Let devs design

# data[].attributes.slidedeck.data[].slides[].desc.html
& Let devs design

# data[].attributes.slidedeck.data[].slides[].desc.html
& Let devs design Let designers code

# data[].attributes.slidedeck.data[].slides[].desc.html
Let devs design & Let designers code

# data[].attributes.slidedeck.data[].slides[].desc.html
Thank you! # Slides: https://noti.st/matthiasott/3QwwRt ! ownyourweb.site ” Typefaces: Tausend by Christoph Koeberlin, NaN Tresor by Christoph Koeberlin, NaN Tragedy by Jean-Baptiste Morizot, Input Mono by David Jonathan Ross