How to Model Animations Using Data Attributes
Watch on YouTube (Prismic)
What is this talk about?
When creating animations, data attributes are useful because they are flexible and easy to manipulate with JavaScript. (From the video description.)
“It could be very tough to discern between classes for describing states and classes for describing style, which is what classes are really meant for.”
“Or you might have an error class, or you might have a success class, in order to maybe change the color of a button or something.”
From the opening of the conversation.
Key takeaways
- Can you explain it. - so a finite state machine takes that idea of only one state at a time, and it expands a little bit more. 3:00
- Even on the off chance that we have both loading and success, that selector will still never be matched because we're looking for it to exactly be loading. - Okay, nice. 5:00
- I also wrote a library called XState, which helps you with more advanced finite state machines and statecharts, which are nested hierarchical state machines, they're a little bit more advanced. 11:00
Quoted from the transcript. Conversations include other speakers.
Full transcript
From the uploaded captions. Technical terms were normalized; some errors remain. 2,148 words.
0:00 Introduction
- so in the last video, we talked about the flip technique, how can you use it to model animations that would run on the GPU so it will be much faster, and you'll have your 60 frames, which is important to have that fluid animation. And now I would like to talk about something else, which is, how can you basically model your animation? What is the flow? For instance, if I think about animations, that you would probably change some CSS classes you put the class, remove another, and then you get your animation going, but do you have a preferred way of modeling the flow of animation? - so your way I'd like to describe as juggling classes because you have to remember, okay we have to remove this class, and add this class, and these classes need to be on here and this class needs to be on the body.
It could be very tough to discern between classes for describing states and classes for describing style, which is what classes are really meant for. So what I'd like to use instead is data attributes. So I would have a data state attribute that describes what state am I in. For example, I could be in idle, loading, success, error, and I could create animations between those states. - so wait, you're just saying it's very interesting. You're saying classes are for style, not for state. And you're not for using classes, at least for avoiding using classes as for state. For indicating some kind of state of the element or of the component. - exactly. And if you think about it, I used to do this all the time, but you might have a loading class, right? Or you might have an error class, or you might have a success class, in order to maybe change the color of a button or something.
But if you think about it, what if you have both a loading and a success class? That makes no sense. And so you might think as a developer, that should be impossible. But how can you guarantee that it's going to be impossible? Because we've seen many examples in the wild where you might have a loading spinner, and an error showing. And it's like, why-- - it's the quantum state? - exactly. It's a quantum state. You don't know, is it loading still? Did it fail? What happened? - and that bit creates a lot of bugs in the interface, where there's these two states showing together and then it becomes not understandable for the user. - yeah, exactly. - so you're saying you'd rather use a data state attribute? - yeah. So data attributes are very useful because they're very flexible. You could define your own data attributes. And they're also very easy to manipulate in JavaScript, if you have the node reference of some element, it's just element dot dataset dot and then whatever you data attribute name is. - and you can have different ones, that's why you don't have to use the same data attribute for a lot of things.
If you want state, you put it in a state data attribute and that's it. - right. And when you do that, now your state is only in one place. And so instead of figuring out which of my class names describes the state, I know that this data state attribute can only be one thing at a time. - one thing at a time, so you can't have both states at the same time. - right. - because you're always assigning a new value. You're not saying add that and remove that. That's the thing. - yeah, and that's what the idea behind finite state machines too. - what is it? Can you explain it. - so a finite state machine takes that idea of only one state at a time, and it expands a little bit more. So if you have a idle, loading, success, error state, those are the only states you could have, let's say in some application, but you also need to define transitions.
How one state moves to the other state. For example, you can't go from idle to success, because you need to start loading the data first, and then you need to go from loading to success. And so those arrows are called transitions, and they're described by events, such as, when you're in the idle state, and a fetch event happens, now you're in the loading state. - Okay, so basically, because it might seem scary when, you're starting talking about finite state machine and we're still here talking about CSS and animation, we didn't go anywhere else, we're still talking about that. But you're saying, by using that pattern, and defining the different states, you're saying we should define the different states, and define the possible transition, only the possible transition. So basically, you said you can't go from the first to the fourth right away. If it doesn't make sense, you should not define any transition that moves you from the first to the last state. - right. - you only define the possible state transitions, right?
And so that would be the responsibility of JavaScript. But also, you could have it in CSS where you just don't define any animation or any styles for one of those impossible states. - right, so they don't even exist, and you're sure that they're not going to happen? - right. - unlike if you're using the style attribute as the class. Because you might miss-- - you might have both. - but in the other case, you're controlling the states and the state transitions. - Mm-hmm, yeah. And that's why data attribute selectors are very helpful in this case, because you could say, when my data state is exactly equal to loading. So even on the off chance that we have both loading and success, that selector will still never be matched because we're looking for it to exactly be loading. - Okay, nice. So you also have a condition, if it's on that exact state, then I'm going to do that, nice.
So can you describe maybe again, an example. And how can you use a finite state machine for animating that example. - so one of my favorite examples is the one I just said, where it's a loading animation, where let's say you have a button where you click it, something asynchronous needs to happen, like you fetch data, or you submit data. And so the button will now have a loading state. And so it might be opacity 0.5, or it might sort of pulse or animate in some sort of way. And then you want some success state too. So you might animate to a green color, or have a little animation for success. - like a check or something. - yeah, exactly. - so now, how many states do you have in this situation? - so in that situation, you would have three states, but now if you need to add another, you would have four states and you'll define the transitions between those states. - and in using that kind of pattern, you can end up having more than these only three states, you can have as many as you want, as long as you define them right. - exactly, and that's the whole idea behind finite state machines.
7:00 You could pan down and go to that bigger view…
It's that, the finite part of this important. All that means is, there's not an infinite number of states you could have, for example, you're not going to describe something like the username or some count, another one of those infinite values. You're defining very strict states for what your application can be in. - can you give an example of a complex animation where you used that, and it helped you manage complexity of that component? - yeah, there was one dribble that I did where it was basically a selection of four items, and you could either tap it, or you could scroll up or pan up with your finger, and so that would smoothly transition to one view, and then you could pan up again and that would smoothly transition to a different view.
But then if you panned up, nothing should happen because there's no other view. But you could pan down and go to that bigger view, and then you could pan down again, and it goes to those navigation items again. You could swipe left, swipe right. - Oh, that's a lot of states. - yeah. - and without having a framework or a way, I mean, that pattern, you can have maybe too many animations, and then you can't exactly control that everything's going to be correct. - right, or you might have glitches, or you might be juggling Boolean variables, is expanded or is shrunken, and then you now have so many different impossible states that you have to deal with. - and also in transition, when the state didn't finish transitioning, it's impossible to gesture or to trigger the next animation because you have that check.
If it's not already in the loaded, you can't trigger the new animation. That also keeps you from having these kind of weird effects where you're trying to do an action, whereas the animation is not even done, right? - exactly. That's actually a really good example. For example, if you're moving from the bigger view to the smaller view, and I'll have a link to this animation. But if you move left or right, it should change whatever screen that you're on. So it should swipe left swipe right. But if you move up, you don't want moving left or right to do anything. You want it to, no matter if you move left or right, it should just go to the next navigation screen. - and that's guaranteed by the by using that - exactly, it's guaranteed naturally, because you could say when we're in a state, the only transitions that could happen are this event or this event.
So if any other event happens, it says we don't handle it, so nothing happens. - yeah, nothing happens. I guess also Accordion are also one good example of that, because sometimes you don't want to open two in the same time, you only want to have one open.
10:00 I have one on 24 ways about styling and designing with…
And that's the same thing. You can handle with that pattern, so that you don't have this impossible state to happen. - exactly, and so that's why I use that pattern a lot when designing and implementing modals on websites, for instance because-- - Oh, yeah, it's very complex. - I'm sure you've seen a website where it showed two modals at the same time. It looks weird, it's like, why is that happening? And so instead, you want to define the finite states where it's like, all right, in this state, only this modal is showing and it's impossible for the other one to show. Maybe it'll show after it closes or something like that. But modal is a state too, where I've also experienced websites where even if the modal was showing, there was-- - the buttons, yeah (Sadek laughs) - there was still a way to click the other buttons. - yeah, and so that's what finite state machines help with. They say when we're in the state, only focus on the modal, nothing else should happen. - and it might even happen accidentally.
It's not that you're trying to play with the background, but just the mouse end up somewhere else and you see things are moving. - Oh, yeah, or if you press tab a few too many times, then it goes to some button. - Ah yeah, that, right. - we can even avoid the tab effect. - exactly, and we run into these issues all the time. And that's because people aren't designing with these finite states in mind. - nice, so now, did you write an article about it? Or something that we can reference, so people can dig deeper into it? - I wrote plenty of articles about it. I have one on 24 ways about styling and designing with keeping finite state machines in mind. And I also wrote a library called XState, which helps you with more advanced finite state machines and statecharts, which are nested hierarchical state machines, they're a little bit more advanced. For most use cases, you would only need a finite state machine, and you don't even need a library for it. - right, and that is a nice thing.
You can do it by yourself. - you can. - we'll link to all of these in the description of the video, thank you very much. - thank you
Related talks
-
Crafting Stateful Styles with State Machines
CSSConf Budapest 2019. 28:51, 9.9K views -
Behind the Illusions: Impossibly High-Performance Layout Animations
CSSConf Australia, 2018. 23:51, 3.8K views -
The (Finite) State of Reactive Animations
RxJS Live (2019). 30:30, 3K views -
Crafting Stateful Styles (dotCSS 2019)
dotCSS 2019 (Paris). 18:25, 1.9K views