About Themes
The most common way to load skeleton themes is by importing them in your root stylesheet.
bg-surface-50-950 preset-filled-primary-500 preset-filled-secondary-500 preset-filled-tertiary-500 preset-filled-success-500 preset-filled-warning-500 preset-filled-error-500 preset-filled-surface-500 bg-linear-to-br from-primary-500 to-secondary-500 bg-linear-to-br from-secondary-500 to-tertiary-500 bg-linear-to-br from-tertiary-500 to-primary-500
@import 'tailwindcss' ;
@import '@skeletonlabs/skeleton' ;
@import '@skeletonlabs/skeleton/themes/cerberus' ;
@import '@skeletonlabs/skeleton/themes/catppuccin' ;
bg-surface-50-950 preset-filled-primary-500 preset-filled-secondary-500 preset-filled-tertiary-500 preset-filled-success-500 preset-filled-warning-500 preset-filled-error-500 preset-filled-surface-500 bg-linear-to-br from-primary-500 to-secondary-500 bg-linear-to-br from-secondary-500 to-tertiary-500 bg-linear-to-br from-tertiary-500 to-primary-500
@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.
bg-surface-50-950 preset-filled-primary-500 preset-filled-secondary-500 preset-filled-tertiary-500 preset-filled-success-500 preset-filled-warning-500 preset-filled-error-500 preset-filled-surface-500 bg-linear-to-br from-primary-500 to-secondary-500 bg-linear-to-br from-secondary-500 to-tertiary-500 bg-linear-to-br from-tertiary-500 to-primary-500
@import 'tailwindcss' ;
@import '@skeletonlabs/skeleton' ;
@import './default.css' ;
bg-surface-50-950 preset-filled-primary-500 preset-filled-secondary-500 preset-filled-tertiary-500 preset-filled-success-500 preset-filled-warning-500 preset-filled-error-500 preset-filled-surface-500 bg-linear-to-br from-primary-500 to-secondary-500 bg-linear-to-br from-secondary-500 to-tertiary-500 bg-linear-to-br from-tertiary-500 to-primary-500
@import 'tailwindcss' ;
@import '@skeletonlabs/skeleton' ;
@import './default.css' ;
bg-surface-50-950 preset-filled-primary-500 preset-filled-secondary-500 preset-filled-tertiary-500 preset-filled-success-500 preset-filled-warning-500 preset-filled-error-500 preset-filled-surface-500 bg-linear-to-br from-primary-500 to-secondary-500 bg-linear-to-br from-secondary-500 to-tertiary-500 bg-linear-to-br from-tertiary-500 to-primary-500
[ data-theme = 'default' ] {}
bg-surface-50-950 preset-filled-primary-500 preset-filled-secondary-500 preset-filled-tertiary-500 preset-filled-success-500 preset-filled-warning-500 preset-filled-error-500 preset-filled-surface-500 bg-linear-to-br from-primary-500 to-secondary-500 bg-linear-to-br from-secondary-500 to-tertiary-500 bg-linear-to-br from-tertiary-500 to-primary-500
[ data-theme = 'default' ] {}
To load your themes we will utilize framework-specific load functions:
To load your themes we will utilize the SvelteKit load function function in combination with <svelte:head> :
bg-surface-50-950 preset-filled-primary-500 preset-filled-secondary-500 preset-filled-tertiary-500 preset-filled-success-500 preset-filled-warning-500 preset-filled-error-500 preset-filled-surface-500 bg-linear-to-br from-primary-500 to-secondary-500 bg-linear-to-br from-secondary-500 to-tertiary-500 bg-linear-to-br from-tertiary-500 to-primary-500
src/route/+layout.server.ts src/routes/+layout.svelte
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')
};
}; < script >
const { data } = $ props ();
</ script >
< svelte : head >
{@ html \ `<style> \$ {data.css}</style> \` }
</svelte:head>
To load your themes we will utilize the NextJS getServerSideProps function function in combination with Head component :
bg-surface-50-950 preset-filled-primary-500 preset-filled-secondary-500 preset-filled-tertiary-500 preset-filled-success-500 preset-filled-warning-500 preset-filled-error-500 preset-filled-surface-500 bg-linear-to-br from-primary-500 to-secondary-500 bg-linear-to-br from-secondary-500 to-tertiary-500 bg-linear-to-br from-tertiary-500 to-primary-500
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<typeof getServerSideProps>) {
return (
<>
<Head>
<style dangerouslySetInnerHTML={{ __html: css }} />
</Head>
<main>
<p>{repo.stargazers_count}</p>
</main>
</>
);
}
⚠️ 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.