# Load Dynamic Stylesheets in React Router

Used: react-router@7.0.0 and remix-utils@8.0.0

In some cases, you may need to dynamically load styles based on user preferences or organizational settings. For example, an organization might customize the UI for its members, or a user might select a theme that requires loading a specific CSS file.

## Generating CSS On-Demand

If the CSS needs to be generated dynamically—perhaps based on database-stored data—you must first create a route to serve the generated CSS:

```ts {% path="resources/styles.ts" %}
import { stylesheet } from "remix-utils/responses";
import type { Route } from "./+types/styles";

export async function loader({ request }: Route.LoaderArgs) {
  let user = await authenticate(request);
  if (!user) return stylesheet(`/* No user found, replace with fallback */`);
  let styles = await getStylesForUser(user);
  return stylesheet(styles);
}
```

Then, in `app/root.tsx`, load the styles from the newly created route:

```tsx {% path="app/root.tsx" %}
// some code here

export function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="stylesheet" href="/styles.css" />
      </head>
      <body>
        {children}
        <ScrollRestoration />
        <Scripts />
      </body>
    </html>
  );
}

// more code here
```

Ensure the route is registered in `app/routes.ts`:

```tsx {% path="app/routes.ts" %}
// some code here
export default [
  // some routes here
  route("styles.css", "resources/styles.ts"),
  // more routes here
] satisfies RouteConfig;
```

Now, when a user visits the page, the CSS file will be generated in real time and served dynamically.

## Dynamically Load Static CSS Files

If you need to load one of several predefined CSS files based on a condition—such as a user’s theme preference—you can achieve this by combining a `LoaderFunction` with a `MetaFunction`:

```tsx {% path="app/root.tsx" %}
export async function loader({ request }: Route.LoaderArgs) {
  let user = await authenticate(request);
  if (!user) return data({ user: null, theme: "default" });
  return data({ user, theme: user.theme });
}

export function meta({ data }: Route.MetaArgs) {
  // if root loader failed, always load default styles
  if (!data) {
    return [
      { tagName: "link", rel: "stylesheet", href: "/themes/default.css" },
    ];
  }

  // if we have the loader data, load the user's theme or the fallback
  return [
    { tagName: "link", rel: "stylesheet", href: `/themes/${data.theme}.css` },
  ];
}
```

Create a set of CSS files in `public/themes/`, such as `default.css`, `dark.css`, and `light.css`, ensuring the appropriate stylesheet is loaded based on user preferences.

## Generating CSS On-Demand with Dynamic URLs

If each user requires a unique CSS file with a URL like `/styles/:userId.css`, you can combine the previous approaches:

First, create a route to generate the CSS dynamically:

```ts {% path="resources/styles.ts" %}
import { stylesheet } from "remix-utils/responses";
import type { Route } from "./+types/styles";

export async function loader({ request, params }: Route.LoaderArgs) {
  let styles = await getStylesForUser(params.userId);
  return stylesheet(styles);
}
```

Then, modify `app/root.tsx` to load the user-specific stylesheet:

```tsx {% path="app/root.tsx" %}
export async function loader({ request }: Route.LoaderArgs) {
  let user = await authenticate(request);
  if (!user) return data({ user: null });
  return data({ user });
}

export function meta({ data }: Route.MetaArgs) {
  if (!data) return [];
  return [
    { tagName: "link", rel: "stylesheet", href: `/styles/${data.user.id}.css` },
  ];
}
```

Finally, register the dynamic route in `app/routes.ts`:

```tsx {% path="app/routes.ts" %}
export default [
  // some routes here
  route("styles/:userId.css", "resources/styles.ts"),
  // more routes here
] satisfies RouteConfig;
```

Now, when a user visits the page, the application will generate and serve a personalized CSS file dynamically.
