Styling with Tailwind CSS
Relevant source files
The following files were used as context for generating this wiki page:
The Heyme project utilizes Tailwind CSS as its primary styling framework. This utility-first CSS framework allows for rapid UI development by composing atomic CSS classes directly in the markup. The system is configured to support custom theming, dark mode, and animations, and is deeply integrated into the Next.js build process.
The styling architecture is built upon a core configuration file (tailwind.config.js), a global stylesheet for base layer definitions (styles/globals.css), and a PostCSS setup for processing. It leverages plugins for enhanced functionality and utility functions for dynamically managing classes within React components.
Core Configuration
The foundation of the styling system is defined in tailwind.config.js and processed via PostCSS as configured in postcss.config.js.
Tailwind Configuration (tailwind.config.js)
This file defines which source files Tailwind should scan for utility classes, sets up the dark mode strategy, and extends the default theme with custom values.
The following diagram shows the key sections of the Tailwind configuration.
Sources: tailwind.config.js
Key configuration options are detailed below:
| Option | Value | Description |
|---|---|---|
darkMode | ["class"] | Enables dark mode based on a dark class on a parent element (typically <html>). |
content | ["pages/**/*.{ts,tsx}", "components/**/*.{ts,tsx}"] | Tells Tailwind to scan all .ts and .tsx files within the pages and components directories to generate the necessary CSS. |
theme.container | { center: true, padding: "1.5rem", ... } | Configures the default styling for the .container utility class, centering it and setting default padding. |
theme.extend.fontFamily.sans | ["var(--font-sans)", ...] | Adds the custom CSS variable --font-sans to the beginning of the sans-serif font stack. |
plugins | [require("tailwindcss-animate")] | Includes the tailwindcss-animate plugin to add animation utilities. |
Sources: tailwind.config.js:5-33
PostCSS Configuration (postcss.config.js)
The project uses PostCSS to process the CSS. The configuration is straightforward, enabling the tailwindcss and autoprefixer plugins. autoprefixer automatically adds vendor prefixes to CSS rules for better browser compatibility.
// postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
Sources: postcss.config.js:1-6
Global Styles and Theming
Global styles, base layers, and theming variables are managed through a combination of CSS and TypeScript files.
Global Stylesheet
The styles/globals.css file is the entry point for Tailwind's base styles, components, and utilities. These @tailwind directives are replaced by the corresponding CSS during the build process.
/* styles/globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
Sources: styles/globals.css:1-3
This file is imported once in pages/_app.tsx to apply the styles globally.
Sources: pages/_app.tsx:6
Dark Mode
Dark mode is managed by the next-themes library, which is listed as a dependency.
Sources: package.json:45
The ThemeProvider component from next-themes is wrapped around the application in pages/_app.tsx. It's configured with attribute="class" which aligns with Tailwind's darkMode: "class" strategy.
// pages/_app.tsx:25-27
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<Component {...pageProps} />
</ThemeProvider>
Sources: pages/_app.tsx:25-27
The <html> element in pages/_document.tsx is given a default class of dark and a color-scheme style to ensure the correct theme is applied on initial load. The <body> tag also has classes for light and dark mode backgrounds and text colors.
// pages/_document.tsx:5
<Html lang="en" className="dark" style={{ colorScheme: 'dark' }}>
// ...
// pages/_document.tsx:11
<body className="min-h-screen bg-slate-100 font-sans text-slate-900 antialiased dark:bg-slate-900 dark:text-slate-50 ">
Sources: pages/_document.tsx:5, pages/_document.tsx:11
Components then use the dark: variant to apply styles conditionally. For example, the site header has a different border and background color in dark mode.
// components/site-header.tsx:11
<header className="sticky top-0 z-40 w-full border-b border-b-slate-200 bg-white dark:border-b-slate-700 dark:bg-slate-900 mx-0">
Sources: components/site-header.tsx:11
Custom Fonts
A custom font, Inter, is loaded via @next/font in pages/_app.tsx. Its value is assigned to a CSS variable --font-sans, which is then used in the Tailwind configuration to create the primary font-sans utility.
// pages/_app.tsx:8-12
const fontSans = FontSans({
subsets: ["latin"],
variable: "--font-sans",
display: 'swap',
})
Sources: pages/_app.tsx:8-12
This variable is then injected into the :root element using a global JSX style tag.
// pages/_app.tsx:17-21
<style jsx global>{`
:root {
--font-sans: ${fontSans.style.fontFamily};
}
`}</style>
Sources: pages/_app.tsx:17-21
Utility Functions and Plugins
Class Name Merging
To conditionally apply and merge Tailwind classes without conflicts (e.g., merging p-2 and p-4 into just p-4), the project uses a helper function cn. This function combines clsx and tailwind-merge.
Sources: package.json:37, package.json:49
The cn utility is defined in lib/utils.ts.
// lib/utils.ts
import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
Sources: lib/utils.ts:2-6
This function is used extensively in UI components to combine base styles with styles passed via props.
Animation Plugin
The tailwindcss-animate plugin is used to add animations based on Radix UI component states. The configuration in tailwind.config.js defines custom keyframes and animation utilities for accordion-down and accordion-up.
| Animation Name | Keyframes | Description |
|---|---|---|
accordion-down | from: { height: 0 } to: { height: "var(--radix-accordion-content-height)" } | Animates the opening of an accordion item. |
accordion-up | from: { height: "var(--radix-accordion-content-height)" } to: { height: 0 } | Animates the closing of an accordion item. |
Sources: tailwind.config.js:21-30, package.json:50