Styling
On this page

Styling



Framework mode uses the React Router Vite plugin, so the styling story is mostly just Vite's styling story.

React Router does not have a separate CSS pipeline for Framework mode. In practice, there are three patterns that matter:

  1. Import CSS as a side effect
  2. Use the route module links export
  3. Render a stylesheet <link> directly

Side-Effect CSS Imports

Because Framework mode uses Vite, you can import CSS files as side effects:

import "./app.css";
import "./dashboard.css";

This is often the simplest option. Global styles can be imported in root.tsx, and route or component styles can be imported next to the module that uses them.

React Router also supports adding stylesheets through the route module links export.

This is useful when you want a stylesheet URL from Vite and need React Router to render a real <link rel="stylesheet"> tag for the route:

import dashboardHref from "./dashboard.css?url";

export function links() {
  return [{ rel: "stylesheet", href: dashboardHref }];
}

The links export feeds the <Links /> component in your root route. This is the React Router-specific styling API in Framework mode. For more on route module exports, see Route Module.

If you're using React 19, you can also render a stylesheet <link> directly in your route component:

import dashboardHref from "./dashboard.css?url";

export default function Dashboard() {
  return (
    <>
      <link
        rel="stylesheet"
        href={dashboardHref}
        precedence="default"
      />
      <h1>Dashboard</h1>
    </>
  );
}

This uses React's built-in <link> support, which hoists the stylesheet into the document <head>. That gives you another way to colocate stylesheet tags with the route that needs them.

Everything Else

For CSS Modules, Tailwind, PostCSS, Sass, Vanilla Extract, and other styling tools, use the normal Vite setup for those tools.

See:

Docs and examples CC 4.0
Edit