Skip to content

Default theme: sidebar links invisible until hydration (section entry animation starts at opacity: 0 at first paint) #154

Description

@daveycodez

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:

  1. 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.
  2. 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:

  1. View Source on a docs page — the sidebar links are present in the SSR HTML.
  2. 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;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions