
Next.js, TailwindCSSでscroll-behaviorを使い分ける

IT技術

はじめに
スムーズスクロール対応のため、html要素にscroll-behavior: smooth;
のclass(以下、TailwindCSSのscroll-smooth)を付与したい時があります。ただ、scroll-behavior: auto;
を使いたいページを要求されたらどうするか心配になるものです。
Next.js App router
Next.js App routerでは<html>
タグをroot layoutで記述する必要がありますが、Route Groupsを使い複数のroot layoutをを用いることができます。
1app
2├── (scroll-auto)
3│ └── layout.tsx
4└── (scroll-smooth)
5 └── layout.tsx
Next.js Pages router
Next.js Pages routerではCustom Documentで<html>
のclassを付与できます。 しかし、アプリで使えるCustom Documentは1つのみです。
迂回策: クライアントでhtmlのclassを修正するコンポーネントで対応する
クライアントでhtmlのclassを上書きすることでもよければ、以下のようなコンポーネントを対応ページに入れることで対応できます。cleanup関数にscroll-smooth
を戻すことで、こちらのコンポーネントがあるページのみscroll-smooth
の反映されず対応できます。
1export const RemoveScrollSmooth = () => {
2 useEffect(() => {
3 document.documentElement.classList.remove("scroll-smooth");
4
5 return () => {
6 document.documentElement.classList.add("scroll-smooth");
7 };
8 }, []);
9
10 return null
11};
番外: htmlをラッピングし、useStateとContext APIで制御する
Next.js Pages routerでは使えないですが、App routerなどで複数のlayout対応するまでも無いのであり、直接DOM操作したく無いことであれば、htmlをラッピングし、中でscroll behaviorのclassを状態として管理することもできます。<RemoveScrollSmooth />
と同様に、<ScrollAuto />
をscroll-auto
を適用したいページに入れると<ScrollAuto />
が含まれている箇所のみクライアント側でclassを更新します。
1"use client";
2
3import {
4 ComponentPropsWithoutRef,
5 createContext,
6 Dispatch,
7 SetStateAction,
8 useContext,
9 useEffect,
10 useState,
11} from "react";
12
13export const SetScrollClassNameContext = createContext<
14 Dispatch<SetStateAction<string>>
15>(() => {
16 console.warn("ScrollClassNameContext used outside of provider");
17});
18
19export default function Html({
20 children,
21 lang,
22}: ComponentPropsWithoutRef<"html">) {
23 const [scrollClassName, setScrollClassName] = useState("scroll-smooth");
24
25 return (
26 <SetScrollClassNameContext value={setScrollClassName}>
27 <html lang={lang} className={scrollClassName}>
28 {children}
29 </html>
30 </SetScrollClassNameContext>
31 );
32}
33
34export const ScrollAuto = () => {
35 const setScrollClassName = useContext(SetScrollClassNameContext);
36
37 useEffect(() => {
38 setScrollClassName("scroll-auto");
39
40 return () => {
41 setScrollClassName("scroll-smooth");
42 };
43 }, [setScrollClassName]);
44
45 return null;
46};
最後まで読んでいただきありがとうございます。何か皆様の生活に役に立つところがあったら幸いです。
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ

Webアプリケーションの開発をしています。