---
title: "Прокручиваемые вкладки в React без Material UI"
description: "Прокручиваемые вкладки в React с нативной прокруткой: активная вкладка центрируется сама, стрелки появляются только когда нужны, произвольное содержимое вкладок. Живая демонстрация и код."
canonical: "https://react-horizontal-scrolling-menu.dev/ru/scrollable-tabs"
image: "https://react-horizontal-scrolling-menu.dev/og.png"
---

# Прокручиваемые вкладки React, которые прокручиваются как браузер

Полоса вкладок перестаёт помещаться, как только в продукте становится больше шести вкладок. Решение — не уменьшать шрифт, а сделать полосу прокручиваемой: переполнение обрабатывает браузер, клик по вкладке центрирует её, а стрелки появляются только тогда, когда есть куда прокручивать.

Overview

Getting started

Visibility

Arrows

Drag to scroll

RTL

apiRef

Helpers

TypeScript

Testing

Changelog

FAQ

Кликните по вкладке у края — она сама прокрутится к центру.

[Редактировать этот пример вживую в Storybook](https://asmyshlyaev177.github.io/react-horizontal-scrolling-menu/?path=/story/examples-centeronclick--center-on-click)

## Единственное важное поведение: центрирование при выборе

Судьба прокручиваемой полосы вкладок решается тем, что происходит при клике по вкладке у края: она должна плавно переместиться к середине, открывая соседей с обеих сторон. Здесь это один вызов — `scrollToItem(el, 'smooth', 'center')` — реализованный в [примере center-on-click](https://react-horizontal-scrolling-menu.dev/ru/examples/center-on-click.md). Восстановление активной вкладки при монтировании — тот же вызов с `'auto'`, показанный в [примере сохранения и восстановления позиции](https://react-horizontal-scrolling-menu.dev/ru/examples/save-restore-position.md).

Стрелки берут те же данные о видимости: `useLeftArrowVisible` равно false, только пока первая вкладка вне экрана, поэтому левая стрелка рендерится именно тогда, когда она полезна. Никакого кода измерений и собственных resize-обсерверов не нужно.

## Если вам стало тесно в прокручиваемых вкладках MUI

Вкладки Material UI с `variant="scrollable"` — правильный выбор внутри дизайн-системы Material, пока ваши «вкладки» остаются вкладками. MUI жёстко привязывает полосу к семантике Tabs: пара `value`/`onChange`, панели вкладок и кнопки прокрутки, которые MUI по умолчанию скрывает на мобильных устройствах. Как только в ряду появляются чипы, карточки, аватары или смешанный контент, или требуется перетаскивание для прокрутки, или нужно знать, какие элементы видны, — вы уже боретесь с компонентом, а не используете его.

Эта библиотека — слой уровнем ниже: прокручиваемый ряд с отслеживанием видимости, без каких-либо представлений о том, что такое «вкладка». Ваша вкладка — это любой компонент с `itemId`: стилизуйте его через Tailwind, собственный `styled` из MUI или обычный CSS. Состояние выбора остаётся вашим — точно так же демо выше хранит его в одном `useState`.

## Доступность почти бесплатна — учтите два пробела

Поскольку полоса — это нативный контейнер прокрутки, фокус клавиатуры, порядок чтения для скринридеров и RTL обеспечивает сама платформа: перемещение фокуса по вкладкам без единой строки кода прокручивает их в область видимости, а [RTL](https://react-horizontal-scrolling-menu.dev/ru/examples/rtl.md) не требует никакой настройки. Как и в любом UI с вкладками, на вас остаются две вещи: выбрать паттерн ARIA (`role="tablist"`, если переключаются настоящие панели, `aria-current`, если «вкладки» — это навигация), и сохранить подавление кликов из рецепта [drag-to-scroll](https://react-horizontal-scrolling-menu.dev/ru/examples/mouse-drag.md), чтобы отпускание перетаскивания никогда не активировало вкладку.

## Паттерн в минимальном виде

Вкладки — это обычные кнопки с `itemId`; выбор одной центрирует её. В этом вся идея — демо выше добавляет стилизацию и перетаскивание.

ScrollTabs.tsx

```
function ScrollTabs({ tabs }: { tabs: string[] }) {
  const [active, setActive] = React.useState(tabs[0]);
  return (
    <ScrollMenu LeftArrow={LeftArrow} RightArrow={RightArrow}>
      {tabs.map((tab) => (
        <Tab itemId={tab} key={tab} label={tab}
          active={tab === active} onSelect={() => setActive(tab)} />
      ))}
    </ScrollMenu>
  );
}

function Tab({ itemId, label, active, onSelect }: TabProps) {
  const api = React.useContext<publicApiType>(VisibilityContext);
  return (
    <button
      aria-current={active}
      onClick={(ev) => {
        onSelect();
        // The behavior that makes tabs feel native: selecting an
        // edge tab glides it to the center of the strip.
        api.scrollToItem(ev.currentTarget, 'smooth', 'center');
      }}
    >
      {label}
    </button>
  );
}
```

## Или установите как компонент shadcn

Элемент реестра [scroll-tabs](https://react-horizontal-scrolling-menu.dev/r/scroll-tabs.json) реализует этот паттерн на основе данных — передайте `tabs`, `value`, `onValueChange` — в виде редактируемого компонента в вашей `components/ui/`:

shadcn

```
npx shadcn@latest add https://react-horizontal-scrolling-menu.dev/r/scroll-tabs.json
```

## Похожие примеры

-   [Центрировать кликнутый элементscrollToItem с inline: center — паттерн прокручиваемых вкладок.](https://react-horizontal-scrolling-menu.dev/ru/examples/center-on-click.md)
-   [Сохранение и восстановление позиции прокруткиСохраняйте смещение прокрутки между размонтированиями и перезагрузками.](https://react-horizontal-scrolling-menu.dev/ru/examples/save-restore-position.md)
-   [Прокрутка перетаскиванием мышьюПеретаскивание мышью, которое не ломает клики по элементам.](https://react-horizontal-scrolling-menu.dev/ru/examples/mouse-drag.md)

[Все примеры (21)](https://react-horizontal-scrolling-menu.dev/ru/examples.md)

---

More examples: <https://react-horizontal-scrolling-menu.dev/examples.md>
Library summary for LLMs: <https://react-horizontal-scrolling-menu.dev/llms.txt>
