The sidebars are basically useless on most wiki pages once you start to scroll down. These should remain in the viewport as you scroll down for much better UX.
A simplistic or naive implementation would simply have the sidebars as fixed or sticky positioning with their own scrollbars, but that would be an inelegant solution. Much better UX would be to avoid scrollbars on the sidebars but have them scroll as the viewport scrolls, pinning to either the top or bottom of the viewport as that respective edge of the sidebar makes contact. This allows the document scroll to act as the scroller for the sidebars in an indirect fashion that ends up still feeling intuitive.
Examples of this are a bit lacking, however the Sticky Sidebar library does just this, though it's a bit janky at times due to not using position: sticky; More examples:
Sidebars (including the branding) must be in the viewport at all time, scrolling with it but pinning to the top or bottom edge.
Non-pointer focus must correctly scroll the viewport to bring the focus target into view.
Should mostly work without JavaScript, probably via position: fixed and overflow-y: auto; position: sticky could work but has the problem that the viewport would need to be scrolled all the way to the bottom to access the bottom of a tall sidebar.
Minimal or no jank; preferably using some hybrid of position: sticky and non-sticky if possible to allow the browser to handle the transition to/from on time, which is especially a noticeable problem on mobile or slower systems when using the Sticky Sidebar library.
Problems
This poses some challenges however, since the layout and document structure is more complex than the visuals indicate, and there are edge cases where the sidebar content might become inaccessible.
The site branding block is not actually in the first sidebar in the HTML structure but placed via CSS to appear that way on larger screens. This allows us to avoid changing the document structure when going from small screen mode to large screen mode and vice versa, but creates multiple problems here:
Neither the branding block nor the first sidebar technically have any easy way to account for each others' current height. This is all handled via CSS Grid and some trickery.
Since the first sidebar contents and branding are not in the same container, they can't be scrolled together visually.
Solutions
Depends on #5 being implemented. Once that's done, we can focus on the next stages.
Remaining tasks
Must haves
[ ] Implement JavaScript sticky for the first sidebar and branding.
[ ] Ensure viewport always scrolls correctly to an element when it receives focus, e.g. via keyboard.
Nice to haves
[ ] Use native position: sticky when a sidebar column fits within the viewport, only switching to the Sticky Sidebar implementation when the viewport becomes too short.
[ ] Fix the occasional frame or two of jank when scrolling quickly and hitting the top or bottom of the sidebar. This might be really difficult to do without the native position: sticky handling it for us.
[ ] Remove the layoutSizeChange dependency from the JavaScript component if not used in final iteration.
The sidebars are basically useless on most wiki pages once you start to scroll down. These should remain in the viewport as you scroll down for much better UX.
A simplistic or naive implementation would simply have the sidebars as fixed or sticky positioning with their own scrollbars, but that would be an inelegant solution. Much better UX would be to avoid scrollbars on the sidebars but have them scroll as the viewport scrolls, pinning to either the top or bottom of the viewport as that respective edge of the sidebar makes contact. This allows the document scroll to act as the scroller for the sidebars in an indirect fashion that ends up still feeling intuitive.
Examples of this are a bit lacking, however the Sticky Sidebar library does just this, though it's a bit janky at times due to not using
position: sticky
; More examples:Requirements
Sidebars (including the branding) must be in the viewport at all time, scrolling with it but pinning to the top or bottom edge.
Non-pointer focus must correctly scroll the viewport to bring the focus target into view.
Should mostly work without JavaScript, probably via
position: fixed
andoverflow-y: auto
;position: sticky
could work but has the problem that the viewport would need to be scrolled all the way to the bottom to access the bottom of a tall sidebar.Minimal or no jank; preferably using some hybrid of
position: sticky
and non-sticky if possible to allow the browser to handle the transition to/from on time, which is especially a noticeable problem on mobile or slower systems when using the Sticky Sidebar library.Problems
This poses some challenges however, since the layout and document structure is more complex than the visuals indicate, and there are edge cases where the sidebar content might become inaccessible.
The site branding block is not actually in the first sidebar in the HTML structure but placed via CSS to appear that way on larger screens. This allows us to avoid changing the document structure when going from small screen mode to large screen mode and vice versa, but creates multiple problems here:
Neither the branding block nor the first sidebar technically have any easy way to account for each others' current height. This is all handled via CSS Grid and some trickery.
Since the first sidebar contents and branding are not in the same container, they can't be scrolled together visually.
Solutions
Depends on #5 being implemented. Once that's done, we can focus on the next stages.Remaining tasks
Must haves
.layout-sidebar-first
top magic number with a value derived from the branding block contents: https://github.com/neurocracy/drupal-omnipedia-site-theme/blob/f8cf6cea1743eed43f0da6c8cf72971f0ef16fb0/stylesheets/layout/_sidebars_sticky.scss#L44header
element bottom padding with a value derived from the first sidebar region contents: https://github.com/neurocracy/drupal-omnipedia-site-theme/blob/f8cf6cea1743eed43f0da6c8cf72971f0ef16fb0/stylesheets/layout/_header_sticky.scss#L24Nice to haves
position: sticky
when a sidebar column fits within the viewport, only switching to the Sticky Sidebar implementation when the viewport becomes too short.position: sticky
handling it for us.layoutSizeChange
dependency from the JavaScript component if not used in final iteration.