It's just an idea, but it'll be very convenient if we'll able to switch classes on body element like this:
<svelte:body class:profile={isProfilePage} />
I've considered this before - what should happen with this when compiling for SSR? There's nowhere in the current .render() response where we could say what classes are on <body>.
Seems, we already have something similar with head:
const { head, html, css, body } = App.render({ ... });
And can be used in Sapper like this:
<head>
...
%sapper.head%
</head>
<body %sapper.body%>
</body>
I really believe the body class for pages is a common case for many apps.
In case someone wants to change the class of the body it's very easy.
Add this to the script part of your main layout file:
document.body.classList.add('my-class')
Then in a global css file like _public/global.css_ add the styles for .my-class
@jorgegorka Sorry, but everyone knows that. Here we're talking about a universal (client and server) and declarative way to set body classes. The way you described won't work with SSR and not declarative.
The same kind of thing would be very useful for setting attributes on html, such as lang. react-helmet handles this by returning htmlAttributes and bodyAttributes when calling helmet.renderStatic()[[link]]. Maybe a similar approach would make sense here?
vote positive on <svelte:body class:name={confition} is usefull
+1 It would be great if we could set it like this, from the special component and with SSR.
+1 for
<svelte:body class:name={confition}>
as well as
<svelte:html lang={lang}>
If you want to change the whole background without having the content being taller than the fold, being able to change body class is pretty vital.
Is there currently a workaround?
If I'm not wrong, using document.body.classList won't work for SSR.
I want to give body different classes based on which page is active.
BTW, I think this feature might somewhat relate to https://github.com/sveltejs/sapper/issues/374.
That issue is basically asking a way for svelte to render directly at the html/body level, instead of a child node, and that probably affects how components can manipulate {body, html} {classes,attributes}
I don't know what is the status of <svelte:body class:name={condition} implementation, but in the meantime, I've managed to overpass this issue by using <svelte:head> instead. As my need was to add styling to my page's body.
<svelte:head>
{#if isModal}
<style>
body {
overflow: hidden;
}
</style>
{/if}
</svelte:head>
Simple theme chooser.
<script>
const themes = ['', 'dark-theme', 'light-theme']
const icons = ['🌙', '🌞', '⭐']
let index = 0
</script>
<button on:click={() => { index = (index + 1) % themes.length }}>{icons[index]}</button>
<svelte:body class={themes[index]}/>
<svelte:head>
<style>
/* CSS file */
:root {
--background-color: #a19585;
--text-color: #f7f7f7;
--primal-color: #30a5a7;
}
.light-theme {
--background-color: #fffaf4;
--text-color: #201f20;
}
.dark-theme {
--background-color: #201f20;
--text-color: #fffaf4;
}
body {
background-color: var(--background-color);
color: var(--text-color);
}
</style>
</svelte:head>
@Conduitry @Rich-Harris Any comments here? Seems this proposal is very popular.
@Rich-Harris
i have the same issue
@sveltejs thanks for deleting my comment and i sure you delete this comment. but i should remember to you (who deleted my comment), Svelte isn’t single compiler around world, so keep your @sveltejs yourself.
I just tried it and already has experience of deleting my comment
i also find that dynamic class assignments to the body element are really needed, especially in the sapper environment with SSR
where is the solution? Someone knows?
I want this feature alongside
const { head, html, css, htmlAttrs, bodyAttrs } = App.render({ ... })
Sapper template:
<html %sapper.htmlAttrs%>
<head>
...
%sapper.head%
</head>
<body %sapper.bodyAttrs%>
...
</body>
</html>
+1 This is a a must. Of course this can be solved but why resort to hacks.
+1
In the meantime in:
_layout.svelte
<script>
import { stores } from '@sapper/app';
import { onMount } from 'svelte';
const { session } = stores();
let root;
onMount( () => {
root = document.documentElement;
}
$: root && (hasUser => root.classList.toggle('loggedin', hasUser))(!!$session.user);
</script>
Most helpful comment
+1 for
as well as