![](/style/images/good.png)
![](/style/images/bad.png)
How To Render CSS on React App Servers
source link: https://www.digitalocean.com/community/tutorials/rendering-css-on-servers-for-nextjs-react-apps
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Introduction
Next.js (React) and Nuxt.js (Vue) help streamline the process of rendering your app views to a server.
You will still need a solution for rendering CSS in your React components in a way that accommodates development. You will also need a solution for rendering CSS on the server so the styles are available.
In this article, we will go over the challenges of rendering CSS and then use styled-components
and styled-jsx
on the server in a Next.js project.
Prerequisites
To complete this tutorial, you’ll need:
- A local development environment for Node.js. Follow How to Install Node.js and Create a Local Development Environment.
This tutorial was verified with Node v16.2.0, npm
v7.14.0, react
v17.0.2, react-dom
v17.0.2, next
v10.2.3, and styled-compnents
v5.3.0.
Understanding Style Patterns in React
There are few common ways to write CSS in React which all work. Depending on your situation, you are applying styles to your React app in one of the following ways:
Global Styles
Global styles are the pattern of including local or content delivery network (CDN) hosted stylesheets.
Here is an example:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/7.0.0/normalize.css" />
This is the less preferred styling pattern because it does not encourage component reuse. It also does not encourage style composition.
These CSS rules are not scoped directly to specific elements or components. There is a high likelihood of conflicts occurring when components interact in a way that was not anticipated through importing, nesting, or expanding.
However, there are cases like font inclusion and CSS resets and defaults where you could include styles globally.
Inline Styles
Inline styles are directly applied to DOM elements or React components using the React style
property. The implementation much like the HTML inline style
attribute but uses the JavaScript element.style
API.
Here is an example:
const titleStyle = {
fontSize: '4rem';
lineHeight: '1.6';
color: '#222';
}
<h1 style={titleStyle} {...props}>{props.children}<h1>
This pattern encourages style and component composition as well as reuse.
However, inline styles does not provide you with a way to handle hover of focus states with pseudo-classes and target pseudo-elements. For larger and complex projects, you may need a solution that is more robust.
Component Styles
Component styles encourage reuse and help you to compose styles and components better. You will need a utility or library to help you accomplish this. Style loaders, styled-components
, Glamor, etc. are examples of tools for supporting component styles.
styled-components
are a popular solution for implementing CSS-in-JS. They are inline component styles but with more power to do things like complex (pseudo) selection, nesting, etc.
Step 1 – Setting Up the Project
To get started, open your terminal and create a new folder for your project:
mkdir css-ssr-next-example
Next, change into the new project directory:
cd css-ssr-next-example
Then run the following command to initialize it:
npm init -y
This will create a package.json
file which you will use to track dependencies.
Then, install Next.js, React, and React DOM:
npm install [email protected] [email protected] react-dom17.0.2
At this point, you will have a new project with Next.js, React, and React DOM.
Note: Since publication, a more modern approach to creating a Next.js project could utilize create-next-app
.
Now, update the package.json
to start a Next.js app with dev
script:
{
"name": "css-ssr-next-example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "next"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"next": "^10.2.3",
"react": "^17.0.2",
"react-dom": "^17.0.2"
}
}
Then, create a pages
directory:
mkdir pages
In this directory, add an index.js
file with the following content:
import React from 'react';
const Index = () => <h1>Hi, new Next.js project</h1>;
export default Index;
Now run the dev
script to start the server:
npm run dev
If you open localhost:3000
in a web browser, you will observe:
Output
Hi, new Next.js project
First, use the Head
component from Next to normalize styles using normalize.css
:
import React from 'react';
import Head from 'next/head';
const Index = () =>
<div>
<Head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/7.0.0/normalize.css" />
<link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet" />
</Head>
<h1>Hi, new Next.js project</h1>
</div>;
export default Index;
Next, create a static
folder on the root of your Next.js project:
mkdir static
In this directory, add a base.css
file with the following CSS content:
body {
font-family: 'Raleway', sans-serif;
color: #222;
}
Import the base.css
file in the Index page:
// ...
<Head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/7.0.0/normalize.css" />
<link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet" />
<link rel="stylesheet" href="/static/base.css" />
</Head>
// ...
In the browser, the font will visibly change from the default font to Raleway.
At this point, you have a Next.js project with global styles.
Step 2 – Using Styled Components
Let’s use the styled-components
library to style components.
First, install styled-components
:
npm install [email protected]
Next, create a components
directory:
mkdir components
In this directory, add a Button.js
file and update the file with the following:
import React from 'react';
import styled from 'styled-components';
const ButtonBase = (props) => <button {...props}>{props.children}</button>
const Button = styled(ButtonBase)`
/* Rectangle 2: */
background: #0077E2;
box-shadow: 0 2px 7px 0 rgba(120,137,149,0.25);
border-radius: 3px;
text-transform: uppercase;
padding: 10px;
color: #fff;
border: #0077E2;
`
export default Button;
We are using styled-components
imported as styled
to style a Button
. ButtonBase
returns a skeleton of the button while Button
returns a component with a styled ButtonBase
.
Import and use the Button
component in the Index page:
import React from 'react';
import Head from 'next/head';
import Button from '../components/Button'
const Index = () => <div>
<Head>
....
</Head>
<h1>Hi, new Next.js project</h1>
<Button>Clicker</Button>
</div>;
export default Index;
Save the changes and observe the application in a browser. Underneath the text will be a new styled button.
However, after a hard refresh, the button is no longer styled as expected.
The button styles seem to be missing, but somehow, the base styles are intact. Use web developer tools to inspect the page source.
The content is rendered to the server, but it doesn’t show any style anywhere on the page relating to the button. On the other hand, as we can observe from the font styles that were applied, we know the external files were rendered to the server successfully.
So what went wrong with the component styles? Take a look at the console:
Output
Warning: Prop `className` did not match. Server: "sc-gtsrHT kbmjhF" Client: "sc-bdnxRM kbyRfM"
You can observe an error showing a miss-match in the class name. This is because, when you reload, content is first fetched from the server.
Unfortunately, styled-components
are not rendered to the server which makes them unavailable at that time.
Note: Since publication, styled-components
supports server-side rendering.
You can also refer to Next.js’s with-styled-components
example.
Let’s take a look at a solution.
Step 3 – Using Styled JSX
The team working on Next.js introduced a library called styled-jsx
to help control mitigate this problem. The library ensures that styles you write are rendered on the server as well as the browser and not just the browser alone.
It already comes bundled with Next.js, so you don’t need to install anything.
Revisit the Button
component and modify it to use styled-jsx
:
import React from 'react';
const Button = props => (
<button {...props}>
{props.children}
<style jsx>{`
background: #0077e2;
box-shadow: 0 2px 7px 0 rgba(120, 137, 149, 0.25);
border-radius: 3px;
text-transform: uppercase;
padding: 10px;
color: #fff;
border: #0077e2;
`}</style>
</button>
);
export default Button;
Before the closing tag of the root element in a component we want to style, you can create a style
element with the jsx
attribute. In the style
element, open a curly brace that contains template strings. The strings should be valid CSS styles and server as your component style.
You can also use selectors in styled-jsx
if your component is not composed of only one element:
import React from 'react';
const TitleAndButton = props => (<div {...props}>
<h1 className="title">Hi Title</h1>
<button>Clicker</button>
<style jsx>{`
h1.title {
color: #222
}
button {
background: #0077e2;
box-shadow: 0 2px 7px 0 rgba(120, 137, 149, 0.25);
border-radius: 3px;
text-transform: uppercase;
padding: 10px;
color: #fff;
border: #0077e2;
}
`}</style>
</div>);
export default TitleAndButton;
Now, you can import and use the TitleAndButton
component in the Index page. Both elements will be styled as expected.
Note: You can also refer to Next.js’s with-styled-jsx
example.
styled-jsx
is one approach to rendering styles to a server in Next.js projects.
Conclusion
In this article, you learned about the challenges of rendering CSS and then used styled-components
and styled-jsx
on the server in a Next.js project.
If you’d like to learn more about Next.js, try our Getting Started with Next.js tech talk, or check out our Next.js topic page for exercises and programming projects.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK