Review
In part 1 we built a basic Next.js site with some pages, and a navigation bar, but it doesn't look like much yet. In part 2 we will explore the different styling options and how to implement them.
Layout Component
Before we apply any styles directly to the existing elements, we can do some refactoring that will save us time in the long run. By using the Next Layout Component, we can share styles, or a general layout, across many pages.
Add a layout.js file to your components folder
And this code
export default function Layout({ children }) {
return (
<div>
<p>layout</p>
{children}
</div>
)
}
Then import Layout into the Posts page, and change the wrapper of the component from a fragment, to a component.
import Navbar from '../components/navbar.js'
import Layout from '../components/layout'
export default function Posts(){
return(
<Layout>
<Navbar />
<div>
<h1>Posts</h1>
</div>
</Layout>
)
}
You should see the word layout at the top of your posts page now. We can utilize the layout component to drop our Navbar component into each page in a cleaner way.
If we alter layout.js looks like this
import Navbar from '../components/navbar.js'
export default function Layout({ children }) {
return (
<div>
<Navbar />
{children}
</div>
)
}
And Post.js
import Layout from '../components/layout'
export default function Posts(){
return(
<Layout>
<div>
<h1>Posts</h1>
</div>
</Layout>
)
}
The post page remains the same, but we are passing our Navbar through our layout wrapper now. Let’s change the other two pages as well.
Let’s add a footer component as well. Creating a /components/footer.js file and some simple code
export default function Footer(){
return (
<footer>
<p>Footer action</p>
</footer>
)
}
By adding the footer to the layout component which wraps our other pages, we will now have a footer on every page as well.
import Navbar from '../components/navbar.js'
import Footer from './footer.js'
export default function Layout({ children }) {
return (
<div>
<Navbar />
{children}
<Footer />
</div>
)
}
We’re ready to scale up now, through our layout component we have added the navbar and footer to each page.
Global CSS
The first place to start styling would be one main CSS file. In Next.js the styles folder contains the a globals.css file for anytime you want to apply styling to every page. Let's add a hover feature to apply to any links on the page.
a:hover {
text-decoration: underline;
}
Add this block and you’ll have hover functionality on all links now.
The global css file imports to the rest of our project through the pages/_app.js file.
CSS Modules
The first option for adding component level CSS is through CSS modules. There are lots of advantages to using modules, and some frustrations as well, it's best to build some files to see for yourself.
Create a components/layout.module.css file adding this code to it
.container {
width: 90vw;
padding: 0 1vmin;
margin: 5vh auto;
}
Then we will import the new module into our Layout component as 'style' and apply the 'container' class to the div.
import Navbar from '../components/navbar.js'
import styles from './layout.module.css'
export default function Layout({ children }) {
return (
<div className={styles.container}>
<Navbar />
{children}
</div>
)
}
Now, if you take a look at the HTML in your browser’s devtools, you’ll notice that the div rendered by the Layout component has a class name that looks like layout_container__...:
CSS modules automatically generate unique class names. You can avoid any class name collisions by keeping class names scoped locally. An added feature is Next.js's code splitting. Next will only load the needed CSS for each page, which keeps everything running quickly.
Now let’s create a style module for the navbar
Creating a components/navbar.module.css file with the following code
.header {
display: flex;
justify-content: space-around;
}
.navlink {
color: #006000;
}
Importing the navbar.module.css to our navbar component and styling the component with it. We can style our links with a separate class name from the header coming from the same file now.
import Link from 'next/link'
import style from './navbar.module.css'
export default function Navbar(){
return(
<header className={style.header}>
<Link href="/"><a className={style.navlink}>Home</a></Link>
<Link href="/posts"><a className={style.navlink}>Posts</a></Link>
<Link href="/about"><a className={style.navlink}>About</a></Link>
</header>
)
}
That's the basics of CSS modules. Personally I find modules clunky, and adding multiple class names using interpolation
className={`${styles.description} ${styles.yellow}`}
Just rubs me the wrong way. So let’s investigate more options.
Styled-jsx
Trying a different route with CSS, we have the Styled JSX framework. The style defined for a component only affects that component and nothing else — not even its children!
Next.js includes Styled JSX by default, so getting started is as simple as adding a
'style jsx' tag into an existing React element and writing CSS inside of it.
Let's experiement with the post.js file
import Head from 'next/head'
import Layout from '../components/layout'
export default function Posts(){
return(
<Layout>
<Head>
<title>Posts</title>
</Head>
<div>
<h1>Posts</h1>
</div>
<style jsx>{`
div {
background: #00a000;
}
h1 {
color: #ffffff;
text-align: center;
}
}
`}</style>
</Layout>
)
}
Notice we are using generic selectors, the styles don't affect the same elements or class names in other components. Styled JSX are scoped to this component only (by applying additional unique class names to styled elements).
Check out the unique class name applied to div we styled:
The downside of Styled JSX is by using a template string to write CSS rules, you lose IDE and code editor assistance to write them, and commenting code out becomes difficult.
If Styled JSX intrigues you, there's lots more you can do with it, including adding global styles inside any component file.
Checkout out Next's documentation for more information.
Adding SASS
I'm a SASS fan, and luckily Next.js integrates with SASS very easily. Let's switch all this over to SCSS files now, because that's sort of the point of this article. Quick side note - I'm using Live Sass Compiler which makes all things SASS a breeze and I highly, highly recommend it. Seriously.
First install SASS
yarn add sass
If we switch our components/navbar.module.css file to components.navbar.scss and compile, we have SASS working for us, but now the files are piling up inside our components folder
Switching the other CSS files to SASS will triple my files, so let’s refactor this.
First, we will create a styles/main.scss - this will import all the other SCSS files so we only compile this one file, and keep everything organized. I will copy all the data from styles/global.css and paste it inside. Then in pages/_app.js we will switch our import from
import '../styles/globals.css'
To
import '../styles/main.css'
Once we compile ( using the live sass compilier ) , that will watch our main.scss file from now on and we don’t have to worry.
Now let’s move our navbar.module.css and layout.module.css files into our styles folder
Rename navbar.module.css to _navbar.scss and rename layout.module.css to _layout.scss
Next, import both into main.scss
@import 'navbar';
@import 'layout';
Change classNames inside our navbar.js file
import Link from 'next/link'
export default function Navbar(){
return(
<header className='header'>
<Link href="/"><a className='navlink'>Home</a></Link>
<Link href="/posts"><a className='navlink'>Posts</a></Link>
<Link href="/about"><a className='navlink'>About</a></Link>
</header>
)
}
By creating a corresponding SCSS file for each component, we've developed a very scalable file structure going forward. And by importing each component SCSS file into the main.scss file, we only have to compile once, and we can sit back and enjoy all the beauty of styling with SASS.
Conclusion
That's a lot of reorganizing files, but for me I have a firm understanding of when I why I would use each of these styling options. I think Styled JSX is a great place to start when building an app, but as things scale up, migrating to SASS and moving everything to the style folder appears to be the best option for myself.
As always, don't take my word for any of this. There's some amazing tutorials out there, and Next.js's own documentation is stellar.
Top comments (0)