Check out a free preview of the full Introduction to Next.js course:
The "Adding CSS & Modules" Lesson is part of the full, Introduction to Next.js course featured in this preview video. Here's what you'd learn in this lesson:

Scott explains how to use modules written in CSS to add style to a Next.js application, and explains that CSS modules do not have a global scope and require a class name to function properly.

Get Unlimited Access Now

Transcript from the "Adding CSS & Modules" Lesson

[00:00:00]
>> So let's talk about one of my favorite parts, which is styling. I'm a really big, like, when it comes to writing code, I'm just all about experience, experience experience and making really good. I don't know feeling really good feeling experiences for users. And, a lot of it has to do with design.

[00:00:17] And so I know a lot of developers is like, CSS. Stuff like that for good reason, but me actually one of those weird people that like CSS and obsess about making things look, picture perfect. Like if when I was working at companies, I would spend half my time sitting next to the designers working with them to design the app, because that's just like what I like doing.

[00:00:36] But I'm by no means a designer. Don't ask me to design anything. I couldn't do it. But I can recognize good design. And I think that's kind of what our value is. So styling. If you use react which i'm hoping all you have, you could probably think of at least five ways to do styling in react right.

[00:00:56] And that's going to depend on how you build it right you got so many different flavors of CSS and JS. You have different ways of making CSS files and then Webpack and import them different ways like. Well, do you want a global do you want me to put them together?

[00:01:12] Do you want me to maybe add modules to them like, what do you want me to do? Is just so many ways to do styling and react. And I think the Next.js team was aware of that, right, so they're just like, you know what? We're gonna pick something that covers some use cases, and it works very well, and we're just gonna do that.

[00:01:28] And I think they did a really good job with the styling when it comes to Next.js. So let's talk about that. So like I said, they do have some conventions baked in, and they're pretty good by default. And they basically look like this. So yeah, let's talk about two different types of stylings first, right?

[00:01:44] So you have global styles, right? You have I need this CSS to be globally, inside of my application, it will have collisions. I don't really care. And that's because a good example of that. And maybe you're not writing that. But let's you download and you npm install a calendar component, and that calendar opponent says you got to import this CSS.

[00:02:07] That's a global styling, right? Hopefully no one's writing libraries like that anymore. If you aren't writing libraries like that, please don't write libraries where someone has to import CSS. It's just so many better ways and it really conflicts with their bill system. So don't do that, but, there's still so many libraries out there that do do that.

[00:02:23] So how do you get that into your app with Next.js. So Next.js is very specific about that. So the only way to include global CSS inside of your application, your Next.js application is inside of a special page called underscore app. Right, so I'm gonna show you what that is.

[00:02:44] So if I go to my pages, I can make a new file here called underscore app. Right. So before we get in here, I think this introduces another conversation. So this means that okay, there's a special page in this pages directory so that you know that would mean that like.

[00:03:02] Okay, you probably can't pick whatever name you want for your pages because Next.js is using specific names for specific pages. So if we were gonna make a route called underscore app here, this would like, it wouldn't pick it up, right? So you can't use whatever names you want, and there's other ones in here too, as well, but most of them start with underscore.

[00:03:21] So it's usually safe, hopefully you're not making. A route with an underscore in it for some reason, I don't know. If you are just pick something else, I don't know. But, yeah, underscore app is basically, allows us to hijack the route, the entry point to our Next.js application.

[00:03:38] This gets created for us for free by default. We never have to touch it unless we gotta make some global styling, right? So the way that works is you could look here. At the end of the day, you just gotta export a function here, you're gonna get this component here, which is gonna be a page.

[00:03:55] So here's a page at any given time, this is a page and then it prompts to that page. So you just return it, this is basically what Next.js is doing under the hood. They're doing this for you automatically. So, you don't have to do it yourself right so you could copy this.

[00:04:09] You could paste this and obviously you need to import react. Right? And this is what happens for you automatically. So just by adding this I actually don't get any benefit. But the reason I have to add this file is because I can't actually add any global CSS in any other file inside of Next.js, for better or for worse other than this file.

