Separate your application logic from your styling logic
minmax()
, clamp()
, CSS trigonometry)@container
, style()
):has()
, :not()
)view-timeline
)popover
, anchor
)@property
):clamp()
responsive typography.item {
--radius: calc(var(--btn-size) + var(--extra-space));
background-color: var(--bg);
transform: translateX(calc(cos(var(--angle)) * var(--radius)))
translateY(calc(sin(var(--angle) * -1) * var(--radius)));
transition: transform 0.3s var(--delay) ease;
}
Popover + Anchor positioning
popover
attributeBuilt-in accessibility semantics, keyboard behavior, tab focus management, and (optional) light-dismiss
May 2023
❌
❌
<!-- Button -->
<button popovertarget="my-popover">
Open Me
</button>
<!-- Popover -->
<div id="my-popover" popover>
Popover Stuff
</div>
<button popovertarget="my-popover">
Open Popover
</button>
<div id="my-popover" popover>
<p>I am a popover with more information.<p>
</div>
<button popovertarget="my-popover">
Open Popover
</button>
<div id="my-popover" popover="manual">
<button class="close-btn"
popovertarget="my-popover"
popovertargetaction="hide">
<span aria-hidden=”true”>❌</span>
<span class="sr-only">Close</span>
</button>
<p>I am a popover with more information.<p>
</div>
:popover-open
@starting-style
Soon ⚠️
❌
❌
.settings-popover {
&:popover-open {
/* 0. BEFORE-OPEN */
@starting-style {
transform: translateY(20px);
opacity: 0;
}
/* 1. OPEN STATE */
transform: translateY(0);
opacity: 1;
}
/* 2. EXIT STATE */
transform: translateY(-50px);
opacity: 0;
/* List transitioning properties (w/ display) */
transition: transform 0.5s,
opacity 0.5s,
display 0.5s;
}
Popover + Anchor positioning
anchor
positioninganchor=""
anchor()
@try {}
Soon ⚠️
❌
❌
<!-- Add an id -->
<button popovertarget="my-popover" id="toggle-btn">
Open Me
</button>
<!-- Add an anchor -->
<div popover id="my-popover" anchor="toggle-btn">
Popover Stuff
</div>
#profile-settings-popover {
bottom: calc(anchor(top) + var(--spacer));
right: calc(anchor(right));
}
[popover] {
bottom: calc(anchor(top) + 1rem);
right: calc(anchor(right));
}
I am a popover tooltip with more information. I am a popover tooltip with more information. I am a popover tooltip with more information. I am a popover tooltip with more information.
I am a non-popover anchored tooltip with more information. I am a non-popover anchored tooltip with more information. I am a non-popover anchored tooltip with more information. I am a non-popover anchored tooltip with more information.
<!-- Selectmenu -->
<selectmenu>
<button slot="button" behavior="button">
<label>Select a color</label>
<span slot="selected-value"
behavior="selected-value"
class="selected-val"></span>
</button>
<option value="Red">
<figure class="red"></figure>
Red
</option>
<option value="Orange">
<figure class="orange"></figure>
Orange
</option>
<option value="Yellow">
<figure class="yellow"></figure>
Yellow
</option>
...
</selectmenu>
:has()
relational selectorStyle parent elements (and more) based on the presence or state of child elements
Aug 2022
Mar 2022
🏁
:has()
relational selectorThis figure doesn't have a figcaption. Lorem ipsum dolor sit amet consectetur adipisicing elit. Eveniet ipsam, ad delectus doloremque blanditiis in incidunt numquam eum ullam ut quo porro vel soluta deleniti rerum reprehenderit quae aliquid quos.
This figure does have a figcaption. Lorem ipsum dolor sit amet consectetur adipisicing elit. Nostrum, aut. Minima natus nulla, dicta, quasi autem a architecto, earum explicabo molestias illum eum rerum magni! Harum sequi cumque quia expedita.
Style based on the number of children
:has(:nth-child(n + x))
@container style(--sunny: true) { .card { ... } }
@container style(--sunny: true) and style(--cloudy: true) { .card { ... } }
@container style(--rain) { .card { ... } }
@container style(25% <= --rain <= 50%) { .card { ... } }
@property
declaration
@property --colorPrimary {
syntax: '<color>';
initial-value: magenta;
inherits: false;
}
@property
Typed CSS
.card {
background-color: var(--colorPrimary); /* magenta */
}
.highlight-card {
--colorPrimary: yellow;
background-color: var(--colorPrimary); /* yellow */
}
.another-card {
--colorPrimary: 23;
background-color: var(--colorPrimary); /* magenta */
}
@property --gradPoint {
syntax: '<percentage>';
inherits: false;
initial-value: 40%;
}
.post {
background:
linear-gradient(var(--color1) var(--gradPoint),
var(--color2) calc(var(--gradPoint) + 20%));
transition: --gradPoint 0.5s;
}
.post:hover, .post:focus {
--gradPoint: 100%;
}
@keyframes fly-in {
0% {
opacity: 0;
transform: translateX(-100px);
}
50% {
opacity: 1;
transform: translateX(0px);
}
}
blockquote {
animation: fly-in auto linear;
animation-timeline: view();
}
🤫 This presentation is fully built with vanilla CSS & HTML*
*with some iframes for demos due to laziness
<style>
with display:block
and contenteditable
scroll-snap
accesskey
The best way to level up your developer skillset is to get good at CSS and HTML
Leverage the browser
Don't underestimate CSS and vanilla HTML components