lit / lit/lit

[labs/virtualizer] Flow layout: scrollToIndex scrolls to margin edge instead of border edge

Open Beginner friendly
#5,286 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
21.8k
Forks
1.1k
Avg merge
18h 25m
Merged PRs (30d)
2

Description

## Description

When `scrollToIndex` scrolls to an item that was not previously in the rendered range, the virtualizer scrolls to the item's margin edge rather than its border edge. Native `scrollIntoView({block: 'start'})` scrolls to the element's border edge, so the virtualizer's behavior is inconsistent with the platform.

This is most visible when items have large margins — the viewport appears offset from the target item by the item's `margin-block-start` value.

## Reproduction

[Lit Playground repro](https://lit.dev/playground/#gist=1dcc912acfd1956dba0d82f081316106)

Use the "Scroll to index" buttons to jump to items not currently in view (e.g., scroll to index 100, then back to 0). Compare the scroll position of the reference list (left) vs the virtualized list (right).

**Expected:** Both lists scroll to the same visual position — the top of the target item's border box aligned with the viewport edge.
**Actual:** The virtualized list scrolls to a position offset by the item's `margin-block-start`, showing extra margin space above the target item.

## Root cause

In `BaseLayout._calculateScrollIntoViewPosition()`, the scroll target is computed from `_getItemPosition(index).insetBlockStart`. In the Flow layout, `_getItemPosition` returns:

```
insetBlockStart: this._getPosition(idx) - marginOffset
```

where `marginOffset` is the item's `marginBlockStart`. This gives the position of the item's margin box (where the absolutely-positioned element starts in the DOM), not its border box (where the visual content starts). Since CSS margins on absolutely-positioned elements shift the element from the transform origin, the margin is already accounted for visually — but the scroll calculation treats it as the content position.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with BaseLayout._calculateScrollIntoViewPosition() and the Flow layout's _getItemPosition(index), then run the linked Lit Playground reproduction with items that have large margins. Confirm that jumping to an unrendered index aligns the target item's border box with the viewport edge, matching native scrollIntoView({block: 'start'}).

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.