htmlcssquarto

How to make a sticky sidebar with Quarto and HTML


I am using quarto to render a static html file and I am using both a tabset panel layout, in which I have also put a sidebar panel (https://quarto.org/docs/interactive/layout.html#sidebar-panel).

The page is however long, so that I need to scroll down to get to the bottom; I would like the sidebar panel to be "fixed" when I scroll the page, and to scroll only if I hover it. This behavior should be achieved by putting position:sticky to the panel-sidebar container, but I have been unable to make it work so far. Any idea why I cant get this to work? see a reproducible example below:

---
title: "Test"
title-block-banner: true
format:
  html:
    theme: default
---

```{css, echo=FALSE}
.panel-sidebar {
  position:sticky
  top:0;
}
```

::: panel-tabset

## Test1

::: panel-fill
A long list of things and a long table:

```{r}
library(tidyverse)
library(reactable)
reactable(mtcars, defaultPageSize=100)
```
:::

::: panel-sidebar
Something that I want to be stick on top when I scroll the page
:::
:::

Solution

  • The main reason why your styling does not apply is that you are missing a semicolon in

    position:sticky /* ; <--- */
    top:0;
    

    However, this will not be sufficient because you have the additional requirement with the scrolling capability. You could add an overflow-y: scroll and height: 100vh for your sidebar such that the whole style definition for the sidebar reads

    .panel-sidebar {
      position: sticky;
      overflow-y: scroll;
      top: 0px;
      height: 100vh;
    }
    

    Then it should work: The header is sticky until you reach the bottom of the container and you can scroll the content inside the sidebar separately when you hover into:

    enter image description here

    ---
    title: "Test"
    title-block-banner: true
    format:
      html:
        theme: default
    ---
    
    ```{css, echo=FALSE}
    .panel-sidebar {
      position: sticky;
      overflow-y: scroll;
      top: 0px;
      height: 100vh;
    }
    ```
    
    ::: panel-tabset
    
    ## Test1
    
    ::: panel-fill
    A long list of things and a long table:
    
    ```{r, message = FALSE}
    library(tidyverse)
    library(reactable)
    reactable(mtcars, defaultPageSize=100)
    ```
    :::
    
    ::: panel-sidebar
    **Something that I want to be stick on top when I scroll the page**
    
    Ipsum facilisis tincidunt nascetur; nostra quisque habitasse feugiat volutpat?
    Parturient potenti leo, luctus libero non pellentesque dis. Habitasse potenti lobortis
    mattis duis purus gravida habitasse vulputate? Nostra dictum donec varius massa ad
    fringilla natoque senectus, pharetra donec lectus penatibus odio.
    
    Ipsum bibendum quis, justo non id rhoncus id orci? Hendrerit metus duis urna curabitur
    facilisis cum nascetur feugiat. Vulputate conubia: himenaeos aptent nibh maecenas dui
    tellus sociosqu? Condimentum non facilisi himenaeos lacinia: lacinia erat sem bibendum
    convallis lobortis venenatis condimentum, ullamcorper rhoncus inceptos varius volutpat
    primis est diam tellus senectus donec.
    
    Adipiscing nostra facilisi pulvinar; mi dictum laoreet maecenas. Nunc purus nostra
    ultrices massa nullam netus sodales vestibulum placerat ante. Hendrerit ultrices
    faucibus cum et malesuada a litora tortor aliquet, diam ornare. Litora quis sapien
    tellus habitasse maecenas sem himenaeos sem vitae. Aliquam erat torquent curabitur
    sapien iaculis convallis ornare hendrerit habitant urna, fermentum ultricies eu taciti
    leo.
    
    Ipsum elementum feugiat eleifend quisque facilisis mollis dictum in? Inceptos feugiat
    hendrerit libero ante sodales in primis? Est lobortis eget imperdiet integer, nam
    aenean mollis? Imperdiet vehicula class dis enim cum vivamus ac ullamcorper. Volutpat
    per mattis sodales auctor nam urna aptent nascetur, pulvinar fusce torquent?
    :::
    :::