A presentation at Beyond Tellerrand in in Berlin, Germany by Manuel Matuzovic
matuzo.social
matuzo.social
matuzo.social S S C n i r o l o C
matuzo.social
matuzo.social
matuzo.social smashingconf.com/online-workshops/workshops/modern-css-manuel-matuzovic
tt matuzo.social container style queries scroll-driven animations lab()/oklab() display-p3 relative color syntax s of syntax container queries :is() / :where() transition-behavior nesting @property @starting-style scoping color-mix() color fonts color spaces :has() initial-le er logical properties subgrid text-wrap viewport units min() max() clamp() color() view transitions @media range syntax sin() cos() tan() gamuts lch()/oklch() light-dark()
tt matuzo.social container style queries scroll-driven animations lab()/oklab() display-p3 relative color syntax s of syntax container queries :is() / :where() transition-behavior nesting @property @starting-style scoping color-mix() color fonts color spaces :has() initial-le er logical properties subgrid text-wrap viewport units min() max() clamp() color() view transitions @media range syntax sin() cos() tan() gamuts lch()/oklch() light-dark()
matuzo.social display-p3 @media (color-gamut) conic-gradients color spaces @media (forced-colors) color-scheme gamuts @media (prefers-contrast) space-separated syntax relative color syntax @media(prefers-reduced- currentColor color-mix() transparency) system colors lch()/oklch() hue interpolation transparent lab()/oklab() perceptual uniform named colors color fonts accent-color hwb() color() gamut mapping … light-dark() gamut clipping
matuzo.social 1 2 3
<body bgcolor=”#00300” text=”#FFFFFF” alink=”#FFFFFF”> … </body>matuzo.social
matuzo.social 1 body { 2 3 background-color: #003300; }
matuzo.social
matuzo.social
matuzo.social 1 body { 2 3 background-image: linear-gradient(45deg, #030, #FFF); }
matuzo.social 1 body { 2 3 background-color: rgba(0, 51, 0, 0.5); }
matuzo.social #D04A6D
matuzo.social rgb(208, 74, 109)
matuzo.social youtu.be/eqZqx6lRPe0
matuzo.social 1 body { 2 3 background-color: hsl(120deg, 100%, 10%); }
matuzo.social smashingmagazine.com/2021/07/hsl-colors-css
matuzo.social 1 body { 2 3 background-color: hsl(120deg, 100%, 10%); }
matuzo.social en.wikipedia.org/wiki/HSL_and_HSV
matuzo.social 1 .notification { 2 —background-color: hsl(206deg 74% 90%); 3 —border-color: hsl(206deg 74% 70%); 4 5 background-color: var(—background-color); 6 border: 2px solid var(—border-color); 7 }
matuzo.social 1 .notification { 2 —h: 206deg; 3 —s: 74%; 4 —l: 90%; 5 6 —background-color: hsl(var(—h) var(—s) var(—l)); 7 —border-color: hsl(var(—h) var(—s) calc(var(—l) - 20%)); 8 9 10 11 } background-color: var(—background-color); border: 2px solid var(—border-color);
matuzo.social 1 2 3
<div role=”status” class=”notification” style=”—h: 40deg;”> <strong>Warning:</strong> You dropped the ball. </div> 4 5 6 7 <div role=”status” class=”notification” style=”—h: 0deg;”> <strong>Error:</strong> This is a tennis racket. </div>matuzo.social
matuzo.social SUCKS! 👎
matuzo.social GAMUT
matuzo.social en.wikipedia.org/wiki/Gamut
matuzo.social developer.chrome.com/docs/css-ui/access-colors-spaces
matuzo.social COLOR SPACES
matuzo.social en.wikipedia.org/wiki/HSL_and_HSV
matuzo.social en.wikipedia.org/wiki/HSL_and_HSV
matuzo.social cdpn.io/pen/debug/zdgXJj
matuzo.social cdpn.io/pen/debug/zdgXJj
matuzo.social commons.wikimedia.org/wiki/File:Visible_gamut_within_CIELAB_color_space_D65_whitepoint_mesh.webm
matuzo.social commons.wikimedia.org/wiki/File:Visible_gamut_within_CIELAB_color_space_D65_whitepoint_mesh.webm
matuzo.social commons.wikimedia.org/wiki/File:Visible_gamut_within_CIELAB_color_space_D65_whitepoint_mesh.webm
matuzo.social commons.wikimedia.org/wiki/File:Visible_gamut_within_CIELAB_color_space_D65_whitepoint_mesh.webm
matuzo.social commons.wikimedia.org/wiki/File:Visible_gamut_within_CIELAB_color_space_D65_whitepoint_mesh.webm
matuzo.social commons.wikimedia.org/wiki/File:Visible_gamut_within_CIELAB_color_space_D65_whitepoint_mesh.webm
matuzo.social hsl([x]deg, 100%, 50%) wildbit.com/blog/accessible-palette-stop-using-hsl-for-color-systems
matuzo.social 1 <button class=”btn”>Send</button> 2 3 <button class=”btn btn—success”>Save</button>
matuzo.social 1 .btn { 2 —h: 270; 3 —s: 100%; 4 —l: 50%; 5 6 background-color: hsl(var(—h) var(—s) var(—l)); 7 color: hsl(0 100% 100%); 8 } 9 10 .btn—success { 11 12 }
matuzo.social 1 .btn—success { 2 3 —h: 90; }
matuzo.social commons.wikimedia.org/wiki/File:Visible_gamut_within_CIELAB_color_space_D65_whitepoint_mesh.webm
matuzo.social commons.wikimedia.org/wiki/File:Visible_gamut_within_CIELAB_color_space_D65_whitepoint_mesh.webm
matuzo.social lea.verou.me/blog/2020/04/lch-colors-in-css-what-why-and-how
matuzo.social commons.wikimedia.org/wiki/File:Visible_gamut_within_CIELAB_color_space_D65_whitepoint_mesh.webm
matuzo.social commons.wikimedia.org/wiki/File:Visible_gamut_within_CIELAB_color_space_D65_whitepoint_mesh.webm
matuzo.social evilmartians.com/chronicles/oklch-in-css-why-quit-rgb-hsl
matuzo.social evilmartians.com/chronicles/oklch-in-css-why-quit-rgb-hsl
matuzo.social evilmartians.com/chronicles/oklch-in-css-why-quit-rgb-hsl
matuzo.social cdpn.io/pen/pen/zYeXvXM
matuzo.social cdpn.io/pen/debug/rNRoBXO
matuzo.social github.com/w3c/csswg-drafts/issues/9449
matuzo.social
matuzo.social w3.org/TR/css-color-4/#GM-hue-curvature
matuzo.social w3.org/TR/css-color-4/#GM-hue-curvature
matuzo.social bottosson.github.io/posts/oklab
matuzo.social
matuzo.social
matuzo.social 1 body { 2 background-color: lch(17 34.86 136.89); 3 background-color: lab(17 -25.45 23.82); 4 5 background-color: oklch(0.28 0.09 142.49); 6 background-color: oklab(0.28 -0.08 0.06); 7 } 111 111 113 15.4
matuzo.social oklch() l: lightness: 0% to 100% or 0 to 1 c: chroma 0 and 0.37. h: 0deg to 360deg. / a: 0 to 1 e.g., oklch(0.73 0.2 352)
matuzo.social oklch() oklab() l: lightness: 0% to 100% or 0 to 1 l: lightness: 0% to 100% or 0 to 1 c: chroma 0 and 0.37. a: -0.4 to 0.4 h: 0deg to 360deg. b: -0.4 to 0.4 / a: 0 to 1 / a: 0 to 1 e.g., oklch(0.73 0.2 352) e.g., oklab(0.73 0.2 -0.03)
oklch.com
oklch.com
matuzo.social 1 .btn { 2 —h: 270; 3 —s: 100%; 4 —l: 50%; 5 background-color: hsl(var(—h) var(—s) var(—l)); 6 } 7 8 .btn—success { 9 10 } —h: 90;
matuzo.social 1 .btn { 2 —l: 39.29%; 3 —c: 120.99; 4 —h: 308.07; 5 background-color: lch(var(—l) var(—c) var(—h)); 6 } 7 8 .btn—success { 9 10 } —h: 135.84;
matuzo.social SPACE-SEPARATED FUNCTIONAL COLOR NOTATIONS
matuzo.social 1 div:is():not(button) { 2 background-color: rgb(255, 0, 0); 3 background-color: rgba(255, 0, 0, 0.5); 4 5 background-color: rgb(255 0 0); 6 background-color: rgb(255 0 0 / 0.5); 7 8 background-color: oklch(0.63 0.26 29.23); 9 background-color: oklch(0.63 0.26 29.23 / 0.5); 10 } 65 79 52 12.1
matuzo.social COLOR()
matuzo.social 1 .valid-css-color-function-colors { 2 —srgb: color(srgb 1 1 1); 3 —srgb-linear: color(srgb-linear 100% 100% 100% / 50%); 4 —display-p3: color(display-p3 1 1 1); 5 —rec2020: color(rec2020 0 0 0); 6 —a98-rgb: color(a98-rgb 1 1 1 / 25%); 7 —prophoto: color(prophoto-rgb 0% 0% 0%); 8 —xyz: color(xyz 1 1 1); 9 } 111 111 113 15
matuzo.social 1 :root { 2 3 —primary: #FF0000; } 4 5 body { 6 7 background-color: var(—primary); } 8 9 @media (color-gamut: p3) { 10 :root { 11 12 —primary: oklch(0.63 0.26 29.23); } 13 } 14 15 @media (color-gamut: rec2020) { 16 :root { 17 18 —primary: color(rec2020 1 0 0); } 19 } 58 79 110 10
matuzo.social GRADIENTS
matuzo.social 1 div { 2 3 background-image: linear-gradient(to right, hotpink, aqua); }
matuzo.social 1 div { 2 3 background-image: linear-gradient(to right in oklab, hotpink, aqua); } 111 111 127 16.2
matuzo.social
matuzo.social nerdy.dev/gradients-going-the-shorter-longer-increasing-or-decreasing-route
matuzo.social 1 .shorter { 2 3 background-image: linear-gradient(to right in oklch shorter hue, hotpink, aqua); } 4 5 .longer { 6 7 background-image: linear-gradient(to right in oklch longer hue, hotpink, aqua); } 111 111 127 16.2
1 background-image: linear-gradient(to right in oklch shorter hue, hotpink, aqua); 1 background-image: linear-gradient(to right in oklch longer hue, hotpink, aqua);
matuzo.social COLOR-MIX()
matuzo.social 1 div { 2 3 background-color: color-mix(in srgb, hotpink, aqua); } 111 111 113 16.2
matuzo.social 1 div { 2 3 background-color: color-mix(in srgb, hotpink, aqua); } 111 111 113 16.2
matuzo.social 1 div { 2 3 background-color: color-mix(in srgb, 70% hotpink, 30% aqua); } 111 111 113 16.2
matuzo.social 1 div { 2 3 background-color: color-mix(in srgb, 70% hotpink, 30% aqua); } 111 111 113 16.2
matuzo.social
matuzo.social 1 div { 2 3 background-color: color-mix(in srgb, 13% hotpink, 12% aqua); } 111 111 113 16.2
matuzo.social 1 div { 2 3 background-color: color-mix(in srgb, 13% hotpink, 12% aqua); } 111 111 113 16.2
matuzo.social
cdpn.io/pen/debug/JjBZLrm
cdpn.io/pen/debug/JjBZLrm
matuzo.social RELATIVE COLOR SYNTAX
matuzo.social 1 div { 2 3 background-color: oklch(from #00F l c h); } 119 119 128 16.4
matuzo.social 1 :root { 2 3 —color: #00F; } 4 5 div { 6 7 background-color: oklch(from var(—color) l c 150); } 119 119 128 16.4
matuzo.social 1 :root { 2 3 —color: #00F; } 4 5 div { 6 7 background-color: hsl(from var(—color) h s calc(l - 10%)); } 119 119 128 16.4
matuzo.social 1 :root { 2 background-color: rgb(from var(—color) 3 calc(r * .3 + g * .59 + b * .11) 4 calc(r * .3 + g * .59 + b * .11) 5 calc(r * .3 + g * .59 + b * .11)); 6 } 119 119 128 16.4
matuzo.social 1 .notification { 2 —h: 206deg; 3 —s: 74%; 4 —l: 90%; 5 6 —background-color: hsl(var(—h) var(—s) var(—l)); 7 —border-color: hsl(var(—h) var(—s) calc(var(—l) - 20%)); 8 9 10 11 } background-color: var(—background-color); border: 2px solid var(—border-color);
matuzo.social 1 :root { 2 —color-info: oklch(0.92 0.03 240.82); 3 —color-warning: oklch(from var(—color-info) l c 84.52); 4 —color-error: oklch(from var(—color-info) l c 17.98); 5 } 6 7 .notification { 8 —_color: var(—color, var(—color-info)); 9 10 —background-color: var(—_color); 11 —border-color: oklch(from var(—_color) calc(l - 0.1) calc(c + 0.06) h); 12 13 background-color: var(—background-color); 14 border: 2px solid var(—border-color); 15 }
matuzo.social 1 :root { 2 —color-info: oklch(0.92 0.03 240.82); 3 —color-warning: oklch(from var(—color-info) l c 84.52); 4 —color-error: oklch(from var(—color-info) l c 17.98); 5 } 6 7 .notification { 8 —_color: var(—color, var(—color-info)); 9 10 —background-color: var(—_color); 11 —border-color: oklch(from var(—_color) calc(l - 0.1) calc(c + 0.06) h); 12 13 background-color: var(—background-color); 14 border: 2px solid var(—border-color); 15 }
matuzo.social 1 :root { 2 —color-info: oklch(0.92 0.03 240.82); 3 —color-warning: oklch(from var(—color-info) l c 84.52); 4 —color-error: oklch(from var(—color-info) l c 17.98); 5 } 6 7 .notification { 8 —_color: var(—color, var(—color-info)); 9 10 —background-color: var(—_color); 11 —border-color: oklch(from var(—_color) calc(l - 0.1) calc(c + 0.06) h); 12 13 background-color: var(—background-color); 14 border: 2px solid var(—border-color); 15 }
matuzo.social COLOR FONTS
matuzo.social
matuzo.social
matuzo.social 1 @font-palette-values —pink { 2 font-family: ‘Rocher’; 3 base-palette: 1; 4 } 5 6 @font-palette-values —green { 7 font-family: ‘Rocher’; 8 base-palette: 2; 9 } 10 11 @font-palette-values —gray { 12 font-family: ‘Rocher’; 13 base-palette: 9; 14 } 15 16 h1 { 17 font-palette: —pink; 18 } 101 101 107 15.4
wakamaifondue.com
wakamaifondue.com
matuzo.social 1 @font-palette-values —gray { 2 font-family: ‘Rocher’; 3 base-palette: 9; 4 5 6 override-colors: 3 rgb(21 58 81); } 101 101 107 15.4
matuzo.social 1 @font-palette-values —custom { 2 font-family: ‘Rocher’; 3 base-palette: 0; 4 5 override-colors: 6 0 hotpink, 7 1 red, 8 2 rebeccapurple, 9 3 aqua; 10 } 101 101 107 15.4
matuzo.social
matuzo.social COLOR SCHEMES
matuzo.social 1 :root { 2 3 color-scheme: light dark; } 81 81 96 13
matuzo.social 1 :root { 2 color-scheme: light dark; 3 } 1
<head> 2 3 <meta name=”color-scheme” content=”light dark”> </head> 81 81 96 13matuzo.social 1 :root { 2 —light: pink; 3 —dark: hotpink; 4 5 6 color-scheme: light dark; } 7 8 input { 9 10 —accent-color: var(—dark); accent-color: var(—accent-color); 11 } 12 13 @media(prefers-color-scheme: dark) { 14 input { 15 16 —accent-color: var(—light); } 17 } 76 79 67 12.1
matuzo.social 1 :root { 2 —light: pink; 3 —dark: hotpink; 4 5 6 color-scheme: light dark; } 7 8 input { 9 10 —accent-color: light-dark(var(—dark), var(—light)); accent-color: var(—accent-color); 11 } 123 123 120 17.5
matuzo.social css-tricks.com/come-to-the-light-dark-side/
matuzo.social MEDIA FEATURES
matuzo.social 1 dialog { 2 background: oklch(1 0 0 / var(—bg-opacity, 1)); 3 backdrop-filter: blur(5px); 4 } 5 6 @media(prefers-reduced-transparency: no-preference) { 7 dialog { 8 9 —bg-opacity: 0.2; } 10 } 118 118
matuzo.social
matuzo.social
matuzo.social 1 @media (prefers-contrast: more) { 2 :root { 3 —text-color: oklch(1 0 0); 4 5 } } 96 96 101 14.1
matuzo.social kilianvalkhof.com/2023/css-html/i-no-longer-understand-prefers-contrast
matuzo.social 1 @media (forced-colors: active) { 2 button { 3 border: 2px solid ButtonText; 4 5 } } 89 79 89 16
matuzo.social
matuzo.social blog.kizu.dev/querying-the-color-scheme/
matuzo.social lea.verou.me/blog/2024/contrast-color/
matuzo.social ❤ ! u o y k n a h T accessibility-cookbook.com matuzo.social matuzo.at htmhell.dev manuel@matuzo.at
Everybody’s talking about container queries, nesting, scroll-driven animation, and view transitions. In all the excitement for these new modules, one topic is a bit overlooked: color in CSS. Manuel Matuzović summarises all the new things we can do in CSS with color to create flexible, scalable, accessible, and user-friendly design systems.
Oh, and he talks about squash…