An open API service indexing awesome lists of open source software.

https://github.com/varugasu/cracked-frontend


https://github.com/varugasu/cracked-frontend

Last synced: 3 months ago
JSON representation

Awesome Lists containing this project

README

          

# Virtualization

## Fixed-Height

The core of this strategy is the `slice`, where we only render what is **inside of the viewport**. That's why we need a predictable way of determining how many items we should render that is a **fixed height per item**

That's why we need **three layers**:



The **Viewport** is a **fixed-height container**:

- It defines how much the list we will see (`viewportHeight`)
- How far the user has scrolled (`scrollTop`)
- and hides the full height of the list (Spacer)

The **Spacer** fakes the full list height, therefore its height is `itemHeight * items.length`. It will give the scrollbar the correct range so the browser thinks **the whole list is rendered**. This provides affordance to the user so they can keep scrolling.

Finally, we have the **Slice** that will the items but it will also **show the user how much they have scrolled** by using the `offsetY`. This will move the scroll to correctly show the position we are at the list.

For the Slice, we render `visibleCount + overscan * 2` items. The visible count is defined by `viewportHeight / itemHeight`. The `overscan`is a buffer to render extra rows **outside of the visible viewport**. This will ensure that even if we scroll really fast, we will still show the next items, providing a **smooth scrolling experience to the user**.

We use `overscan * 2` to ensure we are rendering **before and after**, in case the user also decides to scroll back really fast. Therefore, `* 2` ensuress **overscan above \* overscan below**

Finally, we have the slice that is indeed what we are rendering. We get the `items` and run `.slice` with two indexes we calculated:

```ts
const start = Math.max(0, Math.floor(scrollTop / itemHeight) - overscan)
const end = Math.min(items.length - 1, start + visibleCount + overscan * 2)
```

For `start`, `scrollTop / itemHeight` defines **how many rows** have been scrolled past.
If `scrollTop = 4800` and `itemHeight = 48`, then we know that **100** have been scrolled past.

The `Math.floor` rounds down the start in case we are between rows and `- overscan` ensures we render a few extra rows **above** the viewport

`end` is more straightforward. Given the `start`, we add the amount of visible rows we want (`visibleCount`) and `overscan * 2`. This is multiplied by two to covers the rows we skipped at the top and the buffer at the bottom