Summary
In the default theme, sidebar section links are invisible at first paint and only "flicker in" once hydration finishes, even though they are fully present in the SSR HTML.
Cause
.section-content plays an entry animation on [data-expanded] whose first keyframe hides the content:
https://github.com/kobaltedev/solidbase/blob/main/src/default-theme/Layout.module.css#L165-L172
.section-content {
animation: sectionHide 0.15s var(--sb-transition-timing);
overflow: hidden;
&[data-expanded] {
animation: sectionShow 0.15s var(--sb-transition-timing);
}
}
@keyframes sectionShow {
from {
opacity: 0;
height: 0;
}
...
}
Since SSR emits data-expanded on the <ul>, the sectionShow animation starts the moment styles apply — at first paint, before hydration. Two problems compound:
- The animation's first frame is
opacity: 0; height: 0, so the links are hidden at first paint. Because height is animated, the animation runs on the main thread — which is busy evaluating modules and hydrating right after load — so it can sit frozen on that invisible first frame until hydration settles. On a dev server (or any slow/throttled load) the sidebar shows only the section titles for the whole hydration window, then the links pop in.
- The
to keyframe uses height: var(--kb-collapsible-content-height), which Kobalte only sets from JS after mount, so pre-hydration the keyframe height is unresolvable anyway.
Section titles don't flicker because only the content <ul> is animated — which makes the effect look like a sidebar SSR bug, though the markup is fine.
Reproduction
Any SolidBase site with a sidebar:
View Source on a docs page — the sidebar links are present in the SSR HTML.
- Hard-reload with CPU throttling (or just a dev server) — the sidebar renders only section titles at first paint; links appear after hydration completes.
Observed on 0.6.9; the relevant CSS is unchanged on main.
Suggested fix
Don't play the expand animation on initial mount — only on user toggling. E.g. gate the animation behind a class/attribute that's only set after mount, or drop the entry animation from the default [data-expanded] state entirely and animate only state changes.
Workaround we're using downstream (disables the toggle animation too):
aside nav ul[id^="collapsible-"][id$="-content"] {
animation: none;
}
Summary
In the default theme, sidebar section links are invisible at first paint and only "flicker in" once hydration finishes, even though they are fully present in the SSR HTML.
Cause
.section-contentplays an entry animation on[data-expanded]whose first keyframe hides the content:https://github.com/kobaltedev/solidbase/blob/main/src/default-theme/Layout.module.css#L165-L172
Since SSR emits
data-expandedon the<ul>, thesectionShowanimation starts the moment styles apply — at first paint, before hydration. Two problems compound:opacity: 0; height: 0, so the links are hidden at first paint. Becauseheightis animated, the animation runs on the main thread — which is busy evaluating modules and hydrating right after load — so it can sit frozen on that invisible first frame until hydration settles. On a dev server (or any slow/throttled load) the sidebar shows only the section titles for the whole hydration window, then the links pop in.tokeyframe usesheight: var(--kb-collapsible-content-height), which Kobalte only sets from JS after mount, so pre-hydration the keyframe height is unresolvable anyway.Section titles don't flicker because only the content
<ul>is animated — which makes the effect look like a sidebar SSR bug, though the markup is fine.Reproduction
Any SolidBase site with a sidebar:
View Sourceon a docs page — the sidebar links are present in the SSR HTML.Observed on
0.6.9; the relevant CSS is unchanged onmain.Suggested fix
Don't play the expand animation on initial mount — only on user toggling. E.g. gate the animation behind a class/attribute that's only set after mount, or drop the entry animation from the default
[data-expanded]state entirely and animate only state changes.Workaround we're using downstream (disables the toggle animation too):