ProNextJS
    lesson

    Create a Layout with CSS Modules

    Jack HerringtonJack Herrington

    In this section of the tutorial, we're going to focus on CSS modules. CSS modules are baked into Next.js, and if you just want to do CSS, CSS modules are the way to do it.

    A Preview of the Final Result

    As we go through this example, this is what we're going to be looking for in terms of the final result:

    Polypane screenshot

    We can see that we've got a dark mode view of both the mobile size and the desktop size. A commercial application called Polypane is used here to look at multiple sizes simultaneously, as well as toggling dark mode. However, you can use any browser you like.

    Let's start working on the CSS that gets us to the final result.

    Starting the Development Server

    Start the development server by running:

    pnpm dev
    

    You should see the completely unstyled application:

    Unstyled application

    Back in VS Code, we'll start building out the CSS layout.

    Constraining the Page Width

    The first thing we want to do is constrain the width of the page and then move it in from the sides. We want to set a boundary of 960 pixels and then adjust it from the sides.

    To do that, we're going to create a new file inside of src/app called page.module.css to specify a CSS module. Anything inside of this file is going to be CSS and will be usable as a CSS module.

    Inside of the file, we'll create a CSS class like you normally would in any CSS file. We'll call it main:

    /* inside of page.module.css */
    .main {
      max-width: 960px;
      margin: 0 auto;
    }
    

    Now in the page.tsx file, we'll import the styles:

    // inside page.tsx
    
    import styles from './page.module.css';
    

    Then, to use the main class from the styles, we simply use className and set it to styles.main:

    // inside the Home component
    <main className={styles.main}>
    

    The underlying CSS modules mechanism baked into Next.js is going to take that CSS from the CSS file, then statically generate it into a CSS file that is then associated with the application.

    After saving our work, we can see in Polypane that it brought the content in from the sides a little bit. The effect is subtle, but it's there.

    Polypane preview with constrained widths

    Looking in browser DevTools, notice how class names include a hash similar to this:

    <body class="__className_aaf875">
    

    The cool thing about CSS modules is that the generated CSS gives you good encapsulation, meaning you can have the same class name in multiple components without collisions.

    Creating a Three-Column Layout

    The next thing to do is create a three-column layout for the desktop mode. We're going to use Flexbox for that, and main is going to control that as well.

    Back in the page.module.css file, set the display mode to flex:

    .main {
      max-width: 960px;
      margin: 0 auto;
      display: flex;
    }
    

    Now we've got a Flexbox, it's a flex row, but it's continuing on ad infinitum:

    flex row

    That's not good. We need to tell it to wrap when it reaches the edge of the container. To do that, we specify flex-wrap and set the mode to wrap:

    .main {
      max-width: 960px;
      margin: 0 auto;
      display: flex;
      flex-wrap: wrap;
    }
    

    After saving, it's starting to look like a decent layout:

    The wrapped cards

    Styling the Product Card

    The next thing to do is start styling the card.

    Inside of the page.module.css file we'll add a card class and some media queries:

    .card {
      padding: 0.2rem;
    }
    
    @media screen and (max-width: 768px) {
      .card {
        width: 100%;
      }
    }
    
    @media screen and (min-width: 768px) {
      .card {
        width: 33%;
      }
    }
    

    Your task is to apply the card class to the <div> that wraps the product card in the Home component in the page.tsx.

    In the next lesson, we'll pick up from there.

    Transcript

    In this section of the tutorial, we're going to focus on CSS modules. Now, CSS modules are baked into Next.js, and if you just want to do CSS, CSS modules are the way to do it. Now, as we go through this example, this is what we're going to be looking for in terms of the final result here. We

    can see that we've got a dark mode view of both the mobile size and also the desktop size. I'm using an application called polypane to do this. You don't have to use polypane. It is a commercial product and it does allow me to go and look at multiple sizes simultaneously. It just makes it a little bit

    easier to do these videos. You can use Safari, Chrome, Arc, whatever you want. Another cool feature of Polypaint is you can go and quickly move between light and dark mode. That is another test we're going to want. So this is basically showing us pretty much everything we want on 1 display. It's got a mobile size, it's got the desktop size,

    and we can go and switch between light and dark mode. We're going to work through all of the CSS step by step so that you'll see how all of the CSS works in addition to understanding how CSS modules work. All right, let's jump into our starter application and start building out our CSS modules version. First, I'm going to run the development mode from the starter and we'll see

    what we get. All right, so we've got our completely unstyled application here. Let's go back in the application and start building out the CSS layout. The first thing we want to do is constrain the width of the page and then move it in from the side. So we want to set a boundary of 960 pixels and then just fight in from the side. So what we're going to do is

    we're going to create a new file in here called page.module.css. And that's how you specify a CSS module. Anything inside of this file is going to be CSS. It's going to be usable as a CSS module. In here, I'm just going to create a CSS class like you

    normally would in any CSS file. So we'll call that, for example, main, that'll be the name of our class. We'll go over to our page file and we'll just import that as styles. Styles is generally what folks use for this. You can use any name that you want. Then to

    use main from that styles, we simply use class name and then do styles.main. The underlying CSS modules mechanism baked into Next.js is going to take that CSS that's in the CSS file, it's going to statically generate that into a CSS file that is

    then associated with the application. So it's build time deployed essentially, and It's going to create a class name that we then set to the class name on main. So let's give it a try, hit save. We can see over here in polypane, we brought it in from the sides a little bit. The effect is subtle, but it's

    there. And then let's take a look at this particular element. So we look at the top at main, we can see that we have page, main, and then just this hash value. So the cool thing that CSS modules is doing is giving you good encapsulation, meaning that you can have the same class name in multiple components. It's never going to collide

    because it's going to go and do that name encapsulation for you. So that's really nice. Now, the next thing to do is in the desktop mode, we want a three-column layout. So we're going to use a Flexbox for that, and main is going to control that as well. So go back over to our page model CSS, and we'll set the display mode to flex. Well, now I've

    got a Flexbox, it's a flex row, but it's now just continuing on ad infinitum over there. So that's not good. What we need to do is tell it to wrap when it reaches the edge of the container. To do that, we specify flex wrap and we set the mode to wrap. So let's hit save. There we go. It's starting to look

    like a decent layout. Next thing we're going to do is we're going to start styling the card. So I'm going to add the styles to that module, and I'm going to stop here. And what I'm going to allow you to do is take this card class from page module CSS

    and apply it to this div. So the div that wraps that product card. I want you to try that for yourself. The code is over in the partials directory. You can pick it up from where I left off, and then I'll see you in the next video, and we'll finish off this application.