# Reactive Animations with CSS Variables

Canonical: https://davidk.dev/talks/reactive-animations-with-css-variables/
Video: https://www.youtube.com/watch?v=lTCukb6Zn3g
Speaker: David Khourshid (@DavidKPiano), creator of XState
Type: Conference talk · Event: JSConf Iceland 2016 · Year: 2016 · Duration: 31:03 · Views: 18235 (as of 2026-10-19)
Topics: CSS & animation, Reactive programming, Event-driven architecture

## Summary
CSS variables are here, and they're much more powerful than you think. In this presentation, we will explore the many possibilities with mixing RxJS with CSS variables, including how they can be used to bring your web projects to life with dynamic animations that react to user input. And yes, there will be plenty of demos.

## Key takeaways (quoted from the transcript)
- I would look at examples on dribble, some cool animations, and then I would try to recreate it as best as I could, using only CSS. (2:00)
- Title of my talk is called reactive animations with CSS variables, but I'm not going to be talking about React in this talk. (5:00)
- To apply your CSS, whether it's SAS, L Stylus, PostCSS, or inline Styles does not matter, you could use CSS variables in any of those. (17:00)
- We talked about RxJS, we talked about CSS variables, and we sort of had a hint of how we could mix the two. (23:00)
- What this means is that when you do animations in CSS, you could have those same values dispatched to both canvas. (30:00)

## Chapters
- 0:00 Introduction
- 11:00 First of all, inline styles are going to override any other…
- 13:00 Let's talk real quick about CSS variables
- 17:00 Creating an observable, there's a way to manually create an observable
- 20:00 We also have things such as flat map, where…
- 23:00 Turns out that we could do it with using RX, CSS…

## Transcript
[0:00] Hey everyone, my name is David Khourshid. And, believe it or not, animation is an extremely important part of the user experience. In fact, there's a lot of you here right now. This is probably the most amount of people I've talked to, but many of you are here right now because you realize that. Animation is a growing Trend in both the web and mobile app development, and this is for good reason, too.

[0:00] Animation increases Delight, reduces cognitive load, and it could be an important factor in your brand when it comes to your style guide. So a lot of developers realize this, but so do a lot of users. If you open an app in your iPhone or Android device, you will expect animations to happen whenever you interact with the app. So, my name is David, as I said, and I live in Florida, which is right about there.

[1:00] And this is actually pretty exciting because I'm at JS comp to you, partially talking about CSS, which all of you are familiar with. This is pretty much where I sat on the airplane, I got like an hour of sleep. So so, like most friend and developers, which I'm guessing all of you are either doing a JavaScript on the front end or back end. There's two very important technologies that we have to work with, and that's JavaScript and CSS.

[1:00] And as front and developers, we know that the landscape is constantly changing as well. So we love to experiment, or at least most of us love to experiment. And a couple years ago, I asked myself the question what if, what if I were to maybe not use JavaScript and see what CSS could do? So this is how I approached user interfaces. I would look at examples on dribble, some cool animations, and then I would try to recreate it as best as I could, using only CSS.

[2:00] And so I looked for more and more complex examples, including ones with stateful transitions, such as this one. And with lots of checkbox hacks, hacks and like target, whatever. I was able to, you know, recreate it pretty well. And, by the way, don't do this. These were all really fun experiments. But JavaScript is good for a lot of things, and you should probably use JavaScript. If you want to do interactive animations like this, I got a bit crazy.

[2:00] Saw, you know, some animations online and I decided to recreate them completely in CSS. So this is one of the animations I made. And, one important thing here is that we have the dev tools on the right. If I created this with just JavaScript, we would not get this. We would not be able to play around and interact with all of the elements, you know, in CSS. So why do we get this with CSS animations and not yet with JavaScript animations?

[3:00] Well, it turns out that even though CSS could do a lot of things, it involves a lot of hacks. So I realize that CSS is not the most powerful language, and that's why a lot of people start flocking to using CSS. In JavaScript, using JavaScript to apply Styles, because, hey, JavaScript is a much more powerful language. But here's the thing the fact that CSS is not powerful is actually a good thing.

