# Dynamic Theme Loading
Load skeleton themes on demand.
## About Themes
The most common way to load skeleton themes is by importing them in your root stylesheet.
```css title="app/globals.css"
@import 'tailwindcss';
@import '@skeletonlabs/skeleton';
@import '@skeletonlabs/skeleton/themes/cerberus';
@import '@skeletonlabs/skeleton/themes/catppuccin';
```
```css title="src/app.css"
@import 'tailwindcss';
@import '@skeletonlabs/skeleton';
@import '@skeletonlabs/skeleton/themes/cerberus';
@import '@skeletonlabs/skeleton/themes/catppuccin';
```
This will bundle your themes when you build your application, for that reason you should only import the themes you need because they will increase your CSS bundle size.
While this is sufficient for most applications this might not be flexible enough for your needs, you may want themes to be
user specific, editable, organization specific and so on, since skeleton themes are just CSS variables there are many ways
you can load themes on demand, read further to see how.
## Creating Stylesheets on layout load
This approach assumes the CSS variables of the skeleton theme you want is available during the load function (eg: on your database or in memory).
In this example we will add a default theme that that can be used as a fallback.
```css title="app/globals.css"
@import 'tailwindcss';
@import '@skeletonlabs/skeleton';
@import './default.css';
```
```css title="src/app.css"
@import 'tailwindcss';
@import '@skeletonlabs/skeleton';
@import './default.css';
```
```css title="app/default.css"
[data-theme='default'] {
/* ... */
}
```
```css title="src/default.css"
[data-theme='default'] {
/* ... */
}
```
To load your themes we will utilize the [NextJS `getServerSideProps` function](https://nextjs.org/docs/pages/building-your-application/data-fetching/get-server-side-props) function in combination with [Head component](https://nextjs.org/docs/pages/api-reference/components/head):
```tsx title="app/layout.tsx"
import Head from 'next/head';
import type { InferGetServerSidePropsType, GetServerSideProps } from 'next';
const getThemes = async () => {
return [
{
name: 'theme-1',
css: `[data-theme='theme-1'] { /* ... */ }`
},
{
name: 'theme-2',
css: `[data-theme='theme-2'] { /* ... */ }`
}
];
};
export const getServerSideProps = (async () => {
const themes = getThemes();
return {
props: {
themes: ['default', ...themes.map((t) => t.name)],
css: themes.map((theme) => theme.css).join('\n\n')
}
};
}) satisfies GetServerSideProps<{ repo: Repo }>;
export default function Page({ repo }: InferGetServerSidePropsType) {
return (
<>
{repo.stargazers_count}
>
);
}
```
To load your themes we will utilize the [SvelteKit `load` function](https://svelte.dev/docs/kit/load) function in combination with [``](https://svelte.dev/docs/svelte/svelte-head):
```ts title="src/route/+layout.server.ts"
import type { PageLoad } from './$types';
const getThemes = async () => {
return [
{
name: 'theme-1',
css: `[data-theme='theme-1'] { /* ... */ }`
},
{
name: 'theme-2',
css: `[data-theme='theme-2'] { /* ... */ }`
}
];
};
export const load: PageLoad = async (event) => {
const themes = getThemes();
return {
themes: ['default', ...themes.map((t) => t.name)],
css: themes.map((theme) => theme.css).join('\n\n')
};
};
```
```svelte title="src/routes/+layout.svelte"
{@html ``}
```
> ⚠️ _Important_ make sure you sanitize the CSS before inserting it or you'll be vulnerable to CSS injection.
After doing so you should be able to toggle themes on demand by changing the `data-theme` attribute on the `html` tag.
Note that there are multiple ways to go about this problem, another way could be to generate CSS files with
the same content as the one in this example and then load only the css files you want, while this
is more complex than storing and retrieving themes as JSON on a database this approach could benefit
from the browser caching mechanism.