Bug: ease-sidebar-collapsed width transition causes layout thrashing and jank
Description
The sidebar collapse/expand animation transitions the width property, which triggers layout recalculation on every animation frame. This causes visible jank, especially during expand (width increasing), as the browser must recalculate the layout of all sibling elements in real-time. On pages with complex layouts, this creates a stuttering animation.
Steps to Reproduce
- Link EaseMotion CSS v1.0.0
- Create a sidebar layout with content:
<div class="ease-sidebar-layout">
<aside class="ease-sidebar" id="sidebar">
<nav>...</nav>
</aside>
<main class="ease-sidebar-main">
<p>Lorem ipsum... (lots of content)</p>
</main>
</div>
- Toggle the sidebar collapse via
ease-sidebar-collapsed class
- Record the animation in DevTools Performance tab
Expected Behavior
The sidebar collapse/expand animation should run at a smooth 60fps without causing layout shifts in the main content area during the animation.
Actual Behavior
The sidebar transitions width from 280px to 0 (or vice versa), which is a layout-triggering property. Each frame of the animation forces the browser to recalculate the layout of the main content area (.ease-sidebar-main) and all its children. On pages with complex DOM trees, this causes dropped frames and visible jank. The Performance tab shows a layout recalc on every animation frame rather than just compositing.
Implementation Hints
The issue is in components/sidebar.css:
/* Current implementation — animates width (layout-triggering) */
.ease-sidebar {
width: var(--ease-sidebar-width, 280px);
transition: width 0.3s ease;
overflow: hidden;
white-space: nowrap;
}
.ease-sidebar.ease-sidebar-collapsed {
width: var(--ease-sidebar-collapsed-width, 60px);
}
The fix should use transform: translateX() combined with flex-basis instead of width, or use grid-template-columns with transition:
/* Option A — Use flex-basis + translate (GPU composited) */
.ease-sidebar-layout {
display: flex;
}
.ease-sidebar {
flex-shrink: 0;
flex-basis: var(--ease-sidebar-width, 280px);
overflow: hidden;
transition: flex-basis 0.3s ease;
/* The content inside uses translate to slide in/out */
}
.ease-sidebar.ease-sidebar-collapsed {
flex-basis: var(--ease-sidebar-collapsed-width, 60px);
}
.ease-sidebar-main {
flex: 1;
min-width: 0;
transition: flex-basis 0.3s ease;
}
/* Option B — Use CSS Grid with transition on grid-template-columns */
.ease-sidebar-layout {
display: grid;
grid-template-columns: var(--ease-sidebar-width, 280px) 1fr;
transition: grid-template-columns 0.3s ease;
}
.ease-sidebar-layout.ease-sidebar-collapsed {
grid-template-columns: var(--ease-sidebar-collapsed-width, 60px) 1fr;
}
/* Option C — Overlay approach (best performance) */
.ease-sidebar {
position: fixed;
top: var(--ease-navbar-height, 64px);
left: 0;
bottom: 0;
width: var(--ease-sidebar-width, 280px);
translate: 0 0;
transition: translate 0.3s ease;
z-index: 100;
}
.ease-sidebar.ease-sidebar-collapsed {
translate: calc(-1 * (var(--ease-sidebar-width, 280px) - var(--ease-sidebar-collapsed-width, 60px))) 0;
}
.ease-sidebar-main {
margin-left: var(--ease-sidebar-width, 280px);
transition: margin-left 0.3s ease;
}
Option C (fixed positioning with translate) provides the best performance because translate is a composited property that doesn't trigger layout. The margin-left on the main content area is a layout property but only changes on the start/end of the transition rather than every frame when combined appropriately.
Affected Files
components/sidebar.css — .ease-sidebar width transition, should use composited transform properties
Labels
type:bug, level:intermediate, GSSoC-26
Bug:
ease-sidebar-collapsedwidth transition causes layout thrashing and jankDescription
The sidebar collapse/expand animation transitions the
widthproperty, which triggers layout recalculation on every animation frame. This causes visible jank, especially during expand (width increasing), as the browser must recalculate the layout of all sibling elements in real-time. On pages with complex layouts, this creates a stuttering animation.Steps to Reproduce
ease-sidebar-collapsedclassExpected Behavior
The sidebar collapse/expand animation should run at a smooth 60fps without causing layout shifts in the main content area during the animation.
Actual Behavior
The sidebar transitions
widthfrom280pxto0(or vice versa), which is a layout-triggering property. Each frame of the animation forces the browser to recalculate the layout of the main content area (.ease-sidebar-main) and all its children. On pages with complex DOM trees, this causes dropped frames and visible jank. The Performance tab shows a layout recalc on every animation frame rather than just compositing.Implementation Hints
The issue is in
components/sidebar.css:The fix should use
transform: translateX()combined withflex-basisinstead ofwidth, or usegrid-template-columnswithtransition:Option C (fixed positioning with
translate) provides the best performance becausetranslateis a composited property that doesn't trigger layout. The margin-left on the main content area is a layout property but only changes on the start/end of the transition rather than every frame when combined appropriately.Affected Files
components/sidebar.css—.ease-sidebarwidth transition, should use composited transform propertiesLabels
type:bug,level:intermediate,GSSoC-26