# How to Implement React scrollIntoView for DOM Elements and Fragments

> Implement React scrollIntoView to keep DOM elements or fragments visible. Learn how to use refs for seamless scrolling with full API compatibility.

- Repository: [Meta/react](https://github.com/facebook/react)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Use `ref.current.scrollIntoView(alignToTop)` on standard DOM refs for full API compatibility, or attach refs to React Fragments to leverage the specialized `FragmentInstance` implementation that intelligently scrolls to the first or last child based on the boolean parameter.**

Managing scroll position is essential for modern React applications, especially when building chat interfaces, data tables, or navigation menus. While browsers provide a native `scrollIntoView` method, React offers specialized handling for fragments through the `FragmentInstance` class in the Facebook React repository. This guide explains how to correctly implement react scrollintoview functionality using both standard DOM refs and React's fragment-specific implementation.

## Understanding Native DOM scrollIntoView vs. React Fragment Handling

Standard DOM elements in React support the full native `scrollIntoView` API, including options objects for smooth scrolling and block alignment. However, React fragments require special handling because they don't correspond to a single DOM node.

### Standard DOM Element Scrolling

When you attach a ref to a standard HTML element like a `<div>`, you gain access to the complete native `scrollIntoView` specification, including the options object syntax.

### React Fragment Scrolling Architecture

React implements a `FragmentInstance` class in [`packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js`](https://github.com/facebook/react/blob/main/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js) (lines 53-71). This class provides a `scrollIntoView(alignToTop?: boolean)` method that resolves to the appropriate child element when invoked on a fragment ref, enabling react scrollintoview behavior on non-DOM components.

## Deep Dive: React's FragmentInstance Implementation

### Core Implementation in ReactFiberConfigDOM.js

The `FragmentInstance` class in [`packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js`](https://github.com/facebook/react/blob/main/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js) implements the scroll behavior. The method signature accepts only a boolean `alignToTop` parameter (lines 53-71), diverging from the native API.

### Boolean-Only Parameter Constraints

Unlike standard DOM elements that accept an options object (e.g., `{behavior: 'smooth', block: 'center'}`), React's `FragmentInstance` implementation strictly validates the parameter and throws an error if you pass an object. According to lines 59-63 in [`ReactFiberConfigDOM.js`](https://github.com/facebook/react/blob/main/ReactFiberConfigDOM.js), only boolean values (`true` or `false`) are permitted.

### Child Resolution Logic

The implementation gathers the fragment's child fibers and applies different scrolling strategies based on the `alignToTop` value (lines 94-112):

- When `alignToTop` is `true`: Scrolls to the **last** child
- When `alignToTop` is `false` or omitted: Scrolls to the **first** child

### Handling Text Nodes and Empty Fragments

For `HostText` nodes (text children), React uses the **Range API** to calculate the bounding rectangle and scrolls the window directly (lines 98-107 in [`ReactFiberConfigDOM.js`](https://github.com/facebook/react/blob/main/ReactFiberConfigDOM.js)).

When a fragment has no children, the implementation falls back to the nearest host sibling or parent element (lines 72-88), ensuring the scroll operation still targets a valid DOM node.

## Practical React scrollIntoView Examples

### Scrolling a Standard DOM Element

For regular DOM elements, you can use the full native API including options objects:

```tsx
import React, { useRef } from 'react';

export default function SimpleScroll() {
  const divRef = useRef<HTMLDivElement>(null);

  const handleScroll = () => {
    // Native API supports options objects
    divRef.current?.scrollIntoView({ behavior: 'smooth', block: 'center' });
  };

  return (
    <>
      <button onClick={handleScroll}>Scroll to Target</button>
      <div
        ref={divRef}
        style={{ marginTop: '150vh', height: 100, background: '#a0e' }}
      >
        Target element
      </div>
    </>
  );
}

```

### Scrolling React Fragments with Multiple Children

When working with React Fragments, attach the ref to the Fragment and use the boolean parameter:

```tsx
import React, { Fragment, useRef, useState } from 'react';

export default function FragmentScrollDemo() {
  const fragmentRef = useRef<any>(null); // FragmentInstance
  const [alignToTop, setAlignToTop] = useState(true);

  const scroll = () => {
    // FragmentInstance.scrollIntoView resolves to the right child
    fragmentRef.current?.scrollIntoView(alignToTop);
  };

  return (
    <>
      <label>
        Align to top
        <input
          type="checkbox"
          checked={alignToTop}
          onChange={e => setAlignToTop(e.target.checked)}
        />
      </label>
      <button onClick={scroll}>Scroll fragment into view</button>

      <Fragment ref={fragmentRef}>
        <div style={{ height: 200, background: '#faa' }}>First child</div>
        <div style={{ height: 200, background: '#afa' }}>Second child</div>
        <div style={{ height: 200, background: '#aaf' }}>Third child</div>
      </Fragment>
    </>
  );
}

```

This example mirrors the official fixture in [`fixtures/dom/src/components/fixtures/fragment-refs/ScrollIntoViewCase.js`](https://github.com/facebook/react/blob/main/fixtures/dom/src/components/fixtures/fragment-refs/ScrollIntoViewCase.js) (lines 48-60).

### Auto-Scrolling on Data Updates

For chat interfaces or live feeds, combine `useEffect` with scrollIntoView:

```tsx
import React, { useEffect, useRef } from 'react';

export function AutoScrollList({ items }) {
  const bottomRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    // Whenever `items` changes, ensure the newest item is visible
    lastItemRef.current?.scrollIntoView({ block: 'end' }); // works because this is a plain DOM element
  }, [items]);

  return (
    <div>
      {items.map((it, i) => (
        <div
          key={it.id}
          ref={i === items.length - 1 ? lastItemRef : null}
          style={{ padding: '0.5rem' }}
        >
          {it.text}
        </div>
      ))}
    </div>
  );
}

```

Note that when scrolling a **plain element**, you can pass the full options object (e.g., `{block: 'end'}`) because it uses the native DOM API. The React fragment implementation only supports the boolean `alignToTop`.

## Key Implementation Details and Edge Cases

### Multiple Scroll Containers

When fragment children reside in different scroll containers, React walks the children in reverse order when `alignToTop` is `false`, ensuring each child inside a different scroll container receives the appropriate scroll call. This behavior is demonstrated in the [`ScrollIntoViewCase.js`](https://github.com/facebook/react/blob/main/ScrollIntoViewCase.js) fixture.

### Validation and Error Handling

The test suite in [`packages/react-dom/src/__tests__/ReactDOMFragmentRefs-test.js`](https://github.com/facebook/react/blob/main/packages/react-dom/src/__tests__/ReactDOMFragmentRefs-test.js) validates the strict contract:
- Passing an options object throws an error (lines 26-30)
- The first child is scrolled by default or when `alignToTop` is `true` (lines 61-68)
- The last child is scrolled when `alignToTop` is `false` (lines 70-77)

These tests confirm expected behavior across edge cases (lines 2113-2170).

## Summary

- **Standard DOM elements** support the full native `scrollIntoView` API, including options objects for smooth scrolling and block alignment.
- **React Fragments** expose a specialized `scrollIntoView(boolean)` method via `FragmentInstance` in [`ReactFiberConfigDOM.js`](https://github.com/facebook/react/blob/main/ReactFiberConfigDOM.js), which intelligently scrolls to the first or last child based on the boolean parameter.
- When calling `scrollIntoView` on a fragment, passing an options object throws an error; only `true` or `false` values are accepted.
- For text node children, React uses the Range API to calculate bounding rectangles, while empty fragments fall back to the nearest host sibling or parent.
- The official React repository provides comprehensive tests in [`ReactDOMFragmentRefs-test.js`](https://github.com/facebook/react/blob/main/ReactDOMFragmentRefs-test.js) and working examples in [`ScrollIntoViewCase.js`](https://github.com/facebook/react/blob/main/ScrollIntoViewCase.js) to validate these behaviors.

## Frequently Asked Questions

### Can I pass an options object to scrollIntoView in React fragments?

No. Unlike standard DOM elements that accept an options object (e.g., `{behavior: 'smooth', block: 'center'}`), React's `FragmentInstance` implementation in [`packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js`](https://github.com/facebook/react/blob/main/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js) strictly validates the parameter and throws an error if you pass an object (lines 59-63). Only boolean values (`true` or `false`) are permitted when working with fragment refs.

### How does React handle scrollIntoView on fragments with no children?

When a fragment has no children, the implementation in [`ReactFiberConfigDOM.js`](https://github.com/facebook/react/blob/main/ReactFiberConfigDOM.js) (lines 72-88) falls back to the nearest host sibling or parent element. This ensures that the scroll operation still targets a valid DOM node even when the fragment is empty, maintaining predictable behavior across different component trees.

### Why does my fragment scroll to the last child instead of the first?

React's `FragmentInstance.scrollIntoView` method uses the boolean parameter to determine scroll direction, but the logic may seem counterintuitive. According to the implementation in [`ReactFiberConfigDOM.js`](https://github.com/facebook/react/blob/main/ReactFiberConfigDOM.js) (lines 94-112), when `alignToTop` is `true`, React scrolls to the **last** child; when `false` or omitted, it scrolls to the **first** child. This aligns with the native DOM `scrollIntoView(true)` convention where `true` aligns the element to the top of the viewport.

### Is React scrollIntoView supported in all browsers?

The `scrollIntoView` functionality for standard DOM elements works in all modern browsers that support the native DOM API. For React's fragment-specific implementation (`FragmentInstance`), support depends on the React version—this feature is part of the fragment refs API available in recent React releases. The implementation uses standard browser APIs like the Range API for text nodes, ensuring compatibility across modern browsers including Chrome, Firefox, Safari, and Edge.