[4:00] There's this principle called the principle of least power, and it states that you should use the least powerful language for expressing information con constraints or programs on the worldwide web. And the principle basically states that powerful languages such as JavaScript inhibit information reuse, and what I mean by that is that, even though JavaScript could do a lot of things, the. The fact of the matter is that CSS provides, like a limited, dynamic library that, that you could use to, express style, succinctly, and JavaScript, even though it could do everything.

[4:00] You're going to, you know, have a mess in your code. If you try to define Styles in there, or try to define many things at once, so it's sort of inhibits, reuse if you do that. So today we're going to be talking about two things CSS variables and RxJS observables. How many of you are familiar with CSS variables? All right, how about observables? All right, few less people. If you don't know anything about any of these two, that's okay.

[5:00] We're going to go over them from scratch and sort of just do a quick deep dive into both of them, and then we're going to understand how they could actually work together. Now, I know the. Title of my talk is called reactive animations with CSS variables, but I'm not going to be talking about React in this talk. Unfortunately, however, the good news is that the techniques that you'll learn here you could apply to any framework.

[5:00] React, Angular, Ember, or any of those other dead ones. I'm kidding, no, React is good, Angular is great. Um. And CSS and JavaScript sort of seem at two different ends of the spectrum. We have custom properties being very much a CSS thing and observables being very much a JavaScript thing. So today you're going to get sort of a taste of both, and we're going to, for whatever reason, try to mix them together.

[6:00] So through all this, you might be asking yourself, why? Why do we want to do this? Why do we want to mix, you know, CSS and JavaScript together in this way? And the reason is because, frankly, you can make a lot of really cool animations using that. We have right now a system of doing things in JavaScript where it's imperative, and by imperative. It means we're telling JavaScript exactly what to do, how to apply each style to element.

[7:00] And because of that, we can't iterate quickly and we can't quickly create user interfaces that are rich in interaction and animation, such as the ones you see here. And I'm a little jealous of mobile developers because Android and iOS developers, they basically get the tools to do this for free. And us in the web, we're sort of left in the dark. So let's first dive into how animation are currently done. We have CSS animations which look like this.

[7:00] Most of you are familiar with this. There's two types transitions and, animations. Transitions are good from when you're going from point A to B, and maybe going back from point B to point A. And animations are good when you want to define explicit steps or key frames in your animation so that it does a certain behavior that you want. The beauty about this is that CSS animations are declarative, they're reusable, they're also really legible.

[8:00] I mean, you could read this and know exactly what's going on. Also, these are built into the browser so you don't need any external library to pull in order to. Get these animations. Support's also pretty good, it goes back to I9, I believe, for animations, and hopefully no one uses I8 anyway. Uh. CSS animations can also be offloaded to the Global processing unit, the GPU. Which means they are not going to be choked up by the main thread, especially if you're using a framework like reactor Angular, we're using the main thread for a lot of things.

[8:00] So it's best to, you know, keep things such as styling and animation off that thread. Also, we could use selectors, media queries and other things like that to define our animations. So, we could keep that separate from the DOM. So that when elements appear and disappear, we don't have to keep track of those in CSS. But also this has issues. One of the big issue is that CSS animations are not dynamic.

[9:00] We can't change these on the Fly, we can't, um. For example, set this translate Y value to anything other than 50% or anything other than a static value. And they're pretty difficult to compose, so if you want one animation to go after the other, that's not the easiest thing. Trust me, I've done it, I've tried, it's it's a pain in the ass, it keeps me up at night. So we also have JavaScript animations and this is the web animations API, which is a, pretty recent spec.

[9:00] And it's actually really awesome because it is supported in mainstream browsers today. And it looks almost exactly like, like the CSS animations example. And that's because it pretty much is it uses the same underlying constructs in order to make the animation, so this is the exact same animation we saw. And this is offloaded from the main thread to the GPU, so this is going to be really fast, really performant. And the beauty is that because it's in JavaScript, it's dynamic, we could add this to any element.

[10:00] We could tell it to start, tell it to stop, whenever we want. But um. The web animations API is not really support an Internet Explorer, but that's okay, because nothing is. There's also dynamic JavaScript animations too. And this is sort of the problem that we're going to be tackling today. This is how we do them today. We use request animation frame, which basically asks the. Browser which animation frame should I do this on?

