Skip to content

Styling

rocambille edited this page Jul 26, 2026 · 2 revisions

Summary: This guide explains StartER's unopinionated 3-tier CSS strategy, from semantic styling with Pico CSS via CDN to component-scoped CSS and custom framework setup.

What you'll learn:

  • Understand StartER's unopinionated, classless CSS philosophy
  • Customize brand styling using Pico CSS variables in src/react/index.css
  • Add component-scoped CSS files with Vite
  • Configure Tailwind CSS or custom CSS frameworks if desired

Overview

StartER is deliberately unopinionated about CSS. Instead of locking you into a complex CSS framework (like Tailwind, Sass, or CSS-in-JS), StartER provides a 3-tier styling strategy that starts with zero configuration and grows with your project needs.

┌───────────────────────────────────────────────────────────────────────────┐
│ Tier 1: Semantic HTML (Pico CSS via CDN in index.html)                    │
│ └── Automatic styling for <article>, <header>, <nav>, <button>, etc.      │
├───────────────────────────────────────────────────────────────────────────┤
│ Tier 2: Global Theme Customization (src/react/index.css)                  │
│ └── Override CSS variables like --pico-primary, --pico-font-family        │
├───────────────────────────────────────────────────────────────────────────┤
│ Tier 3: Component-Scoped CSS (Vite native CSS imports)                    │
│ └── Import component-specific styles directly (import "./ItemCard.css")   │
└───────────────────────────────────────────────────────────────────────────┘

Tier 1: Semantic HTML with Pico CSS

StartER includes Pico CSS via CDN in index.html. Pico is a classless CSS framework: it automatically styles standard HTML5 semantic elements without requiring utility classes.

How to use it

Simply write standard HTML tags in your React components:

function ItemCard({ title, content }: { title: string; content: string }) {
  return (
    <article>
      <header>
        <h3>{title}</h3>
      </header>
      <p>{content}</p>
      <footer>
        <button type="button">Read more</button>
      </footer>
    </article>
  );
}

Pico will automatically render this with clean padding, typography, card borders, and interactive hover states.

Common semantic elements

  • Layout & Structure: <header>, <main>, <footer>, <nav>, <article>, <aside>, <section>
  • Forms & Inputs: <form>, <input>, <select>, <textarea>, <button>, <fieldset>, <label>
  • Dialogs & Modals: <dialog>
  • Tables & Lists: <table>, <ul>, <ol>, <dl>

Tier 2: Global Theme Customization

To change your application's brand color, font, or border radius, edit src/react/index.css.

Pico CSS uses native CSS variables on the :root selector:

/* src/react/index.css */

:root {
  /* Brand primary color (buttons, active links, accents) */
  --pico-primary: #6366f1;
  --pico-primary-background: #6366f1;
  --pico-primary-underline: rgba(99, 102, 241, 0.5);

  /* Typography */
  --pico-font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  /* Geometry */
  --pico-border-radius: 0.5rem;
}

Tip

Consult the Pico CSS Color Palette Documentation for the full list of customizable CSS variables.

Dark Mode & Theme Switching

Pico CSS supports dark mode out of the box with zero extra configuration.

1. Automatic OS Preference

By default, Pico automatically detects and matches the user's operating system dark/light mode preference (prefers-color-scheme).

2. Forcing Light or Dark Theme

To force a specific theme globally, set the data-theme attribute on the <html> element in index.html:

<!-- Force dark mode -->
<html data-theme="dark">

<!-- Force light mode -->
<html data-theme="light">

3. React Theme Switcher Component

To allow users to switch themes dynamically in React:

export function ThemeToggle() {
  const toggle = () => {
    const html = document.documentElement;
    const current = html.getAttribute("data-theme");
    html.setAttribute("data-theme", current === "dark" ? "light" : "dark");
  };

  return (
    <button type="button" onClick={toggle} className="secondary outline">
      Toggle Theme
    </button>
  );
}

Tier 3: Component-Scoped CSS with Vite

When a specific React component requires custom styling beyond what Pico provides, create a .css file next to your component. Vite natively supports importing CSS files inside React components without any extra configuration.

Example

  1. Create src/react/components/item/ItemCard.css:
.item-badge {
  display: inline-block;
  padding: 0.25rem 0.5rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--pico-primary-inverse);
  background-color: var(--pico-primary);
  border-radius: var(--pico-border-radius);
}
  1. Import it in src/react/components/item/ItemCard.tsx:
import "./ItemCard.css";

export function ItemCard() {
  return <span className="item-badge">Featured</span>;
}

Optional: Adding Tailwind CSS

If you prefer utility-first CSS with Tailwind CSS, you can install it in a few seconds thanks to Vite:

Step 1: Install Tailwind and PostCSS

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Step 2: Configure content paths in tailwind.config.js

/** @type {import('tailwindcss').Config} */
export default {
  content: ["./index.html", "./src/react/**/*.{js,ts,jsx,tsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
};

Step 3: Add directives to src/react/index.css

Replace src/react/index.css with:

@tailwind base;
@tailwind components;
@tailwind utilities;

Vite will automatically compile Tailwind CSS during development and production builds.

See also

Clone this wiki locally