logo

もっと見るボタン付近だけいい感じに透過グラデーションする

2024-02-04
10 months ago

開発環境

  • next 14.0.4
  • tailwind 3.4.1

前提

コンテンツ中身の高さに応じて「もっと見る」ボタンを出し分けるカスタムフックを実装します。

加えて、「もっと見る」ボタンとコンテンツの間あたりにいい感じの透過グラデーションを入れます。

本題

完成イメージはこちら

containerRefを渡した要素の、中のコンテンツの高さがmax-heightを超えた場合にisOverflowingtrueで返すHooksを実装します。

また、「もっと見る」ボタンを押下した際にコンテンツをmax-heightいっぱいに広げる関数とstateも一緒に返します。

'use client';

import { useCallback, useEffect, useRef, useState } from 'react';

export const useScrollSize = () => {
  const [isOverflowing, setIsOverflowing] = useState(false);
  const [isShowAll, setIsShowAll] = useState(false);
  const containerRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const container = containerRef.current;
    if (!container) return;

    const checkOverflow = () => {
      const isContentOverflowing =
        container.scrollHeight > container.clientHeight;
      setIsOverflowing(isContentOverflowing);
    };

    checkOverflow();
    window.addEventListener('resize', checkOverflow);

    return () => {
      window.removeEventListener('resize', checkOverflow);
    };
  }, []);

  const open = useCallback(() => setIsShowAll(true), []);

  return { isOverflowing, containerRef, open, isShowAll };
};
use-scroll-size.ts

そして以下はHooksを利用する例です。

'use client'

import type { ReactNode } from 'react'

import { useScrollSize } from '@/hooks/use-scroll-size'

type ContainerSampleProps = {
  children: ReactNode
}

export const ContainerSample = ({ children }: ContainerSampleProps) => {
  const { containerRef, isOverflowing, isShowAll, open } = useScrollSize()

  return (
    <div className='container bg-white py-6'>
      <div
        className={`
          relative flex w-full overflow-y-hidden p-8
          ${isShowAll ? 'h-full' : 'max-h-60'}
        `}
        ref={containerRef}
      >
        {children}
        {isOverflowing && !isShowAll && (
          <div className='absolute bottom-0 z-10 h-12 w-11/12 bg-gradient-to-b from-white/40 to-white/90' />
        )}
      </div>
      {isOverflowing && !isShowAll && (
        <div className='py-4 text-center'>
          <button className='hover:underline' onClick={open}>
            もっと見る
          </button>
        </div>
      )}
    </div>
  )
}
container-sample.tsx

さいごに

一定の高さで要素の表示/非表示を切り替える実装はよくありますが、そこにプラスアルファで「まだ要素が下にあるよ」というレイアウト実装例です。

tailwindでもっと良いやり方があれば知りたい・・

参照