[10:00] So that I'm not choking the main thread and that I'm making sure that my per, my animations run at 60 frames per second.

[11:00] And so we run this in a loop sometimes, or we run this on events such as, this one. So over here. We're moving the mouse, and whenever we move the mouse, we get a, we get an events back, and from that events, we could grab the X and Y position from the mouse. And we're directly applying it to the style of the box. This is inline Styles. This is bad for many reasons.

[11:00] First of all, inline styles are going to override any other styles you have. It's hard to configure them. You can't put it in a media query. Well, actually, you could. You could listen for the browser, resize event and change the animation based on that. You're also updating the DOM a lot, and updating the DOM is expensive. For those of you who've heard Lind's talk, it's an expensive procedure. And that's why React in other Frameworks try to minimize updating the DOM as much as possible.

[12:00] By doing this, you're saying, forget that I'm going to update it all the time, and there's nothing you could do about it. Also, because this DOM elements the box has to exist at the time that you're adding the animation. This could also be problematic if you're using Frameworks such as Angular React, where DOM elements appear and disappear. They're mounted and they're unmounted pretty much all the time. So the problem with this is that you have to keep track of it.

[12:00] And you have to make sure that when it's added back, you're adding this event listener back on. And also, if you want to add more animations based on the same event listener, you either have to hardcode it inside this function right here, or you have to add another event listener.

[13:00] Which could lead to memory leaks. Because that's a lot of event listeners to keep track of, all right? So let's talk real quick about CSS variables. In case you know you might not know, this is how a CSS variable is defined. It's prepended with two dashes. I don't know why it stands out, though, and in. Order to use it, you would put it inside a selector such as root. And this is the most common way that you're going to see CSS variables being defined.

[13:00] Because this is going to Cascade down and be applied to pretty much, every selector that asks for the color, and for this, you would just put it inside a selector. And that color is going to be applied to any element. With, you know, with that class name. And of course, this follows cascading, and it also follows specificity too. So you could do some pretty cool things like putting this in a media query, or putting it as a different color in a more specific selector.

[14:00] So you have a high amounts of configurability with this. Now, here's a really cool part about CSS variables, and that's that you could define them in JavaScript. So we have three methods to do this. We have set property, which is going to, set the custom property, and it's going to put it right on the HTML root elements. You could also get the property value like, like, so, so you just pass in the variable name and it's going to return that value to you as a string.

[14:00] And there's also remove property. You know, if you ever need it. So, waiting for my slides to update, all right, here we go. So here's an example of this. I didn't make this, West boss made it really cool. Example where I'm attaching what I just showed you, updating the values with JavaScript, and I'm attaching those to event listeners here. So, as you could see, we could dynamically change all of these different variables, and this is just using CSS.

[15:00] If you can't see, I'm changing that to Blue. And so our JavaScript is very small. By small. I mean, you could barely read it because it's so tiny up there. But just trust me. These variables are being applied using. Just, if my slides decide to let me go to the next example, but they probably won't, so that's okay. Ah, here we Wi-Fi, all right, we'll skip that. Let's look at browser supports, so browser support for CSS variables, believe it or not, is actually very good.

[16:00] And this is very recent. In fact, my IOS Safari right now is still. At 9.2 and, 9.3, I guess just came out. So. The only problem here, though, is that neither Internet Explorer or edge support, you know, custom properties. But not a big surprise, not a big problem either. Because we could use, we could use plugins such as, there's a couple posts. Plugins for variables that will default to the original value.

[17:00] And, ignore any other their custom variable declarations in your CSS.

[17:00] So this is where Progressive Enhancement comes in really, really handy pre-processor supports to is actually really good, so it doesn't matter what you're using to. To apply your CSS, whether it's SAS, L Stylus, PostCSS, or inline Styles does not matter, you could use CSS variables in any of those. All right, let's talk real quick now about RxJS observables, which about half of you already know about, and half of you maybe don't.

