Skip to content

Keep the sidebar within the viewport - #476

Open
gfiguero wants to merge 1 commit into
basecamp:mainfrom
gfiguero:sidebar-viewport
Open

Keep the sidebar within the viewport#476
gfiguero wants to merge 1 commit into
basecamp:mainfrom
gfiguero:sidebar-viewport

Conversation

@gfiguero

Copy link
Copy Markdown

Fixes #475.

The problem

#sidebar is a grid item spanning all four rows of the body grid, so block-size: 100% and max-block-size: 100% resolve against a grid area as tall as the whole document. The element is never shorter than its content, so its overflow: auto never engages, and the absolutely positioned .toc.sidebar__content inside it (inset: 0 auto 0 0) stretches to the bottom of the page along with it.

In a book with long pages that leaves the page scrollbar as the only way to reach the end of the table of contents, and scrolling the text drags the navigation out of view. On a 1257px viewport with a long page the sidebar measures just over 20,000px tall.

The fix

Stick the sidebar to the viewport and bound it to 100dvh, so it scrolls its own content:

block-size: 100dvh;      /* was 100%     */
max-block-size: 100dvh;  /* was 100%     */
inset-block-start: 0;    /* new          */
position: sticky;        /* was relative */

sticky rather than fixed keeps the sidebar a grid item, so the column keeps its width and the open/close margin-inline-start transition is untouched. It also still establishes the containing block for the absolutely positioned menu inside it.

dvh needs a 2022-or-newer browser, which is no newer than the :has() and container queries already in use. The sidebar is display: none below 70ch, so the mobile layout is unaffected.

Tests

test/system/sidebar_scroll_test.rb covers both halves of the problem, and both fail without the change:

  • the sidebar fits the viewport instead of growing with the page — before the fix it measures 20970.64px in a 1257px viewport
  • it stays at top: 0 after the page is scrolled to the bottom

Full suite is green on Ruby 3.4.7.

The sidebar is a grid item spanning all four rows, so `block-size: 100%`
resolves against a grid area as tall as the whole document. Its `overflow`
never kicks in, and the absolutely positioned table of contents inside it
stretches to the bottom of the page.

In a long book that leaves the page scrollbar as the only way to reach the
end of the table of contents, and scrolling the text drags the navigation
out of view.

Stick the sidebar to the viewport and bound it to `100dvh` so the table of
contents scrolls its own content instead.
Copilot AI balanced review requested due to automatic review settings August 16, 2026 18:51

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a regression test and adjusts sidebar CSS so the table of contents sidebar is constrained to the viewport and remains visible while the document scrolls.

Changes:

  • Add a system test validating sidebar height is capped to the viewport and that it doesn’t scroll away.
  • Update #sidebar styling to size and stick relative to the viewport (using dvh + position: sticky).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
test/system/sidebar_scroll_test.rb Adds system coverage for sidebar height/scroll behavior.
app/assets/stylesheets/layout.css Switches sidebar sizing to viewport units and makes it sticky to prevent page-length growth.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +12 to +13
assert_operator document_height, :>, viewport_height * 2,
"the test page should be considerably taller than the viewport"
test "the table of contents stays put while the page scrolls" do
execute_script "window.scrollTo(0, document.documentElement.scrollHeight)"

assert_equal 0, sidebar_top.round,
:where(#sidebar) {
background-color: var(--color-subtle-light);
block-size: 100%;
block-size: 100dvh;
Comment on lines +105 to +108
inset-block-start: 0;
max-block-size: 100dvh;
overflow: auto;
position: relative;
position: sticky;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sidebar table of contents scrolls with the page in long books

2 participants