Tailwind CSS

Learn how to use Tailwind CSS v4 in your Bini.js application with zero configuration.

Tailwind CSS v4 is the default styling option in Bini.js. It is pre-configured using the official Vite plugin - no PostCSS configuration needed.

Zero Configuration: Bini.js uses the @tailwindcss/vite plugin. Everything works out of the box - no postcss.config.js or tailwind.config.js required.

Setup

When you create a new Bini.js project with Tailwind, everything is configured automatically. Use the --tailwind flag:

>_Terminal
$ npx create-bini-app@latest my-app --tailwind

Or use the interactive prompt and select Tailwind CSS under the styling question:

>_Terminal
? Select a styling solution:
> Tailwind CSS
CSS Modules
None
 
↑↓ navigate • ⏎ select

Tailwind is the default, so you can also just run:

>_Terminal
$ npx create-bini-app@latest my-app

With TypeScript + Tailwind:

>_Terminal
$ npx create-bini-app@latest my-app --tailwind --typescript

Everything below is configured automatically:

vite.config.ts
src
app
globals.css
layout.tsx
page.tsx
vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'
import { biniroute } from 'bini-router'

export default defineConfig({
  plugins: [
    react(),
    tailwindcss(),  // Automatically added
    biniroute(),
  ],
})
src/app/globals.css
/* src/app/globals.css */
@import 'tailwindcss';
src/app/layout.tsx
// src/app/layout.tsx
import './globals.css'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}

Global CSS

Everything Tailwind related lives in one file, globals.css. It is imported once in the root layout, so the theme, base styles and custom utilities apply to every route:

src
app
globals.css
layout.tsx
page.tsx
components
Card.tsx
src/app/globals.css
/* src/app/globals.css */
@import 'tailwindcss';

/* Theme tokens - each one becomes a utility (bg-primary, rounded-card, ...) */
@theme {
  --color-primary: #06b6d4;
  --color-primary-dark: #0891b2;
  --font-sans: 'Inter', system-ui, sans-serif;
  --radius-card: 1rem;
}

/* Base styles applied to every page */
@layer base {
  body {
    font-family: var(--font-sans);
    -webkit-font-smoothing: antialiased;
  }
}

/* Custom utilities */
@utility text-gradient {
  background: linear-gradient(to right, var(--tw-gradient-stops));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

@utility card-hover {
  transition: all 0.2s ease;

  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
  }
}
src/app/layout.tsx
// src/app/layout.tsx
import './globals.css'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}
Keep @import 'tailwindcss' at the top of the file. The sections below show each part of this file in more detail.

Basic Usage

Use Tailwind's utility classes directly in your components:

src/app/page.tsx
export default function HomePage() {
  return (
    <div className="flex min-h-screen flex-col items-center justify-center bg-black">
      <h1 className="bg-linear-to-r from-cyan-400 to-blue-500 bg-clip-text text-4xl font-bold text-transparent">
        Welcome to Bini.js
      </h1>
      <p className="mt-4 text-lg text-slate-400">
        Styled with Tailwind CSS v4
      </p>
      <button className="mt-6 rounded-lg bg-cyan-500 px-4 py-2 font-medium text-black transition-colors hover:bg-cyan-400">
        Get Started
      </button>
    </div>
  )
}

Tailwind CSS v4 Features

FeatureDescription
Vite PluginNative Vite integration - no PostCSS config needed
CSS-first configConfigure via CSS variables instead of JS
Lightning CSSFaster builds with Lightning CSS
Simplified setupJust @import "tailwindcss" - that is it

Theming with CSS Variables

Tailwind v4 uses CSS variables for theming. Every token you declare in @theme becomes a utility:

--color-primary#06b6d4
--color-primary-dark#0891b2
src/app/globals.css
/* src/app/globals.css */
@import 'tailwindcss';

@theme {
  --color-primary: #06b6d4;
  --color-primary-dark: #0891b2;
  --font-sans: 'Inter', system-ui, sans-serif;
  --radius-card: 1rem;
}
src/app/components/Card.tsx
// src/app/components/Card.tsx
export function Card({ children }: { children: React.ReactNode }) {
  return (
    <div className="rounded-(--radius-card) bg-primary p-6">
      {children}
    </div>
  )
}

Responsive Design

Use Tailwind's responsive prefixes to adapt your layout:

sm
640px
md
768px
lg
1024px
xl
1280px
2xl
1536px
src/app/page.tsx
export default function ResponsivePage() {
  return (
    <div className="container mx-auto px-4">
      <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
        {[...Array(3)].map((_, i) => (
          <div key={i} className="rounded-lg bg-slate-900 p-4">
            <h2 className="text-lg font-semibold text-white sm:text-xl">
              Card {i + 1}
            </h2>
          </div>
        ))}
      </div>
    </div>
  )
}
BreakpointMin Width
sm640px
md768px
lg1024px
xl1280px
2xl1536px

Dark Mode

Use the dark: variant for dark mode:

light
Theme Aware Component
This adapts to light and dark mode
dark:
Theme Aware Component
This adapts to light and dark mode
src/app/components/ThemeToggle.tsx
export function ThemeToggle() {
  return (
    <div className="rounded-lg bg-white p-4 dark:bg-slate-900">
      <h2 className="text-slate-900 dark:text-white">
        Theme Aware Component
      </h2>
      <p className="text-slate-600 dark:text-slate-400">
        This adapts to light and dark mode
      </p>
    </div>
  )
}

Custom Utilities

Create custom utilities using @utility:

src/app/globals.css
/* src/app/globals.css */
@import 'tailwindcss';

@utility text-gradient {
  background: linear-gradient(to right, var(--tw-gradient-stops));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

@utility card-hover {
  transition: all 0.2s ease;

  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
  }
}
src/app/components/FeatureCard.tsx
export function FeatureCard() {
  return (
    <div className="card-hover rounded-lg bg-slate-900 p-6">
      <h3 className="text-gradient from-cyan-400 to-blue-500 text-xl font-bold">
        Custom Utility
      </h3>
    </div>
  )
}

Common Patterns

Container

src/app/components/Container.tsx
// src/app/components/Container.tsx
export function Container({ children }: { children: React.ReactNode }) {
  return (
    <div className="container mx-auto px-4">
      {children}
    </div>
  )
}

Flex Center

src/app/components/FlexCenter.tsx
// src/app/components/FlexCenter.tsx
export function FlexCenter({ children }: { children: React.ReactNode }) {
  return (
    <div className="flex items-center justify-center">
      {children}
    </div>
  )
}

Grid Layout

src/app/components/GridLayout.tsx
// src/app/components/GridLayout.tsx
export function GridLayout({ children }: { children: React.ReactNode }) {
  return (
    <div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
      {children}
    </div>
  )
}

Button Styles

src/app/components/Buttons.tsx
export function Buttons() {
  return (
    <div className="flex gap-3">
      {/* Primary */}
      <button className="rounded-lg bg-cyan-500 px-4 py-2 font-medium text-black hover:bg-cyan-400">
        Primary
      </button>

      {/* Secondary */}
      <button className="rounded-lg border border-slate-700 px-4 py-2 text-white hover:bg-slate-900">
        Secondary
      </button>
    </div>
  )
}
Was this helpful?