---
title: "Dải cuộn ngang kiểu Netflix trong React"
description: "Xây dựng dải danh mục kiểu Netflix trong React với cuộn gốc trình duyệt: mũi tên khi hover, mờ dần ở cạnh, kéo để cuộn, theo dõi khả năng hiển thị. Demo trực tiếp và mã nguồn đầy đủ."
canonical: "https://react-horizontal-scrolling-menu.dev/vi/netflix-row"
image: "https://react-horizontal-scrolling-menu.dev/og.png"
---

# Dải cuộn ngang kiểu Netflix trong React

Dải áp phích bạn lướt qua trên mọi trang xem phim trực tuyến không phải là carousel — đó là một menu. Không có gì snap, không có gì tự phát; nó chạy trên cuộn quán tính gốc của trình duyệt với các mũi tên phủ lên trên. Đó chính xác là những gì `react-horizontal-scrolling-menu` cung cấp: thẻ của bạn, cuộn gốc, và khả năng hiển thị theo từng item để mũi tên biết khi nào cần ẩn.

Sci-Fi

Comedy

Drama

Horror

Docs

Kids

Action

Indie

Anime

Classics

Thriller

Reality

Kéo nó, hoặc di chuột qua dải — các mũi tên mờ dần hiện lên ở các cạnh, và mỗi mũi tên biến mất khi đến đầu dải tương ứng.

[Chỉnh sửa ví dụ này trực tiếp trong Storybook](https://asmyshlyaev177.github.io/react-horizontal-scrolling-menu/?path=/story/examples-mousedrag--mouse-drag)

## Tại sao đây không phải là việc của carousel

Dải Netflix không bao giờ hiển thị từng slide một lúc. Các item bị cắt một phần ở các cạnh một cách có chủ ý — tấm áp phích bị cắt là tín hiệu thị giác nói rằng "còn nữa". Các engine carousel chống lại điều này: chúng chiếm lấy tầng cử chỉ bằng các phép biến đổi JavaScript, snap vào ranh giới slide, và tái triển khai quán tính mà trình duyệt của người dùng vốn đã có sẵn. Trên một dải thẻ có thể nhấp, tất cả những điều đó là chi phí thừa.

Cuộn gốc cho bạn quán tính, cảm ứng, trackpad và thanh cuộn miễn phí. Hai thứ nó không cho bạn là mũi tên phủ lên và biết thẻ nào đang trên màn hình — và đó chính là hai thứ thư viện này bổ sung, thông qua [`useIsVisible`](https://react-horizontal-scrolling-menu.dev/vi/examples/simple.md) cho từng item và trạng thái mũi tên nhận biết cạnh.

## Ba chi tiết làm nên hiệu ứng

-   **Mũi tên phủ lên nội dung**, không nằm cạnh nó. Hiển thị chúng với vị trí tuyệt đối trên các đầu dải (demo ở trên truyền chúng qua `Header` để chúng ở trong ngữ cảnh của menu), hiện chúng khi hover, và ẩn từng mũi tên khi [`useLeftArrowVisible` / `useRightArrowVisible`](https://react-horizontal-scrolling-menu.dev/vi/examples/simple.md) báo rằng đầu dải đó đã đạt tới.
-   **Các cạnh mờ dần.** Một dòng CSS — gradient `mask-image` trên vùng chứa cuộn — thay thế logic "hé lộ" mà các plugin carousel cung cấp cho việc này.
-   **Kéo không được kích hoạt click.** Một thao tác kéo chuột kết thúc trên một áp phích không được mở nó. [Công thức kéo để cuộn](https://react-horizontal-scrolling-menu.dev/vi/examples/mouse-drag.md) theo dõi trạng thái kéo và nuốt chính xác cú click đó.

## Mở rộng quy mô: dải lười tải và rail dài

Giao diện xem phim trực tuyến xếp chồng hàng chục dải với hàng trăm thẻ. Vì các item là DOM thuần trong một vùng chứa cuộn gốc, không có gì render lại khi cuộn — [ví dụ hiệu năng](https://react-horizontal-scrolling-menu.dev/vi/examples/performance.md) chạy 300 item mà không cần virtualization. Khả năng hiển thị theo từng item cũng cho bạn lazy-loading ảnh miễn phí: render một placeholder cho đến khi `useIsVisible` báo thẻ đã lên màn hình.

Nếu dải của bạn cần quay vòng ở cuối, đó là nơi duy nhất mà ngữ nghĩa slide thực sự hữu ích — xem [công thức vòng lặp vô hạn](https://react-horizontal-scrolling-menu.dev/vi/examples/infinite-loop.md) cho phiên bản userland ~60 dòng trước khi tìm đến một engine carousel.

## Mẫu hình, tối giản

Phủ mũi tên lên một dải cuộn gốc — demo ở trên chính là cấu trúc này cộng với styling. Mã nguồn drop-in hoàn chỉnh, có kéo và mờ cạnh, được cung cấp dưới dạng component shadcn bên dưới.

MediaRow.tsx

```
function MediaRow({ children }: { children: React.ReactNode }) {
  return (
    <div className="group relative">
      <ScrollMenu Header={<OverlayArrows />} wrapperClassName="edge-fade">
        {children}
      </ScrollMenu>
    </div>
  );
}

// Rendered as Header, so it lives inside the menu's VisibilityContext
// and can sit absolutely positioned over the row ends.
function OverlayArrows() {
  const api = React.useContext<publicApiType>(VisibilityContext);
  const atStart = api.useLeftArrowVisible();
  const atEnd = api.useRightArrowVisible();
  return (
    <>
      <button
        className="overlay-arrow left-0"
        hidden={atStart}
        onClick={() => api.scrollPrev()}
      >
        ←
      </button>
      <button
        className="overlay-arrow right-0"
        hidden={atEnd}
        onClick={() => api.scrollNext()}
      >
        →
      </button>
    </>
  );
}

/* .edge-fade — the Netflix edge, one CSS line:
   mask-image: linear-gradient(to right,
     transparent, black 40px, black calc(100% - 40px), transparent); */
```

## Hoặc cài đặt nó như một component shadcn

Registry item [media-row](https://react-horizontal-scrolling-menu.dev/r/media-row.json) chính là mẫu hình này — mũi tên khi hover, mờ dần cạnh bằng gradient, kéo để cuộn — dưới dạng component được style bằng Tailwind trong `components/ui/` của bạn, sẵn sàng để bạn chỉnh sửa:

shadcn

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

## Các ví dụ liên quan

-   [Kéo để cuộn bằng chuộtKéo chuột mà vẫn để các cú bấm mục hoạt động.](https://react-horizontal-scrolling-menu.dev/vi/examples/mouse-drag.md)
-   [Vòng lặp vô hạnVòng lặp liền mạch từ API công khai — không thay đổi thư viện.](https://react-horizontal-scrolling-menu.dev/vi/examples/infinite-loop.md)
-   [5,000 mục và vẫn nhanhCuộn gốc mở rộng được — không cần ảo hóa ở đây.](https://react-horizontal-scrolling-menu.dev/vi/examples/performance.md)

[Tất cả 21 ví dụ](https://react-horizontal-scrolling-menu.dev/vi/examples.md)

---

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