Getting Twind to work with Next.js (v10).
Ensure your project has the correct Twind dependencies:
npm install -D @twind/next twind
Create a twind.config.js
file at the root of your project, and add the following:
export default {
theme: {
extend: {
screens: {
standalone: { raw: '(display-mode:standalone)' },
},
},
},
};
Add some very simple Twind styles to a test page.
// pages/example.js
import Head from 'next/head';
import Image from 'next/image';
import { tw } from 'twind';
export default function Page() {
return (
<main
className={tw`h-screen bg-purple-400 flex items-center justify-center`}
>
<h1
className={tw`font-bold text(center 5xl white sm:gray-800 md:pink-700)`}
>
This is Twind!
</h1>
</main>
);
}
Fire up your Next.js app. These Twind styles should load.
You should see a lavendar purple page with large pink text saying "This is Twind!".
If this isn't working, you'll need to tinker to get the basics of Twind to work with your Next.js project.
If Twind is working, then move onto the next step.
At this point in time, you should have:
However, you may notice that you're experience a flash of unstyled content (FOUC) for production builds.
This is because Twind isn't being server-side rendered yet. We're going to do that now!
Previously, we've installed the necessary dependency to get this working, @twind/next
.
npm install -D @twind/next twind
On Twind's Next.js docs, they include instructions on setting up Twind with a custom Document component.
This is what you'll have to do.
Open (or create) a pages/_document.js
file in your Next.js project.
Add the following to ensure the exported Document
(class) is wrapped with withTwindDocument
and twindConfig
.
// pages/_document.js
import Document from 'next/document';
import withTwindDocument from '@twind/next/document';
import twindConfig from '../twind.config';
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx);
return { ...initialProps };
}
}
export default withTwindDocument(twindConfig, MyDocument);
Twind's instructions are missing the Document
import. Add this part in if your _document.js
file doesn't have it.
import Document from 'next/document';
Moment of truth...
You can actually do this without building Next.js for production and serving it.
In local development (running npm run dev
), when you view the source code, you should be able to see the (giant) style
tag with the various Tailwind styles inside.
<style id="__tw-v3yfpw">button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;margin:0...
If you can see it when viewing source, that means that SSR is working. The styles from Twind is extracting correctly and being injected into the document.
Simply put, it's looking at the HTML to figure out what classes the page needs, then injecting those classes.
All of this happens in pages/_document.js
.
CSS(-in-JS) and SSR work by examining the HTML that's being rendered on the page. They then cross match details (like classes) to pluck out the necessary styles needed to render those styles.
After getting all the classes, they'll "inject" all of those classes in a style
tag along with the page's original HTML (string
).
That's it! SSR CSS in a nutshell.
You can see some of these mechanics in Twind's Next.js integration as well as their shim file.