| 1 | ---
|
| 2 | title: Styling
|
| 3 | ---
|
| 4 |
|
| 5 | # Styling
|
| 6 |
|
| 7 | [MODES: framework]
|
| 8 |
|
| 9 | <br/>
|
| 10 | <br/>
|
| 11 |
|
| 12 | Framework mode uses the React Router Vite plugin, so the styling story is mostly just Vite's styling story.
|
| 13 |
|
| 14 | React Router does not have a separate CSS pipeline for Framework mode. In practice, there are three patterns that matter:
|
| 15 |
|
| 16 | 1. Import CSS as a side effect
|
| 17 | 2. Use the route module `links` export
|
| 18 | 3. Render a stylesheet `<link>` directly
|
| 19 |
|
| 20 | ## Side-Effect CSS Imports
|
| 21 |
|
| 22 | Because Framework mode uses Vite, you can import CSS files as side effects:
|
| 23 |
|
| 24 | ```tsx filename=app/root.tsx
|
| 25 | import "./app.css";
|
| 26 | ```
|
| 27 |
|
| 28 | ```tsx filename=app/routes/dashboard.tsx
|
| 29 | import "./dashboard.css";
|
| 30 | ```
|
| 31 |
|
| 32 | 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.
|
| 33 |
|
| 34 | ## `links` Export
|
| 35 |
|
| 36 | React Router also supports adding stylesheets through the route module `links` export.
|
| 37 |
|
| 38 | 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:
|
| 39 |
|
| 40 | ```tsx filename=app/routes/dashboard.tsx
|
| 41 | import dashboardHref from "./dashboard.css?url";
|
| 42 |
|
| 43 | export function links() {
|
| 44 | return [{ rel: "stylesheet", href: dashboardHref }];
|
| 45 | }
|
| 46 | ```
|
| 47 |
|
| 48 | The `links` export feeds the [`<Links />`][links-component] 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][route-module].
|
| 49 |
|
| 50 | ## Direct `<link>` Rendering
|
| 51 |
|
| 52 | If you're using React 19, you can also render a stylesheet `<link>` directly in your route component:
|
| 53 |
|
| 54 | ```tsx filename=app/routes/dashboard.tsx
|
| 55 | import dashboardHref from "./dashboard.css?url";
|
| 56 |
|
| 57 | export default function Dashboard() {
|
| 58 | return (
|
| 59 | <>
|
| 60 | <link
|
| 61 | rel="stylesheet"
|
| 62 | href={dashboardHref}
|
| 63 | precedence="default"
|
| 64 | />
|
| 65 | <h1>Dashboard</h1>
|
| 66 | </>
|
| 67 | );
|
| 68 | }
|
| 69 | ```
|
| 70 |
|
| 71 | This uses React's built-in [`<link>`][react-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.
|
| 72 |
|
| 73 | ## Everything Else
|
| 74 |
|
| 75 | For CSS Modules, Tailwind, PostCSS, Sass, Vanilla Extract, and other styling tools, use the normal Vite setup for those tools.
|
| 76 |
|
| 77 | See:
|
| 78 |
|
| 79 | - [Vite CSS Features][vite-css]
|
| 80 | - [Vite Static Asset Handling][vite-assets]
|
| 81 | - [`<Links />`][links-component]
|
| 82 |
|
| 83 | [links-component]: ../api/components/Links
|
| 84 | [react-link]: https://react.dev/reference/react-dom/components/link
|
| 85 | [route-module]: ../start/framework/route-module
|
| 86 | [vite-assets]: https://vite.dev/guide/assets.html
|
| 87 | [vite-css]: https://vite.dev/guide/features.html#css
|