Check out a free preview of the full Professional CSS: Build a Website from Scratch course
The "Animating display: none" Lesson is part of the full, Professional CSS: Build a Website from Scratch course featured in this preview video. Here's what you'd learn in this lesson:
Kevin demonstrates how to animate elements that have a "display: none" property using CSS. He explains the limitations of animating the display property and introduces the new "transition-behavior: allow-discrete" property that allows for animating the display property. He also shows how to use the "@starting-style" property to define the starting styles for the animation.
Transcript from the "Animating display: none" Lesson
[00:00:00]
>> Kevin Powell: Another one of my absolute favorite new things in CSS, which is a perfect progressive enhancement, is that we can now animate to and from display none. This is something that we've long wanted and it was just impossible to do or you'd have to use JavaScript so you'd bring the element in with an opacity of zero and then once that was there then you'd add a class to it.
[00:00:19]
It wasn't fun. And it's actually relatively easy to do now. So the best case in this project, or the best thing I think, to work on for that, is with our mobile navigation. Because if we take a look at our mobile navigation, it goes in and out. Works it's fine but a lot of the time we have animations on these.
[00:00:38]
They slide in, they slide down. They fade in. There's different things we can do with it. So we'll start with a fading animation, but then we'll see how we can step it up from there, and you can play around with it a little bit and come up with some really fun things.
[00:00:49]
So for this would be in our components. The stuff for our primary navigation is here right now. And so this is my primary nav. No, that's not the primary nav. The primary navigation is right here. We only need to do this within our media query, cuz this is where we're playing with it.
[00:01:06]
So I'm gonna stick within this media query that's here right now. I do apologize. This is like a placeholder for nothing. But I think it didn't work. Sometimes when you have something extra in there, it fixes the syntax highlighting. Let me just try again, li.
>> Kevin Powell: It doesn't like that there's no selector there.
[00:01:32]
So I might do this just to fix the syntax highlighting so it looks a little bit better. It might break some stuff along the way, but we'll see what happens. Does it still work? Okay, so don't necessarily repeat this in your own code. I'm just doing it so the syntax highlighting looks a little nicer.
[00:01:48]
So we have our display none, that's perfect. And then we're going from the display none to this display block right here, display block when it comes in. The problem right now is if I came up on here and maybe wanted to fade in, so not only is it gonna be a display: none, but I'm going to put an opacity of 0 on here.
[00:02:09]
And then I'm gonna come all the way down for when it comes in. And I want this to have an opacity of 1. Nothing, that's fine, not expecting any difference. We can come back up here. I forgot that as well. That wouldn't have changed anything, though. And then I can go transition opacity.
[00:02:29]
Let's just say one second. It's way too slow, but let's say we did that, and you'd expect it to transition, but it doesn't. The reason CSS doesn't transition in this case is because display property is technically animatable, but it's considered a discrete animation. And a discrete animation is something that CSS can't really animate, because what's in between display none and display block, there's nothing that makes sense within those that range.
[00:02:55]
If you did it within a keyframes animation, what it would do is halfway between the two keyframes you've done. It's gonna switch from one to the other. So that's the discrete animation. It's letting the animation happen, but it's just flipping a switch if you're trying to transition something, and that item that you're transitioning has something that involve, is involved in a discretionary animation, or has is a discretionary animation.
[00:03:19]
Your transition just won't work at all. This was the traditional problem that we've had up until now. But luckily, we can actually come here and now say we're also gonna transition display one second. I wish we only had to do that. It's still not gonna work. But we only have one other thing.
[00:03:38]
I'm gonna take a new line. This is the new thing we can do transition,-behavior, and it's called allow-discrete. So anything that would have a discrete animation, it's saying, you know what? We know that it's there. We're gonna allow it, and it's opt in, or they've done this as an opt in, and the reason they're doing it as an opt in type of thing is just because there could be old websites that things were set up in a certain way.
[00:04:02]
And because of the way it worked, everything was fine. And if they change the default behavior, some animations or weird stuff might start happening. So instead of changing the default behavior, they're giving us a one line opt in. And it sort of works because you can see it fades out.
[00:04:18]
Doesn't fade in but it fades out halfway there, pretty good. It's already exciting that we can do that in one direction. What it's basically doing at this stage is when it goes from let's open it, because it's easier to understand. When we're here, we have display block, we have opacity of 1 and I'm saying I want to transition the opacity over one second, and I want to transition the display over one second.
[00:04:39]
Display doesn't really transition, though. So what it's doing is it's transitioning the opacity for one second. And when that one second is finished, it's instantly changing the display block just to get rid of it, and it goes to the display: none. So that's why when we go this way, it works without any problems.
[00:04:54]
When we're coming the other way on the animation, though, that type of thing can't work because we have to instantly change to display block at the very beginning. And as soon as it gets display block on it, it's rendering that on the page, and it's instantly jumping to the styles we have here.
[00:05:12]
Because these are both true. It never had that opacity of zero, because it's sort of that style never existed on that element cuz it was a display none. It didn't exist on the page. It's this weird sort of conundrum type thing that we've run into. So to help with that, we have another new property called @starting.style.
[00:05:31]
So it's another at property VS code still doesn't recognize it, but it works. And here you just put your starting styles on there. So my starting style is actually an opacity of 0. And so now it will fade out and it will fade in, because when it instantly switches that display to block, it's going okay, it's block.
[00:05:52]
But now I'm gonna start with an opacity of 0 instead of instantly just coming up to the styles that are here. There's one kind of strange thing I find with this entire thing is just wrapping your mind around the order that you have to put things in. You generally have your closed state or your exit state first, then you have your finished entrance state.
[00:06:14]
And then you have this like transition in from state at the end, if you bring this up here, it won't work and not just 'cause the syntax highlighting is broken, so when I open it, it's just opening instantly. The reason this is happening is the same reason that if you have, it's just the order CSS goes from top to bottom.
[00:06:33]
So it sees the opacity 0 as a starting style, but then it sees the opacity 1 and it just gets the opacity 1. This is the same as if you did a media query first, like we could do it here. Let's just say the, I don't know. We'll say site, we'll do primary navigation.
[00:06:50]
Primary, navigation, background, red, important, just to make sure it actually comes through. And then if I put a media query underneath this at media width is bigger than 200 pixels, so we know that it's gonna work. Background, green, important, and I probably should have nested that, or we'll just do .primarynavigation
>> Kevin Powell: That we're getting the green because it does this.
[00:07:31]
Then it goes, okay, this media query is overwriting it. But if I brought this media query here and I bring it above that, it's gonna become red, because this is if the width is greater than 200 but this is always. So then the red wins over the media query that we have there.
[00:07:47]
So it's the same thing with your starting style. The starting style gets disclaimed first, then it sees opacity one, it just assumes that's the always style for everything, and it doesn't win. So your starting style, despite it being the starting thing. Does have to be the last thing that's declared, which it takes a little bit of getting used to, but it's just what it is.
[00:08:12]
>> Kevin Powell: Now, there is one really nice advantage, and it feels a little bit weird, in a sense, that you have an opacity 0 here, and the opacity 0 here, and you need to have it in both places. But there's an advantage of having this starting style and that we actually need it even if it feels a little bit clunky at times.
[00:08:28]
And the reason that that has an advantage to it is because it actually enables a different entrance and exit animation if that's what you want. Because this is, let's do a quick one here. We're doing our opacity, our display, and let's add a third one to our list, where I'm also gonna do a translate of 1 second.
[00:08:51]
While I'm here, just really fast, the transition behavior allow-discrete, I'm doing it here. It could be included in the transition shorthand. I just find it easier to do my transitions and add that here, because then I know it's gonna get applied to everything, and I don't have to stress about it.
[00:09:07]
So yeah, that's just why I have it as a separate property. It is included as part of the shorthand if you want it, but I'm gonna do my translate right there. And this is when it's closed. So when my menu is closed, let's move it up. So to move it up would be a translate of I'm gonna get it wrong 01, 100% it's probably gonna go to the wrong place.
[00:09:26]
Yes, it did -100 and it will go up. So now, when I open it, we need it. When we open it, we need it to slide down, so I can come here and I can say the translate is a 00, so it will slide up and then it will appear.
[00:09:47]
That's kind of interesting, right? It's already two separate animations, and that's because our starting style, the only thing on it is the opacity. So I can have it slide up when it leaves, but when it enters, maybe I'm gonna do a translate of 100% and 0 this way.
[00:10:03]
So if I do that, when it enters, it's actually entering from the side. And when it leaves, it slides at the top. I actually prefer it the other way around. So I think I'll do a 0-100 here, and then all the way up here we can do this whoops we can do this as the 100, 0 and I just remembered looking at that this should be a negative.
[00:10:29]
And I think I did that wrong we'll find out slides out slides down there we go slides that way and then slides that way. Something fun you can definitely do lots of really fun, cool stuff with this with different entrance, exit animations, not just for navigations. It could be for if you have cards that you click and it adds, like a to do list item, you can have it transition in.
[00:10:49]
And then when you close that or finish that to do list item, it leaves in a different direction or has a different animation on it, all really easily
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops