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 selectorStyle 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