Check out a free preview of the full Introduction to Gatsby, v2 course:
The "Add Scoped Styles with CSS Modules" Lesson is part of the full, Introduction to Gatsby, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Jason walks through indicating a CSS module to Gatsby, coding the CSS styling, and importing the newly coded scoped styles as if they were JavaScript classes. Once the module's class names are attached to elements in the layout, the site styling will update accordingly.

Get Unlimited Access Now

Transcript from the "Add Scoped Styles with CSS Modules" Lesson

[00:00:00]
>> Next, we want to actually style things up a little bit, we don't have, this header, it's kinda junky, just everything smashed on top of itself. If we want that to look like an actual header bar, we want the content to not be smashed against the side of the page.

[00:00:20] So let's style our layout. And for the layout styles, I want to be able to write the styles without fear of collision later on. So one of the hot topics in CSS, and one of the big frustrations that a lot of people run into when doing styling, is, how do you avoid really complex naming structures.

[00:00:43] Or just a lot of rules in the way that you write CSS without running into this problem where the cascade in CSS becomes a big foot gun? We don't want it to be a trap, right? We want it to be something where when you write styles, you can take advantage of the CSS cascade, you can just write CSS.

[00:01:02] And it's very powerful, it gives you a lot of opportunities, but it doesn't become cumbersome, right? CSS should be fun, and I think that by using CSS with a few guardrails, it can be fun. It doesn't need to be this thing that is terrifying and stressful and hard to scale and all this stuff, right?

[00:01:27] And so that's why in this workshop, we're actually just going to write CSS. There are a million options out there, you could introduce CSS and JS, one of the tools like Emotion. You could introduce Tailwind, or Chakra. Those are all good solutions, and if that's what your team wants to do, 100%, do it, they're great ways to handle styles.

[00:01:45] I like a less is more kind of approach, so I'm gonna be using CSS modules, which is not exactly a CSS spec, but it allows us to not add any additional libraries for writing our styles. I also really like CSS modules, because they're more or less built into all the frameworks now, so you can use CSS modules with Gatsby, with Next, with Knocks.

[00:02:11] There's a bunch of different frameworks out there now that will just give you out of the box support for CSS modules, which means you get to write CSS. You don't have to learn Less or Sass or Stylus or Tailwind, or Chakra or emotion or any of the CSS and JS stuff.

[00:02:26] You can just write the CSS you already know, import it as a module, and it just works, so let's do that. I'll show you how it works. So we created this one as global.css. For a scoped CSS or a CSS module, we just have to do module dot CSS.

[00:02:44] So by adding this layout.module.css, I have now indicated to Gatsby that I want to use this as a CSS module, so inside of it, I can just start writing CSS. So I wanna have some styles for the header. So I'm gonna use that black color for the background and then I want the regular color, needs to be high contrast for accessibility, so we'll make it white.

[00:03:08] I want to use display flex so that I can get the header link, the home link to be on one side and the nav to be on the other side, I want them to be spread. So I'm gonna use display: flex; and then justify-content: space-between. Which the way that I remember this is every time I look at the CSS rule, I think about that Dave Matthews' song, The Space Between, and it gets stuck in my head, now it gets to get stuck in your head too.

[00:03:38] So then we're gonna add a little bit of padding around the header, about 1 rem. If you're not familiar with REMs, REMs are the the original font size, so when we look at the global.css and I set font size of 18 here, now I've basically said 1 rem is 18 pix.

[00:03:59] And the reason I use REMs is that I can now make my whole layout relative to that base font size. It's a nice little pattern, makes my life easier and you don't have to stress about it now. So inside of this, I'm gonna use just regular old CSS selectors.

[00:04:17] I wanna get any link inside of the header and I want to make it whatever the color of the header is. I also want to make it inline-block so that we can apply some padding around it. And so we're gonna set the padding to be 0.5 rem and then I wanna take off the underline.

[00:04:41] But because I just took off the underline, that would cause an accessibility issue, if I didn't add something back. So we're gonna go to the focus and hover state, and we're going to say that when it's hovered, we're gonna set the background to be white, and the color to be black, all right.

[00:05:03] And then the last thing that I wanna do here is I just wanna set a little bit of space around the content. So we're gonna create a class called content, this will go on our main tag. And I want to give it a margin of 3 rem on the top and bottom, and auto on the left and right, that'll center it.

[00:05:20] And then I wanna put a max width of, we're gonna use a little trick that I like of using the character. So what this means is when you look at the legibility of text, one of the things that we found is that a line length has a bigger impact than the actual width.

[00:05:39] So, depending on the number of characters per line, you actually wanna adjust the width the screen. So 54 characters wide gives you a pretty legible reading for tracking of text. You can adjust this, there's really good research you can read on the way that works but I like this in CSS is kind of setting.

[00:05:59] Whatever we do with the font sizes, let's make sure that our line length is good and adjust the width accordingly, so that, I think that's good enough, let's stop there. So these are the styles that will give us a header and content but notice I use some pretty risky class names here, like .header, .content.

[00:06:23] As this codebase scales, there's a near 100% chance that somebody else would create a .content class. Unless we implemented some kind of naming scheme like BEM or something where you have to do the component name underscore underscore, content underscore, whatever. There's these tricky things you have to do to avoid naming collisions.

[00:06:47] But because we're using CSS modules, we don't have to care about that, we can not worry about that and instead just write class names that we like. Because the way that we're actually gonna use this is we are going to import it as if it was a JavaScript package.

[00:07:04] So down here in our our layout, I'm gonna import header and content from the module, so from styles and layout.module.css like they were just JavaScript classes or objects. And then I can use these as class names. So on my header, I'm gonna set a class name of header.

[00:07:30] And on my main, I'm gonna set a class name of content, all right? And once I have saved this, look at that, we've got ourselves a site, but here's what's really cool about these, let me make this a little bit bigger so we can see what's going on here.

[00:07:50] When I select this header, note that it's not using header as the class, it automatically generated all of that scoping for me. So that these styles are actually going to correctly respect inheritance. Now there's some things that I can do to make this hard on myself. I targeted every a inside of a header without any restrictions.

[00:08:20] So if we had a nav component and had a nav.module.css that had its own link styles, I can still get collisions, so you can still make this hard. There are things that you need to think about, I chose not to worry about that because this site is not gonna grow beyond the couple of pages we're making here.

[00:08:44] But it's a consideration, if you wanna be absolutely sure, instead of using header a, we probably would have wanted to do something like header link, right? It doesn't matter, you can do it whichever way you want. Using named classes for everything is probably the the safest solution. But if you are sure that your header is going to always have links that should always look the same, then you can make that choice.