👷

React Hooksで小さいサイズのスマホへ対応する

2022/07/04に公開

ファンタラクティブのエンジニアの 太田 です。
Webサイトで小さいデバイスへの対応をReactのhooksを使って行う方法を紹介します。

課題

最近のスマートフォンの画面サイズは数年前とくらべ大きくなり、400pxを超えるものもめずらしくありません。
Androidに比べ比較的小さいiPhoneに関しても、現在発売されているものは375pxが最小です。
しかし第一世代のiPhoneSEは320pxであったり、360pxのAndroidも全体の割合としては多くないもののまだまだ使われています。
折りたたみ式の最新のスマートフォンも折りたたんだ状態では小さいサイズのものがあるかもしれません。

しかし、小さいサイズのデバイスを考慮してデザイン、実装することは結構たいへんです。
全体からみると小さい割合のデバイスへの対応を簡単に行ってしまう設計とReact Hooksの実装例を紹介します。


主要なサイズのスマートフォンを対象に作ったデザインを小さいサイズのデバイスに当てはめるとスタイルが崩れる

考えられる対応方法

今回の紹介する方法の他に考えられる対応方法をみていきます

小さいサイズのデバイス用のデザインを別途用意する

  • デザインに時間がかかる
  • breakpointが増え実装が複雑になる

小さいサイズのデバイスに合わせてスマートフォンの画面デザインをする

  • デザインの制約が大きくなる
  • 全体の割合が大きいサイズのデザインが小さいサイズのデザインに依存してしまう

どちらもそれぞれ小さくない課題が残ります。
また考慮した最小サイズよりさらに小さいサイズのデバイスが登場したら追加で対応が必要になります。

この記事で紹介する方法

主要なデバイス内で最小のサイズでデザインを行い、それ以下のサイズのデバイスの場合は縮小して表示する。

今回紹介する方法は一度実装してしまえば、それ以上のメンテナンスは必要なく小さいサイズ用のデザインを用意する必要もないため、上記で紹介した案の課題をクリアしています。[1]

React Hooks

今回は思い切って375px以下は縮小する例とします。

サンプルコード[2]

useViewport.ts
import { useLayoutEffect, useState } from 'react'

const MIN_DEVICE_WIDTH = 375

const getViewport = ({ width }: { width: string }) => {
  return `width=${width},initial-scale=1.0,maximum-scale=1.0`
}

export const useViewport = () => {
  const [viewport, setViewport] = useState<string>(
    'width=device-width,initial-scale=1.0,maximum-scale=1.0'
  )

  useLayoutEffect(() => {
    setViewport(
      getViewport({
        width: `${
          window.outerWidth > MIN_DEVICE_WIDTH
            ? 'device-width'
            : MIN_DEVICE_WIDTH // 最小サイズ以下の場合は最小サイズのスタイルを縮小表示
        }`,
      })
    )
  }, [])

  return { viewport }
}
_app.tsx
import Head from 'next/head'

import { useViewport } from '@/hooks/utils'

function MyApp({ Component, pageProps }) {
  const { viewport } = useViewport()

  return (
    <>
      <Head>
        <meta name="viewport" content={viewport} />
      </Head>
      <Component {...pageProps} />
    </>
  )
}

export default MyApp

出力

主要なサイズのデバイスの場合

<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0">

小さいサイズのデバイスの場合

<meta name="viewport" content="width=375,initial-scale=1.0,maximum-scale=1.0">

あとがき

あらゆるデバイスに対して最適に表示できるように対応できれば最高ですが、複雑になればなるほど多くのリソースを必要とし開発のスピードを失うことになると思います。
今回紹介したようなシンプルな方法で対応し、別の重要なことにリソースをかけることができれば幸せになれそうだと思いました。

脚注
  1. 縮小されるので小さいサイズのデバイスで見ると少し見づらいかもしれない ↩︎

  2. windowサイズのリサイズに対応したい場合は、別途EventListenerでリサイズを検知しinnerWidthを返すようなhooksを作ると対応できます。 ↩︎

ファンタラクティブテックブログ

Discussion