Alle demoer virker i Chrome Canary
@layer theme { html { --color: oklch(80% 2 220); } * { text-box-trim: both; text-box-edge: cap alphabetic; } } @layer component { div { margin-trim: block; padding: 2rlh; :is(article):has(&) { --rainbow-gradient: in oklch longer hue, red 0 0; padding-inline: max(1rem, (100% - 800px) / 2); background: linear-gradient(45deg var(--rainbow-gradient)); container: div / inline-size; } :is(article) & { border: 2px solid color(display-p3 1 none 1); background: oklch(80% .37 220 / 25%); @container div (inline-size > 35rem) { font-size: calc(1rem * pow(1.25, 1)); } } :is(aside) { container: aside / sticky; position: sticky; inset-block-start: 0; @container aside state(stuck) { & h2 { background: red; } } } :is(h2, h3) { inline-size: 17ch; text-wrap: balance; } > h2 { background: hsl(from var(--color) h s calc(l + 10%)); } :not(article) & :nth-child(2 of .paragraph) { &:first-letter { initial-letter: 3; margin-inline-end: 1ch; } } & section { max-inline-size: 400px; > p { text-wrap: pretty; } } } }
@layer theme { html { --color: oklch(80% 2 220); } * { text-box-trim: both; text-box-edge: cap alphabetic; } } @layer component { div { margin-trim: block; padding: 2rlh; :is(article):has(&) { --rainbow-gradient: in oklch longer hue, red 0 0; padding-inline: max(1rem, (100% - 800px) / 2); background: linear-gradient(45deg var(--rainbow-gradient)); container: div / inline-size; } :is(article) & { border: 2px solid color(display-p3 1 none 1); background: oklch(80% .37 220 / 25%); @container div (inline-size > 35rem) { font-size: calc(1rem * pow(1.25, 1)); } } :is(aside) { container: aside / sticky; position: sticky; inset-block-start: 0; @container aside state(stuck) { & h2 { background: red; } } } :is(h2, h3) { inline-size: 17ch; text-wrap: balance; } > h2 { background: hsl(from var(--color) h s calc(l + 10%)); } :not(article) & :nth-child(2 of .paragraph) { &:first-letter { initial-letter: 3; margin-inline-end: 1ch; } } & section { max-inline-size: 400px; > p { text-wrap: pretty; } } } }
Det ligner CSS, men det føles som et nyt sprog
— "CSS4" måske?
2012 - 2017
Intrinsic web
2017 -
Intrinsic web
2017 -
2023 -
Intrinsic web
Robust, pålidelig og fleksibel
meget snart!
section { border: 2px solid red; color: red; } }
h2 {
section { border: 2px solid red; color: red; } }
&
h2 {
section { border: 2px solid red; color: red; } }
>
h2 {
section { border: 2px solid red; color: red; } }
:is( )
h2 {
✅
Hoisted
.feature-list { display: grid; grid: "stack"; :is(img, ul) { grid-area: stack; } > ul { z-index: 1; place-self: center start; > li { animation: opacity linear both; animation-timeline: view(); &:hover { opacity: .8; } } } }
article { padding: 1rem; background: aliceblue; color: darkslateblue; :nth-child(even) > & { color: aliceblue; background: darkslateblue; } }
p:not(#id) { color: green; } p.class { color: red; }
<p class="class">text</p> <p id="id">last text</p>
0,0,0
0,0,1
@layer reset { /* ... other reset rules */ input[type="text"] { border: 1px solid gray; } } @layer components { /* ... other component rules */ .my-input { border: 4px solid blue; } }
@layer reset { /* ... other reset rules */ input[type="text"] { border: 1px solid gray; } } @layer components { /* ... other component rules */ .my-input { border: 4px solid blue; } }
@layer reset { /* ... other reset rules */ input[type="text"] { border: 1px solid gray; } } @layer components { /* ... other component rules */ .my-input { border: 4px solid blue; } }
@layer reset, components, utilities; @layer reset { /* ... other reset rules */ input[type="text"] { border: 1px solid gray; } } @layer components { /* ... other component rules */ .my-input { border: 4px solid blue; } }
1
2
3
@layer reset, components, utilities; @layer components { /* ... other component rules */ .my-input { border: 4px solid blue; } } @layer reset { /* ... other reset rules */ input[type="text"] { border: 1px solid gray; } }
1
2
3
@layer reset, components, states; @layer components { /* Buttons, inputs etc. */ } @layer states { /* Make sure stats override, no matter specificity count */ :disabled { background-color: #ddd; color: #999; } :focus-visible { outline: 2px solid var(--focus-color, currentColor); outline-offset: 2px; } }
@layer reset, theme, global, layout, components, utilities, states;
.grid { align-items: last baseline; grid-template-columns: subgrid; }
meget snart!
Loading...
Loading...
Loading...
.subgrid { display: grid; grid-template-rows: [system-status] 3.5rem [primary-nav] 3rem [primary-header] 4rem [main] auto [footer] 4rem [system-gestures] 2rem; grid-template-columns: [fullbleed-start] 1rem [main-start] auto [main-end] 1rem [fullbleed-end]; }
nav { grid-area: primary-nav / fullbleed; display: grid; grid-template-columns: subgrid; } nav > .content { grid-area: main; }
body { display: grid; grid-template-rows: auto 1fr auto; grid-template-columns: [full-start] 1fr [content-start] minmax(0, 800px) [content-end] 1fr [full-end]; gap: 1rlh; > * { grid-column: content; } } header, main, footer { display: grid; grid-template-columns: subgrid; grid-column: full; align-content: start; > * { grid-column: content; } } .full-bleed { display: grid; grid-template-columns: subgrid; grid-column: full; > * { grid-column: content; } }
.cards { display: grid; gap: 1rlh; @media (width > 600px) { grid-template-columns: repeat(3, 1fr); } } .card { display: grid; grid-template-rows: subgrid; grid-row: span 3; }
@container (inline-size > 40em) { .card { flex-direction: column; } }
width
range
@media (20em < width <= 40em) { ... }
.card-wrapper { container-type: inline-size; } @container (inline-size > 40em) { .card { flex-direction: column; } }
.card-wrapper { container-type: inline-size; container-name: main; } @container main (inline-size > 40em) { .card { flex-direction: column; } }
.card-wrapper { container: main / inline-size; } @container main (inline-size > 40em) { .card { flex-direction: column; } }
flere navne
.card-wrapper { container: main / inline-size; } .card { font-size: clamp(1.45rem, 6cqi, 1.75rem); }
6 % af inline (bredden)
li:nth-last-child(odd):first-child
meget snart!
artcle:has(> img) {} p:not(article > *) { ... } article > :is(.class, #id) { ... } :where(#article) a { ... }
article:has(h2) { ... } article:not(:has(h2)) img { ... } article:has(> :last-child:nth-child(3)) { ... }
article:has(h2) { ... } article:not(:has(h2)) img { ... } article:has(> :last-child:nth-child(3)) { ... }
article:has(h2) { ... } article:not(:has(h2)) img { ... } article:has(> :last-child:nth-child(3)) { ... }
article:has(h2) { ... } article:not(:has(h2)) img { ... } article:has(> :last-child:nth-child(3)) { ... }
body { display: grid; } body:has(main + aside) { grid-template-columns: 1fr 300px; } body:has(aside + main) { grid-template-columns: 300px 1fr; }
:root:has(dialog[open]) { overflow: hidden; }
.valid-css-color-function-colors { --srgb: color(srgb 1 1 1); --srgb-linear: color(srgb-linear 100% 100% 100% / 50%); --display-p3: color(display-p3 1 1 1); --rec2020: color(rec2020 0 0 0); --a98-rgb: color(a98-rgb 1 1 1 / 25%); --prophoto: color(prophoto-rgb 0% 0% 0%); --xyz: color(xyz 1 1 1); }
.most-hyped { --display-p3: color(display-p3 1 1 1); --rec2020: color(rec2020 0 0 0); }
.element { background: oklch(80% .2 220); }
lightness
chroma
hue
In OKLCH all backgrounds with L≥87% have good contrast with black text.
in oklch
--bg: color-mix( in oklch, var(--color-a), var(--color-b) var(--percent) ) ;
Centering stuff
.element { display: flex; gap: 1.25ch; align-items: center; }
Centering stuff
Overskrift
Morbi tortor mi, semper id magna quis, auctor auctor purus. Nam pellentesque vulputate lectus, et euismod est tincidunt sed.
Overskrift
Overskrift
Overskrift
giraf
Figma: Vertical trim
h1 { text-box-trim: both; text-edge: cap alphabetic; }
Overskrift
Morbi tortor mi, semper id magna quis, auctor auctor purus. Nam pellentesque vulputate lectus, et euismod est tincidunt sed.
h1 { text-box-trim: both; text-edge: cap alphabetic; /* future? */ /* text-box-trim: cap alphabetic; */ }
.balance { text-wrap: balance; } .pretty { text-wrap: pretty; }
article { padding: 2rlh; gap: 1rlh; }
Intrinsic web
Hvorfor griber man typisk fat i JS?
Comparison Function
min(), max(), clamp()
Stepped Value Functions
round(), mod(), rem()
Trigonometric Functions
sin(), cos(), tan(), asin(), acos(), atan(), atan2()
Exponential Functions
pow(), sqrt(), hypot(), log(), exp()
Sign-Related Functions
abs(), sign()
Numeric Constants
e, pi
Degenerate Numeric Constants
infinity, -infinity, NaN
Er CSS snart et programmeringssprog? 😉
Inert, Esc dismiss,
top-layer
Loading...
.box { rotate: 45deg; translate: -50% -50%; scale: 1.1; } .box:hover { rotate: 0deg; }
@property --colorPrimary { syntax: '<color>'; }
@property --colorPrimary { syntax: '<color>'; initial-value: magenta; }
@property --colorPrimary { syntax: '<color>'; initial-value: magenta; inherits: false; }
@property --colorPrimary { syntax: '<color>'; initial-value: magenta; inherits: false; }
@property --colorPrimary { syntax: '<color>'; initial-value: magenta; inherits: false; }
@property --colorPrimary { syntax: '<color>'; initial-value: magenta; inherits: false; }
OBS! @property performance
Optimized composited scroll animations
Not blocking main thread
Loading...
Loading...
Loading...
Loading...
Loading...
.element { animation: progress linear; animation-timeline: scroll(block root); }
.element { animation: progress linear; animation-timeline: scroll(); }
.element { animation: reveal linear; animation-timeline: view(); animation-range: cover 0% entry 100%; }
section > * { animation: entry linear, exit linear; animation-timeline: view(); animation-range: [...]; }
Optimized flip-animations
Loading...
Loading...
Loading...
Loading...
.box-1 { view-transition-name: box-1; } .box-2 { view-transition-name: box-2; }
.box-1 { view-transition-name: box-1; } .box-2 { view-transition-name: box-2; }
btn.addEventListener("click", () => { document.startViewTransition(_ => grid.classList.toggle("col-count")); });
.box-1 { view-transition-name: box-1; } .box-2 { view-transition-name: box-2; }
btn.addEventListener("click", () => { if (document.startViewTransition) { document.startViewTransition(_ => grid.classList.toggle("col-count")); } else { grid.classList.toggle("col-count"); } });
.box-1 { view-transition-name: box-1; } ::view-transition-new(box-1) { animation: scale-in .5s both; } ::view-transition-old(box-1) { animation: scale-in .5s both reverse; }