TL;DR
この記事では、Next.js と TypeScript を用いて、Emotion Media Queries を使う方法を説明します。Media Queries を活用することで、異なるデバイスサイズに対応したレスポンシブなデザインを実現できます。
開発環境 | バージョン |
---|---|
Next.js | 13.4.3 |
TypeScript | 5.0.4 |
Emotion | 11.11.0 |
React | 18.2.0 |
Media Queries とは?
Media Queries は CSS の一部で、デバイスの特性や状況に基づいてスタイルを適用するための技術です。例えば、スクリーンの幅や高さ、方向(ランドスケープまたはポートレート)、解像度などに応じて異なるスタイルを適用することができます。これにより、ある範囲のビューポートサイズで特定のスタイルを適用することが可能になり、レスポンシブデザインを実現できます。
Next.js での Media Queries の使い方
Next.js では、Emotion を使って Media Queries を使用することができます。ここではその基本的な使用方法をお見せします。
以下の例では、useMediaQuery
というカスタムフックを作成し、ビューポートの幅が一定の値より大きいかどうかを判定しています。
// /hooks/useMediaQuery.tsx
import { useEffect, useState } from 'react'
type UseMediaQueryType = (width: number) => boolean
const useMediaQuery: UseMediaQueryType = (width) => {
const [targetReached, setTargetReached] = useState(false)
const updateTarget = () => {
setTargetReached(window.innerWidth > width)
}
useEffect(() => {
updateTarget()
window.addEventListener('resize', updateTarget)
return () => window.removeEventListener('resize', updateTarget)
}, [])
return targetReached
}
export default useMediaQuery
次に、このフックを使って、コンポーネントのスタイルを動的に変更する方法をお見せします。
// /components/DynamicStyledComponent.tsx
import { css } from '@emotion/react'
import useMediaQuery from '../hooks/useMediaQuery'
type Props = {
text: string
}
const DynamicStyledComponent = ({ text }: Props) => {
const isDesktop = useMediaQuery(768)
return (
<div
css={css`
color: ${isDesktop ? 'blue' : 'red'};
`}
>
{text}
</div>
)
}
export default DynamicStyledComponent
上記のコンポーネントは、ビューポートの幅が 768px より大きい場合にはテキストの色を青に、それ以外の場合には赤に設定します。
レスポンシブデザインの実装
さらに、Media Queries を使ってレスポンシブデザインを実装する方法について見てみましょう。以下は、スマートフォン、タブレット、デスクトップで異なるスタイルを適用するための一例です。
// /components/ResponsiveComponent.tsx
import { css } from '@emotion/react'
import useMediaQuery from '../hooks/useMediaQuery'
type Props = {
content: string
}
const ResponsiveComponent = ({ content }: Props) => {
const isTablet = useMediaQuery(768)
const isDesktop = useMediaQuery(1024)
return (
<div
css={css`
color: ${isDesktop ? 'blue' : isTablet ? 'green' : 'red'};
font-size: ${isDesktop ? '2em' : isTablet ? '1.5em' : '1em'};
`}
>
{content}
</div>
)
}
export default ResponsiveComponent
上記のコンポーネントでは、ビューポートの幅に応じてテキストの色とサイズを変更しています。
styled を使う
styled
は、Emotion ライブラリの一部であり、JavaScript 内部で CSS を記述し、それを React コンポーネントに適用するためのツールです。テンプレートリテラルを使用して CSS を記述し、それを指定した HTML タグや React コンポーネントに適用することで、スタイリングされた新しいコンポーネントを作成します。この結果、スタイルの再利用と一貫性が向上し、スタイルの管理が容易になります。
@emotion/styled
モジュールを使用すると、コンポーネントスタイルをより明確に分離して管理することができます。以下に、styled
を使用して Emotion でメディアクエリを実装する例をお見せします。
import styled from '@emotion/styled'
const StyledParagraph = styled.p`
font-size: 30px;
@media (min-width: 420px) {
font-size: 50px;
}
`
export const ExampleComponent = () => {
return <StyledParagraph>Some text!</StyledParagraph>
}
このコードでは、styled.p
を使って新しいスタイリングされたパラグラフコンポーネント StyledParagraph
を作成しています。これは CSS 文字列テンプレートリテラル内でメディアクエリを含むことができます。StyledParagraph
はビューポート幅が 420px
以上の場合に font-size
を 50px
に変更します。
最後に、新しく作成した StyledParagraph
コンポーネントを ExampleComponent
内部で使っています。これにより、ビューポート幅に応じて動的にサイズ変更するテキストを表示できます。
このように、styled
を使うと、CSS を JavaScript コードから分離し、より一貫性のあるスタイリングを実現できます。