Hi there!
I'm Arisa, a DevRel from this June living in Germany🇩🇪 (A big announcement is coming this June😏)
I have a free online programming learning community called Lilac, with free hands-on Frontend e-books👩💻
Who is this article for?
- Anyone wants to integrate dark mode🌘
- Anyone wants to integrate multiple themes
Step 1: Install TailwindCSS
$ yarn add tailwindcss
If you want to generate tailwind.config.js
file, run this👇
$ npx tailwindcss init
Step 2: Install gatsby-plugin-postcss
$ yarn add postcss gatsby-plugin-postcss
Make sure to add in gatsby-config.js
file too.
plugins: [`gatsby-plugin-postcss`]
Step 3: Create a postcss.config.js
file
Create a postcss.config.js
file in a root directory.
Add the configuration like below.
module.exports = () => ({
plugins: [require("tailwindcss")],
})
Step 4: Edit global styles, src/components/layout.css
Swap default styles to these 3 lines.
@tailwind base;
@tailwind components;
@tailwind utilities;
These are Tailwind directives to enable Tailwind styles.
Also, we can already add a dark theme and light theme at this point in the same file.
@tailwind base;
@tailwind components;
@tailwind utilities;
body.dark {
--primary: #111827;
--text-main: white;
}
body.light {
--primary: white;
--text-main: #111827;
}
We'll use those variables in tailwind.config.js
file.
module.exports = {
purge: [],
darkMode: 'class',
theme: {
extend: {
colors: {
primary: 'var(--primary)',
'text-main': 'var(--text-main)',
}
},
},
variants: {
extend: {},
},
plugins: [],
}
If your variable name contains a hyphen like ablve, make sure to set it as a string when you call it in a config file.
Camel case doesn't work in here.
Step 5: Test dark mode first
At this point, we don't have anything like a button or checkbox to trigger the change of the theme styles.
But not so fast.
We need to make sure first whether TailwindCSS is integrated or not by applying some styles.
Go to TailwindCSS documentation.
Let's apply something dark gray from what we can choose from their documentation.
import * as React from "react"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"
import Header from "./header"
import "./layout.css"
const Layout = ({ children }) => {
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
}
}
}
`)
return (
<div className="bg-gray-900 text-white">
<Header siteTitle={data.site.siteMetadata?.title || `Title`} />
<div
style={{
margin: `0 auto`,
maxWidth: 960,
padding: `0 1.0875rem 1.45rem`,
}}
>
<main>{children}</main>
<footer
style={{
marginTop: `2rem`,
}}
>
© {new Date().getFullYear()}, Built with
{` `}
<a href="https://www.gatsbyjs.com">Gatsby</a>
</footer>
</div>
</div>
)
}
Layout.propTypes = {
children: PropTypes.node.isRequired,
}
export default Layout
We can check in the browser by running the development mode.
$ yarn develop
We can confirm that TailwindCSS is working fine in our project💃
Let's rock more 😎
Step 6: Create a dark mode theme
Add a config in tailwind.config.js
module.exports = {
purge: [],
darkMode: 'class',// 👈 he's your guest
theme: {},
variants: {
extend: {},
},
plugins: [],
}
We're toggling a dark mode manually.
Here is what I followed from the documentation.
Step 7: Update class attribute in layout.js
We created a dark theme and a light theme.
Also, we configured that we'll manually toggle dark mode.
At this point, we can already apply the variables we prepared.
Open your layout.js
file.
You can only swap the class attribute values when we tested the dark theme to see TailwindCSS is enabled.
// same as previous code
return (
{/* 👇 use variables in here */}
<div className="theme-dark bg-primary text-text-main">
<Header siteTitle={data.site.siteMetadata?.title || `Title`} />
<div
style={{
margin: `0 auto`,
maxWidth: 960,
padding: `0 1.0875rem 1.45rem`,
}}
>
<main>{children}</main>
<footer
style={{
marginTop: `2rem`,
}}
>
© {new Date().getFullYear()}, Built with
{` `}
<a href="https://www.gatsbyjs.com">Gatsby</a>
</footer>
</div>
</div>
)
// same as previous code
Wondered where all these theme
, bg-
and text-
came from?
Those are all from tailwind.config.js
.
It's like a path to fetch data.
Step 8: Install gatsby-plugin-dark-mode
Gatsby made our life so much easier.
Simply, just install this plugin first.
$ yarn add gatsby-plugin-dark-mode
Of course, include it in gatsby-config.js
file as any other plugins.
plugins: [`gatsby-plugin-dark-mode`]
Step 9: Create a src/components/themeToggle.js
file
Create a themeToggle.js
in under the directory of src/components
.
Actually, all we need to do in here is just use the example from Gatsby's documentation.
import React from 'react'
import { ThemeToggler } from 'gatsby-plugin-dark-mode'
export default function ThemeToggle() {
return(
<ThemeToggler>
{({ theme, toggleTheme }) => {
if (theme == null) return null
return(
<label>
<input
type="checkbox"
onChange={e => toggleTheme(e.target.checked ? 'dark' : 'light')}
checked={theme === 'dark'}
/>{' '}
<span></span>
</label>
)}
}
</ThemeToggler>
)
}
💡 A note:
gatsby-plugin-dark-mode
had an issue that can't switch from dark mode to light mode in the first load of the page until clicking 3 times. Above is from the latest commit from this plugin but not yet in a latest release.
Then we'll import themeToggle component into the page or component we want to enable.
This time, I want to have in my header navigation menu.
Let's import in a header component.
import * as React from "react"
import PropTypes from "prop-types"
import { Link } from "gatsby"
import ThemeToggle from '../components/themeToggle'// 👈
const Header = ({ siteTitle }) => (
<header
style={{
marginBottom: `1.45rem`,
}}
>
<div
style={{
margin: `0 auto`,
maxWidth: 960,
padding: `1.45rem 1.0875rem`,
}}
className="flex justify-between"
>
<h1 style={{ margin: 0 }}>
<Link
className="text-2xl font-black"
to="/"
>
{siteTitle}
</Link>
</h1>
<ul className="grid grid-cols-2 gap-4">
{/* 👇 */}
<li>
<ThemeToggle />
</li>
<li>
<Link to="/" className="text-base font-semibold text-gray-400">
Blog
</Link>
</li>
<li>
<Link to="/" className="text-base font-semibold text-gray-400">
Talk
</Link>
</li>
</ul>
</div>
</header>
)
Header.propTypes = {
siteTitle: PropTypes.string,
}
Header.defaultProps = {
siteTitle: ``,
}
export default Header
It works like a magic🧙♂️
- dark mode disabled
- dark mode checked
Hope you found something useful from this blog post!
These sources were helpful too🙌
Top comments (1)
In paragraph 4, I think there is a typo, "a hyphen like ablve".
Also 'gatsby-plugin-dark-mode' does not seem to work, it is probably outdated. There is a fork that works: npmjs.com/package/@skagami/gatsby-...
Thanks for the article!