Getting Reactive with CSS
David Khourshid · @davidkpiano
CSS is not powerful
but that's a good thing.
What if web apps
felt native?
What if interactive web UIs
were easier to make
with CSS?
CSS
IS
AWESOME
CSS
IS
AW...
FUL
CSS
IS
FUN
CTIONAL
CSS Variables
Functional & Reactive
CSS in JS
React, Angular, Vue
There are only two hard things
in computer science:
-
Naming things
-
Vertically centering things
CSS-Modules, etc:
.button {
/* ... */
}
.Anklickbar-Knopfart {
/* ... */
}
<DIV ID="oDiv"
STYLE="background-color: #CFCFCF; position: absolute;
left: expression(document.body.clientWidth / 2 - oDiv.offsetWidth / 2);
top: expression(document.body.clientHeight / 2 - oDiv.offsetHeight / 2)">
Example DIV
</DIV>
CSS Expressions (IE7)
<style type="text/javascript">
tags.H1.color = "red";
tags.p.fontSize = "20pt";
with (tags.H3) {
color = "green";
}
with (tags.H2) {
color = "red";
fontSize = "16pt";
marginTop = "4cm";
}
</style>
JavaScript Style Sheets (Netscape 4)
.box {
--delta-x: 150px;
}
CSS
.box {
--delta-x: 150px;
transform: translateX(
var(--delta-x));
}
CSS
.box {
--delta-x: 150;
transform: translateX(
calc(var(--delta-x) * 1px));
}
CSS
.box {
transform:
translateX(calc(var(--delta-x) * 1px));
}
const box = document.querySelector('#box');
const hBox = new Hammer(box);
hBox.on('panleft panright', (e) => {
box.style
.setProperty('--delta-x', e.deltaX);
});
hBox.on('panend', () => {
box.style
.setProperty('--delta-x', 0);
});
CSS
JAVASCRIPT
.box {
--not-panning: calc(-1 * var(--panning) + 1);
transition:
transform
calc(var(--not-panning) * .6s)
ease-out;
transform:
translateX(calc(var(--delta-x) * 1px))
rotate(calc(var(--delta-x) * .1deg));
}
const box = document.querySelector('#box');
const hBox = new Hammer(box);
hBox.on('panleft panright', (e) => {
box.style
.setProperty('--delta-x', e.deltaX);
box.style
.setProperty('--panning', 1); // true
});
hBox.on('panend', () => {
box.style
.setProperty('--delta-x', 0);
box.style
.setProperty('--panning', 0); // false
});
CSS
JAVASCRIPT
calc(-1 * var(--panning) + 1) -1 * 1 + 1 = 0 -1 * 0 + 1 = 1
sudo npm install wifi
Why CSS Variables?
Media Queries
:root {
--pan-fraction: 1;
--duration: 0.3s;
}
@media (max-width: 700px) {
:root {
--pan-fraction: 0.5;
}
}
@media (prefers-reduced-motion) {
:root {
--duration: 0s;
}
}
.card {
transform: translateX(calc(
var(--pan-fraction)
* var(--delta-x)
* 1px
));
transition-duration: var(--duration);
}
Pseudoselectors
.box {
--progress-x:
calc(var(--delta-x, 0) / 100);
transform:
translateX(calc(var(--delta-x, 0));
}
.box::before {
content: 'Nicht';
color: red;
opacity:
calc(var(--progress-x) * -1));
}
.box::after {
content: 'Jawohl';
color: green;
opacity: var(--progress-x);
}
Performance
Inspection
What if
you wanted to
react
What if
to any event
at any time
you wanted to
react
What if
to any event
at any time
to create rich, interactive UIs
you wanted to
react
What if
to any event
at any time
to create rich, interactive UIs
in an expressive, declarative way?
you wanted to
react
Functional Reactive Animations
(Continuous) events
Discrete changes
A "reactive animation" is one involving discrete changes, due to events.
By allowing programmers to express the "what" of an interactive animation, one can hope to then automate the "how" of its presentation.
[
]
. . .
Value
Array
Promise
Observable
3s
1s
2s
3.5s
Observables with RxJS
const box = document.querySelector('.box');
const mouseMove$ = Rx.Observable
.fromEvent(box, 'mousemove')
.map(e => ({
x: e.clientX,
y: e.clientY
});
const hBox = new Hammer(box);
const pan$ = Rx.Observable
.fromEventPattern(handler =>
hBox.on('panleft panright', handler))
.map(e => ({
deltaX: e.deltaX,
deltaY: e.deltaY
});
Rx.Observable.fromEvent()
-
DOM element
-
event name
Rx.Observable.fromEventPattern()
-
function that adds handler
-
function that removes handler
ball$.map(toSquare)
ball$.delay(300)
ball$.filter(isRed)
ball$.scan((a, b) => a + b)
1
1
1
5
2
2
1
1
2
3
8
10
12
13
Marble Diagrams
Observaballs
observable$.subscribe((value) => {
// do anything with the value
});
pan$.subscribe((value) => {
const { deltaX } = value;
box.style
.setProperty('--delta-x', deltaX);
});
Subscribing to Observables
If you can read this, the WiFi is a little spotty
please WiFi work 🙏
🔜
oh my god
why did I make so many demos
JavaScript
CSS
JavaScript
CSS
JavaScript
CSS
Any source
Any medium
Material Motion
What will you make with CSS Variables?
Thank you CSSConfEU!
Getting Reactive with CSS
By David Khourshid
Getting Reactive with CSS
CSSConfEU 2017
- 23,773