DEV Community

Cover image for Styling with Next.js
Oscar Luna
Oscar Luna

Posted on • Updated on

Styling with Next.js

Styling with Next.js

Welcome back! Today I’m going to break down the options made available to us when styling our React components with Next.js. There’s very few approaches Next can’t use for this, so it’s important to understand the mechanics of each. This way you’ll have a clear understanding as to why your chosen styling approach is optimal for your web application, whether it’s an external library, theming, or inline styling. I’m going to start this series off with what’s already available with Next.js, which is Styled-JSX. Let’s dive right in!

Styled JSX

Next.js comes with its own CSS feature styled-jsx right out of the box. With this feature you can write your CSS styles right into your JSX code using a built-in <style> component. Styled JSX requires no additional libraries or preprocessors to install. We simply create the style component and write our CSS selectors as we normally would in a CSS file.

...
return (
 <style jsx>{`
   body {
     width: 100vw;
     height: 100vh;
     }
`}</style>
)
Enter fullscreen mode Exit fullscreen mode

Specificity is a good practice when creating our selectors for our JSX elements. Styled-JSX handles specificity by limiting the scope of our styles to the rendered JSX elements. This avoids any problems with your code’s scope, such as duplicate stylings. We can also add a global attribute to the <style> component at the top level of our application for global styles.

...
<style global jsx>{`
  html {
    display: inline-block;
  }
`}</style>
)
}
Enter fullscreen mode Exit fullscreen mode

If we need to render our styles on the server side, Styled-JSX has two helper functions to expose a style sheet to the rendered HTML called flush() and flushHTML(). The first function flush() generates an array of React.element, while flushHTML() exposes the array to the rendered HTML elements.

//flush example
...
export default (req, res) => {
  const app = ReactDOM.renderToString(<App />)
  const styles = flush()
  const html = ReactDOM.renderToStaticMarkup(<html>
    <head>{ styles }</head>
    <body>
      <div id="root" dangerouslySetInnerHTML={{__html: app}} />
    </body>
  </html>)
  res.end('<!doctype html>' + html)
}

//flushHTML example

export default (req, res) => {
  const app = ReactDOM.renderToString(<App />)
  const styles = flushToHTML()
  const html = `<!doctype html>
    <html>
      <head>${styles}</head>
      <body>
        <div id="root">${app}</div>
      </body>
    </html>`
  res.end(html)
}

Enter fullscreen mode Exit fullscreen mode

Alternatively we can also import the styled-jsx/css library to define styles outside of the render method while maintaining the scope of our selectors using the provided css, css.global, and ‘css.resolvetags, as we would if usingstyled-components`.


const body = css.global
body { margin: 0; };
const button = css
button { width: 200px; height: 60px; };
const link = css.resolve
a { text-decoration: none; }`;

`

That’s it for now! Be on the lookout for my next post where I’ll be covering how to implement routing in Next.js. Until next time!


Top comments (1)

Collapse
 
allenarduino profile image
Allen Jones

Hi Oscar, thanks for your post. Is it a best practice to use styled-jsx ?