[17:00] So this is going to be a real quick crash course. Arrays are a finite collection of values, so, for example, this array has six balls. In the stream is sort of like an array, except these values come in over time and they come at different times. And streams can also have a beginning and an end. So, if you're a musician, think of an array as a chord that you play, or, you know, to compare that to a stream.

[18:00] Think of a stream as an arpegio, where you play one note at a time instead of all notes at the same time. So a good way to think about this is that an observable stream is an array that's asynchronous, the items can come in at any time, it's immutable, which means whenever you do something like an operator to an observable, it's going to give you a new observable instead of that same observable.

[18:00] And it's subscribable, so whenever an item is pushed onto the observable, whatever is subscribing to, it will know about it when it happens. Finally, that slide loaded, all right. So, over here, we're applying CSS variables the same way, I'm going to backtrack a bit and we're adding a transition to it. So what's going to happen is that by changing the values, you see that, using CSS, we could smoothly transition each value all right back to our scheduled programming.

[19:00] Thanks, Slides.com. All right, browser support, Internet Explorer sucks, inline Styles suck, all right, moving on. So, creating an observable, there's a way to manually create an observable. But we're going to breeze through that and we're going to just figure out the most common ways of creating an observable. So RxJS has a way to take normal noral arrays or normal iterable, such as set. And by calling from, you could create an observable from that, you could also create an observable from a promise.

[20:00] Which is basically going to be a stream of only one value, which is the return value of the promise.

[20:00] Or whenever you call, do then on a promise, that's a value that you get back. We could also call observables from events, which is what we're going to be using, in the coming slides. So we give it the DOM node, and we give it the event name, such as mouse move. We could also call it from an event pattern, so what an event pattern is just a call back. So there's a lot of libraries that use callbacks for their event patterns, such as Hammer..js.

[20:00] And this is one that I use in a lot of my examples when showing U.M. Observables with CSS variables. Because Hammer.js abstracts all of these concepts and it's really easy to use, so we could emulate. Rotating, pinching, pressing, panning, tapping, swiping, all the things that you're used to on mobile devices, on regular websites. So all you do is you pass in the DOM elements to Hammer. And then we're going to have a, event pattern, which takes in the handler and passes that on to.

[21:00] Whatever, Hammer.Js is doing so over here, all we're doing is listening. For pan. Now, subscribing to an observable is pretty easy, too. All you do is, you call, do, subscribe on that observable. And you pass it in a function where every single value, whenever you get a value, you do something with it. Optionally, you could pass in an error handler and a completion handler. So pretty much the only thing you need to remember from this, unless you want to dive into more details, is that you could pass a handler.

[21:00] To sub describe. That does something. Every time an event is called, there's also a bunch of. Operators, too. And the best thing to think about is that RS RxJS is low dash for observables. So we have the same methods that we could use on arrays, such as filter, where we? If you imagine this as an array. All we're doing is taking the green balls. There's also map, which works just as you would expect, there's debounce, which doesn't really happen to arrays, because arrays are not time based, and there's Scan, where.

[22:00] It's sort of like array reduce. And we also have things such as flat map, where, if you think of an array of arrays and you want that to squish into one array, flat map is basically the same thing. Okay? So here is an example of using an observable to update the DOM.

[23:00] All we're doing here is we're listening for the M Mass event and we're seeing, you know, the values change over here, so think about this. We're using an event to create an observable to update the DOM. Whenever the mouse moves. So hopefully, if the slides change, will. Are you thinking what I'm thinking? I mean, hopefully you are. We talked about RxJS, we talked about CSS variables, and we sort of had a hint of how we could mix the two.

[23:00] So what if we modeled observable events as CSS variables? What I mean by this is a question that you might have all asked before is what if we could write JavaScript in CSS? So this is where functional reactive animations come into play, and we're going to be doing this with CSS variables and RxJS observables. And, trust me, they're a awesome. This is not a new idea, dates back to 1997, in a academic paper called functional reactive animations.

[24:00] Which is one involving discrete changes due to events such as user behaviors, or even other behaviors, or behaviors that are based on other behaviors as well. An important quote here is, by allowing programmers to express the what we could hope to automate. The how React is really good at doing this, but we're not the best at doing this with animations right now. Because right now, the way we do this is we directly tell JavaScript how to style each element.

