2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Reactで横スクロールボタンを実装する

2
Last updated at Posted at 2026-03-31

useRef は、値を保持するためのフックですが、Reactでは特に
DOM要素を直接参照したいときによく使います。

たとえば、

  • input に自動でフォーカスを当てる
  • スクロール位置を動かす
  • 要素の幅や高さを取得する

今回は横スクロールをボタンで動かす例を使います。

useRefを使う流れ

  1. useRef(null) を作る
  2. スクロールしたい要素に ref={scrollRef} を付ける
  3. scrollRef.current から実際のDOM要素を取得する
  4. scrollBy() を使ってスクロールを動かす
import React, { useRef } from "react";
import { css } from "@panda/css";

const wrapper = css({
  width: "100%",
  padding: "24px",
  background: "#f8fafc",
  borderRadius: "20px",
});

const buttons = css({
  display: "flex",
  justifyContent: "space-between",
  marginBottom: "8px",
});

const button = css({
  padding: "16px 24px",
  border: "none",
  borderRadius: "9999px",
  background: "#1e293b",
  color: "#ffffff",
  fontSize: "14px",
  fontWeight: "600",
  cursor: "pointer",
  transition: "opacity 0.2s ease",
  _hover: {
    opacity: 0.85,
  },
});

const scrollArea = css({
  overflowX: "auto",
  padding: "8px",
  borderRadius: "16px",
  scrollbarWidth: "none",
  "&::-webkit-scrollbar": {
    display: "none",
  },
});

const cardList = css({
  display: "flex",
  gap: "16px",
  width: "max-content",
});

const card = css({
  width: "260px",
  minHeight: "160px",
  padding: "20px",
  background: "#ffffff",
  borderRadius: "18px",
  boxShadow: "0 8px 24px rgba(15, 23, 42, 0.08)",
  border: "1px solid #e2e8f0",
  flexShrink: 0,
});

const cardTitle = css({
  margin: "0 0 12px",
  fontSize: "18px",
  fontWeight: "700",
  color: "#0f172a",
});

const cardText = css({
  margin: 0,
  fontSize: "14px",
  lineHeight: "1.7",
  color: "#475569",
});

const sampleProjects = [
  { id: 1, title: "案件1", description: "社内SEの募集です。" },
  { id: 2, title: "案件2", description: "RPAエンジニアの募集です。" },
  { id: 3, title: "案件3", description: "ネットワーク運用の募集です。" },
  { id: 4, title: "案件4", description: "フロントエンド開発の募集です。" },
];

const UseRefSample = () => {
  const scrollRef = useRef(null);

  const scrollToLeft = () => {
    const el = scrollRef.current;
    if (!el) return;

    el.scrollBy({
      left: -276,
      behavior: "smooth",
    });
  };

  const scrollToRight = () => {
    const el = scrollRef.current;
    if (!el) return;

    el.scrollBy({
      left: 276,
      behavior: "smooth",
    });
  };

  return (
    <div className={wrapper}>
      <div className={buttons}>
        <button type="button" className={button} onClick={scrollToLeft}>
          ← 左へ
        </button>
        <button type="button" className={button} onClick={scrollToRight}>
          右へ →
        </button>
      </div>

      <div ref={scrollRef} className={scrollArea}>
        <div className={cardList}>
          {sampleProjects.map((project) => (
            <div key={project.id} className={card}>
              <h2 className={cardTitle}>{project.title}</h2>
              <p className={cardText}>{project.description}</p>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};

export default UseRefSample;

上記のコードでは、

  • スクロールボタン
  • 案件が書かれたカード(横に並ぶ)

UIとして作成しています。

image.png

「右へ」ボタンを押すと、右にスクロールされます。

image.png

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?