Gatsby Styling — CSS Modules, Global CSS, and CSS-in-JS
Learn how to style Gatsby sites with CSS Modules, global stylesheets, CSS-in-JS libraries like styled-components, and Tailwind CSS for React static sites.
In this lesson, you'll understand the styling options in Gatsby and how to choose the right approach for your project.
What You'll Learn
How to use CSS Modules for component-scoped styles, global CSS for base styles, CSS-in-JS with styled-components, and Gatsby-specific styling considerations.
Why It Matters
Styling approach affects developer experience, bundle size, and maintainability. Gatsby supports multiple styling methods so you can choose what fits your team.
flowchart LR
A[Styling Options] --> B[CSS Modules]
A --> C[Global CSS]
A --> D[CSS-in-JS]
A --> E[Tailwind CSS]
B --> F[Component-Scoped]
C --> G[Base Styles]
D --> H[Dynamic Styles]
E --> I[Utility-First]
style A fill:#639,color:#fff
CSS Modules
Component-scoped CSS that prevents class name collisions:
// src/components/Button.js
import React from 'react';
import * as styles from './Button.module.css';
export default function Button({ children }) {
return <button className={styles.button}>{children}</button>;
}
/* src/components/Button.module.css */
.button {
background: #639;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
}
.button:hover {
background: #4a148c;
}
Output: The .button class is hashed to a unique name like Button_button_abc123. Styles don't leak to other components.
Global CSS
Import global stylesheets for base resets and typography:
// gatsby-browser.js
import './src/styles/global.css';
/* src/styles/global.css */
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0;
font-family: 'Inter', sans-serif;
line-height: 1.6;
}
h1, h2, h3 {
line-height: 1.2;
}
Output: Global styles apply everywhere. Import global.css in gatsby-browser.js to ensure it's included in the build.
CSS-in-JS with styled-components
Dynamic, component-scoped styles with full JavaScript power:
npm install styled-components gatsby-plugin-styled-components
// gatsby-config.js
module.exports = {
plugins: ['gatsby-plugin-styled-components']
};
// src/components/Card.js
import React from 'react';
import styled from 'styled-components';
const CardWrapper = styled.div`
border: 1px solid #ddd;
border-radius: 8px;
padding: 16px;
margin: 8px 0;
box-shadow: ${props => props.elevated ? '0 2px 8px rgba(0,0,0,0.15)' : 'none'};
`;
const Title = styled.h3`
color: #639;
margin: 0 0 8px 0;
`;
export default function Card({ title, children, elevated }) {
return (
<CardWrapper elevated={elevated}>
<Title>{title}</Title>
{children}
</CardWrapper>
);
}
Output: The Card component has scoped styles. The elevated prop dynamically changes the box-shadow.
Tailwind CSS
Utility-first CSS with Gatsby:
npm install -D tailwindcss postcss autoprefixer gatsby-plugin-postcss
npx tailwindcss init
// tailwind.config.js
module.exports = {
content: ['./src/**/*.{js,jsx,ts,tsx}'],
theme: { extend: {} },
plugins: []
};
/* src/styles/global.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
// gatsby-config.js
module.exports = {
plugins: ['gatsby-plugin-postcss']
};
// src/components/Badge.js
import React from 'react';
export default function Badge({ text, variant = 'default' }) {
const colors = {
default: 'bg-gray-100 text-gray-800',
success: 'bg-green-100 text-green-800',
warning: 'bg-yellow-100 text-yellow-800',
error: 'bg-red-100 text-red-800'
};
return (
<span className={`inline-block px-2 py-1 rounded text-xs font-medium ${colors[variant]}`}>
{text}
</span>
);
}
Output: Badge uses Tailwind utility classes for styling. No custom CSS needed.
Common Mistakes
- Not importing CSS Modules correctly: Use
import * as styles from './File.module.css'orimport styles from './File.module.css'depending on your setup. - Putting component styles in global CSS: Global CSS should be minimal (resets, typography). Component styles belong in CSS Modules or CSS-in-JS.
- Forgetting to install styled-components plugin: Without
gatsby-plugin-styled-components, SSR breaks and styles flash on page load. - Not configuring Tailwind's
contentpaths: Tailwind scans your source files for class names. If paths are wrong, classes won't generate. - Using CSS-in-JS for everything: CSS Modules are simpler for static styles. Use CSS-in-JS only when you need dynamic styling based on props.
Practice Questions
What naming convention activates CSS Modules in Gatsby? Answer: Files ending with
.module.cssare treated as CSS Modules. Regular.cssfiles are global.How do you add global styles in Gatsby? Answer: Import a CSS file in
gatsby-browser.js:import './src/styles/global.css'.What plugin is required for styled-components SSR? Answer:
gatsby-plugin-styled-components. It ensures styles are extracted during the build.How do you style based on component props? Answer: Use CSS-in-JS (styled-components, emotion) or pass class names conditionally with CSS Modules.
Challenge
Build a component that uses all three styling approaches: a Card with CSS Modules base styles, a Button with styled-components for prop-based variants, and layout utility classes from Tailwind.
Mini Project
Create a blog post template styled with CSS Modules for the article layout, styled-components for dynamic theme colors, and global CSS for base typography and resets.
FAQ
What's Next
Learn about Gatsby Static Assets and Images to handle images, fonts, and static files in your Gatsby site.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro