1
/
5

Reactでクリック時に該当セクションへスムーズスクロールする実装方法


目次

  • はじめに

  • 実装の背景

  • 実装方法

  • 1. イニシャルボタンの作成

  • 2. スクロール先の要素にIDを付与

  • 3. スムーズスクロールの実装

  • 4. モーダルからのイニシャル選択(モバイル対応)

  • 5. 全体のコード

  • 注意点

  • まとめ


はじめに

こんにちは、READY TO FASHIONの開発チームの片桐です。現在はブランドの一覧ページを実装しています。
弊社のサービスでは、ユーザーがブランド一覧をより快適に閲覧できるように、イニシャル(頭文字)をクリックすると、そのイニシャルに対応するブランドリストの部分までスムーズにスクロールする機能を実装しました。

今回は、その実装方法とポイントについてご紹介します。

実装の背景

ブランド一覧ページでは、多数のブランドがアルファベット順に表示されており、ユーザーが目的のブランドを探しやすくするために、イニシャルごとのナビゲーションを提供しています。

従来は、イニシャルをクリックするとページが即座にジャンプしていましたが、ユーザー体験を向上させるために、スムーズスクロールを導入することにしました。





実装方法

1. イニシャルボタンの作成

まず、イニシャル(A-Zおよび「その他」)のボタンを生成します。

renderInitialButtons() {
const initials = [...Object.keys(this.state.groupedIds)].sort()

return (
<div className='brands-list__initials'>
{initials.map(initial => (
<button
key={initial}
className={`brands-list__initial-button ${this.state.selectedInitial === initial ? 'active' : ''}`}
onClick={() => this.handleInitialClick(initial)}>
{initial}
</button>
))}
</div>
)
}

2. スクロール先の要素にIDを付与

ブランドリストをイニシャルごとにグループ化し、それぞれのグループに対応するIDを設定します。

renderBrandGroups() {
return (
<div className='brands-list__groups'>
{Object.keys(this.state.groupedIds).sort().map(initial => (
<div key={initial} className='brands-list__group' id={`group-${initial}`}>
<h2 className='brands-list__group-title'>
{initial}
<span>{this.state.groupedIds[initial].length}</span>
</h2>
</div>
))}
</div>
)
}

3. スムーズスクロールの実装

イニシャルボタンがクリックされたときに、対応するセクションまでスムーズにスクロールします。

handleInitialClick(initial) {
this.setState({ selectedInitial: initial })
const element = document.getElementById(`group-${initial}`)
if (element) {
element.scrollIntoView({ behavior: 'smooth', block: 'start' })
}
}

scrollIntoViewメソッドのbehaviorオプションに'smooth'を指定することで、スムーズスクロールを実現しています。

4. モーダルからのイニシャル選択(モバイル対応)

モバイルデバイスでは、画面幅の関係でイニシャルボタンを横に並べることが難しいため、モーダルを使用してイニシャルを選択できるようにしています。

handleSelectInitial(initial) {
this.setState({ selectedInitial: initial, isModalOpen: false })
const element = document.getElementById(`group-${initial}`)
if (element) {
element.scrollIntoView({ behavior: 'smooth', block: 'start' })
}
}

5. 全体のコード

上記のポイントを踏まえた全体のコードは以下のようになります。

class BrandsList extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedInitial: null,
groupedIds: {},
isModalOpen: false
}
}

componentDidMount() {
this.fetchGroupedBrandIds();
}

// 処理を軽くするためバックエンド側でデータの処理を記載し、apiで取得
fetchGroupedBrandIds() {
fetch('/api/v1/brands/grouped_brand_ids_by_initial', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
credentials: 'same-origin'
})
.then(response => response.json())
.then(data => {
this.setState({ groupedIds: data.grouped_ids });
});
}

handleInitialClick(initial) {
this.setState({ selectedInitial: initial });
const element = document.getElementById(`group-${initial}`);
if (element) {
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
}

handleSelectInitial(initial) {
this.setState({ selectedInitial: initial, isModalOpen: false });
const element = document.getElementById(`group-${initial}`);
if (element) {
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
}

handleModalOpen() {
this.setState({ isModalOpen: true });
}

handleModalClose() {
this.setState({ isModalOpen: false });
}

renderInitialButtons() {
// 前述のコードを参照
}

renderBrandGroups() {
// 前述のコードを参照
}

render() {
return (
<div className='brands-list'>
{this.renderInitialButtons()}
{this.renderBrandGroups()}
<BrandModal
isOpen={this.state.isModalOpen}
onClose={() => this.handleModalClose()}
onSelectInitial={(initial) => this.handleSelectInitial(initial)}
/>
</div>
)
}
}
  • scrollIntoViewメソッド:特定のDOM要素が見える位置までスクロールします。behavior: 'smooth'を指定することで、スムーズなアニメーションになります。
  • アクセシビリティの向上:スムーズスクロールにより、ユーザーは現在のページ内で移動していることが視覚的に理解しやすくなります。
  • モバイル対応:モバイルデバイスではモーダルを使用してイニシャルを選択できるようにし、同じロジックでスムーズスクロールを実現しています。

注意点

  • ブラウザの互換性scrollIntoViewbehaviorオプションは一部の古いブラウザではサポートされていない可能性があります。必要に応じてポリフィルを検討してください。

まとめ

今回は、Reactでイニシャルをクリックした際に対応するセクションまでスムーズにスクロールする機能の実装方法をご紹介しました。scrollIntoViewメソッドを活用することで、シンプルなコードでユーザー体験を向上させることができます。

ユーザーがブランド一覧を快適に閲覧できるよう、今後も機能の改善を続けていきます。

READY TO FASHIONでは一緒に働くエンジニアを募集しています!
ファッションに興味があるエンジニアのご応募お待ちしております!


Railsエンジニア
ファッション×採用を加速させる!Railsエンジニア募集!
2016年11月に創業。ファッション業界特化の求人プラットフォーム「READY TO FASHION」を開発・運営するスタートアップです。 弊社は、若者や既存の枠を超える「人」の力によって、旧態依然としたファッション業界の変革を促進し、「業界に従事する人」や「ファッションを楽しむ人」の生活を豊かにすることを目指しています。 そのために、採用におけるコミュニケーションだけでなく、業界のコミュニケーションにおける課題をITの力で解決し続けます。 【主な事業内容】 ・求人メディア事業 ファッション業界特化の求人プラットフォーム「READY TO FASHION」 https://www.readytofashion.jp 弊社のメイン事業。2017年3月にプロダクトをリリースし、現在は900社を超えるファッション企業、50000人以上のユーザーに登録していただいております。アパレル業界だけでなく、広義的にファッションを扱う企業情報を掲載。 ・CtoCマッチング事業 ファッションビジネスマッチングアプリ「fatch」 2019年2月ローンチ:https://www.readytofashion.jp/lp/fatch ・メディア事業 ファッション好きな若者のためのWEBマガジン「READY TO FASHION MAG」 https://www.readytofashion.jp/mag/ ・コミュニティー|学生マーケティング事業 ファッション系学生団体の組織「fashion community 1.0」 https://www.readytofashion.jp/mag/fashioncommunity1_0.html ・イベント事業 株式会社 三越伊勢丹と共催の『DENIM ACT NIGHT(デニムアクトナイト)』 https://www.readytofashion.jp/mag/news/denim_act_night_201803/
READY TO FASHION
フロントエンドエンジニア
ファッション×HRを加速させるフロントエンドエンジニア募集!
2016年11月に創業。ファッション業界特化の求人プラットフォーム「READY TO FASHION」を開発・運営するスタートアップです。 弊社は、若者や既存の枠を超える「人」の力によって、旧態依然としたファッション業界の変革を促進し、「業界に従事する人」や「ファッションを楽しむ人」の生活を豊かにすることを目指しています。 そのために、採用におけるコミュニケーションだけでなく、業界のコミュニケーションにおける課題をITの力で解決し続けます。 【主な事業内容】 ・求人メディア事業 ファッション業界特化の求人プラットフォーム「READY TO FASHION」 https://www.readytofashion.jp 弊社のメイン事業。2017年3月にプロダクトをリリースし、現在は900社を超えるファッション企業、50000人以上のユーザーに登録していただいております。アパレル業界だけでなく、広義的にファッションを扱う企業情報を掲載。 ・CtoCマッチング事業 ファッションビジネスマッチングアプリ「fatch」 2019年2月ローンチ:https://www.readytofashion.jp/lp/fatch ・メディア事業 ファッション好きな若者のためのWEBマガジン「READY TO FASHION MAG」 https://www.readytofashion.jp/mag/ ・コミュニティー|学生マーケティング事業 ファッション系学生団体の組織「fashion community 1.0」 https://www.readytofashion.jp/mag/fashioncommunity1_0.html ・イベント事業 株式会社 三越伊勢丹と共催の『DENIM ACT NIGHT(デニムアクトナイト)』 https://www.readytofashion.jp/mag/news/denim_act_night_201803/
READY TO FASHION


READY TO FASHIONからお誘い
この話題に共感したら、メンバーと話してみませんか?
READY TO FASHIONでは一緒に働く仲間を募集しています

今週のランキング

片桐 俊さんにいいねを伝えよう
片桐 俊さんや会社があなたに興味を持つかも