[00:04:33] So if I had that button or that calendar and I needed some CSS for it, I would have to do it here. It would have to be calendar, whatever that thing is for that calendar it would have to be here. You can't do it anywhere else if you try to import this CSS in a component.

[00:04:51] Or anything that's not, or even in a page, anything, that's not this underscore app, you're gonna get an error from Next.js that says, you can't do that. And we can test that. Right. So I can go and I'm gonna go to source and I'm gonna make a new file.

[00:05:03] I'm just gonna call it styles dot CSS, and I'll add some styles here. Like that right? And then what I'm gonna do is I'm just gonna import that in my index page and let's see what happens. So I'm gonna say imports, Source slash style dot CSS. All right, so let's see what happens if we try to do that, boom, like I said, you get this really nice, huge error.

[00:05:37] It immediately threw up. It was like, nope, not happening. Global CSS cannot be imported from files other than your custom app. Please move all global CSS imports to that, or convert it to CSS models, which is what we will be talking about next. So the reason they do that it has a lot to do with the bundling of the styles and how they treat the global styles to make sure they are loaded in properly.

[00:06:03] So it makes sense, but that can also be a headache. But I also realize that headache is mostly due because people are still making libraries. With global CSS exports, I don't know why they still do that. Don't do that. It's not a good experience. And you will almost never make global CSS.

[00:06:19] If you're the author of this application, you will most likely never do that. So it usually is always some NPM module that requires you to do that. So, yeah, that sucks. I'm at the point now where if I come across one of those models and I need it, I will literally just fork it.

[00:06:33] And make the CSS not to import and publish and NPM myself and use that one. That's how bad of a problem it is for me now, I like, fork mods up for like 10 modules a week. Now just doing stuff like that. So yeah, it's that big of a problem.

[00:06:47] All right. But if we do add that, oops, not this. But if we do add that CSS here to our custom app, so if I say source styles dot CSS here, hey, it works. It loaded up just fine, right? So yeah, global CSS and put it in your app component.

[00:07:10] Have a happy day. Hopefully you never have to do it. Now the part that you're actually going to be using is is a Next.js support for CSS modules. So if you've never heard of CSS modules, basically what they do is, they allow you to write your CSS the way you normally write it.

[00:07:30] But the way that it works during build time, every time you import that CSS file. Into a file, every single import is gonna dynamically create a class, a dynamic class just for that import. And it's gonna apply it for all the styles on that import. So even though you have the same CSS classes, and you might import the same file in many components.

[00:07:53] They're all gonna have their own scoped class in front of them, because it's unique to that import. That happens at build time. So that's how the scoping works with CSS modules. They just basically get a dynamic unique class associated with them per import. And Next.js gives us that for free.

[00:08:11] Because I remember when CSS modules first came out, like, five years ago or something like that. It was so hard to set up. It was ridiculous, setting it up with Webpack and all that stuff, and now you get it for free. We kind of take it for granted.

[00:08:25] So, how would you do CSS modules and where would you use them? So you can pretty much use CSS modules anywhere. Even the App.js, any page, any component, doesn't matter, it'll just work. So, the way a CSS models works is all you have to do is rename the file, so in this case, style dot CSS I will say styles.module.CSS.

[00:08:46] That's it. All I have to do is put the word module in. And this is gonna tell a Next.js, this is a CSS module. Cool. Got you. And this is now gonna allow you to import it in any file. And that CSS is gonna be scoped. To that file, so even if I import in many places, it won't collide, right and it won't collide with any of the global stuff.

[00:09:09] So now that I have this, I can go back to my page here. I could put that in there. And then I could say that module.CSS like that. Right. Yeah, and now it's just freaking out because I'm trying to do a body CSS modules doesn't allow you to do like pure selectors like that, right?

[00:09:30] So I need to just dot body, something like that. There we go. The reason i freaked out is because CSS modules needs a class name. In order to like put a dynamic class in front of, you can't do this. Cuz if you attach the body that's global, right?

[00:09:47] You're global now that's defeating the purpose of CSS module. So it's like, hey, you wanted modules but you're not doing modules. What are you doing? Go make some global CSS. And so that's why we got that error which is very helpful.