[24:00] So here's a little preview of what we're going to be doing. So taking the last mouse example, where whenever I move my mouse, the values are updated, we could see that the little Husky's head moves around and follows the mouse. Now there's a lot of moving parts here, so you might think there's a lot of JavaScript, but in fact, that's all. That's all we have. Everything is being applied to the CSS, which is a crap ton, so we're not going to go through that.

[25:00] And as I'm waiting for the slide to change, actually, you know what, I'll do it right here, that's a wrong slide, all right. So here's how we're going to do that. We're going to need to use something called a subject. Now. A subject in RxJS is just something that's both an observable and an observer, so this subject is going to observe many things. Such as whenever the mouse moves, whenever we scroll, tap, swipe, maybe timers that we have, it's going to send them off.

[25:00] As a side effect to CSS variables, using the techniques we learned about how to apply CSS variables with JavaScript. And it's going to also dispatch to all of our observers whenever the values change, of course, that's optional. I made a really, really tiny library for this called RX CSS, and it's on MPM if you want to try it. And all it does is we take in observables such as whenever we move the mouse which, of course, is just from the mouse move event, and we stick that into the RX CSS.

[26:00] Function. So if you're familiar with Redux, think of this as combining, reducers. If you're not familiar with Redux, you have no idea what I'm talking about. But basically, you could just stick that inside the RX CSS function, and then you could use these values directly inside your CSS. So hopefully you could see how this is, you know, very, very useful, where we could define dynamic animations inside of our CSS. And of course, it only comes down to 1.56 kilobytes if you're already using RxJS, which in some of your applications you are.

[27:00] So let's look at a real quick example of how we could, apply this. This is something that I found on dribble, which, you know, is Iceland, so it's fitting and it's a really cool animation where whenever you scroll, did. You see how the background image sort of faded out and, disappeared, and it also scaled in a little bit. And also when they click the horse, when they drag it, it moves up and the text disappears.

[27:00] So think in your minds, how am I going to do this with? Just JavaScript probably involves a lot of code, a lot of event listeners. But turns out that we could do it with using RX, CSS, or, defining those variables in JavaScript and sending them to CSS variables. So this is what it looks like, and this is Harpa where we are right now. And so, as you could see, a lot of things are happening, but not a lot of JavaScript is happening over here.

[28:00] All I'm doing is sending two observables if you could see that. We're doing the photo pan, which is whenever we move our finger on the photo. And we're also, adding a scroll event so that the background image changes whenever we scroll. And it's going to be dynamic and it's going to also be performance. I tested this, ran out a smooth 60 frames per second. So, yeah, change this. So why use CSS variables?

[28:00] Well, there's, there's a few reasons, first of all, you don't get excessive DA manipulation. You might, be familiar with if you're applying transitions to all of your to all of your elements on your DOM. That there's going to be a bunch of purple over here. Thankfully, with CSS variables, the only thing that's really being manipulated is that top root element over there. That's what's changing. And there's also a bunch of really good reasons.

[29:00] Such as you could debug it, you could change CSS variables right in the debugger. It doesn't care whether the notes there or not. And you could think of a bunch of other cool uses too, such as is theming based on selectors. Progressive enhancement using Calc and CSS variables work in SVG as well, so your options are, you know, really, Limitless. So what's next with CSS variables? We could now do many things that, that mobile app developers already can do, such as constraint layouts, which is laying things out based on where other things are.

[29:00] Or saying, Hey, we need this. At least 20 pixels from the. Right, and other things such as physics, modeling, choreography, making animations happen, together in sequence. And observables also play nice with canvas and WEDG. So what this means is that when you do animations in CSS, you could have those same values dispatched to both canvas. WEBG. Anything else that could subscribe to observables. Which, by the way, there's a lot of things, it's just JavaScript.

[30:00] So this all happened based on me asking, what if I'm not telling you to do this? I'm telling you that. This is just, you know, something that you could think about and something that you could experiment with. Because we all like experimenting. And that's, you know, one of the great reasons that, you know, we do what we do. So, thank you, JS Comp Iceland. It's all the time I have and I'm David Kpano on everywhere.

[30:00] If you want to talk to me, thank you.
