対象読者
- JavaScriptとWeb開発の基礎に理解がある方
- Reactを用いたJavaScriptアプリケーション開発の経験者
前提環境
筆者の検証環境は以下の通りです。
- macOS Big Sur 11.5.2
- Node.js 16.11.1/npm 8.0.0
- React 17.0.2
- react-scripts 4.0.3
- @chakra-ui/react 1.6.10
Webアプリ制作時に嬉しいコンポーネントとHooks
前回に引き続き、今回もChakra UIについて解説します。Chakra UIは、React向けのUIライブラリとしては後発の部類ですが、Webアプリケーション制作で必要となるコンポーネントを多く備えていることからか、たくさんの採用事例が現れました。最近だとメルカリShopsのフロントエンド実装で採用されたのが記憶に新しいですね。
どんなコンポーネントやHooksの存在が魅力的なのか、今回と次回の2回に分けて解説していきます。公式ドキュメントのジャンル分けをもとに、次のように基礎編と応用篇に分けて解説します。
-
基礎編(今回)
- レイアウトに関するコンポーネント
- テキスト表示に関するコンポーネント
- メディア表示に関するコンポーネント
-
応用編(次回)
- フォームに関するコンポーネント
- データ表示に関するコンポーネント
- フィードバックに関するコンポーネント
- オーバーレイに関するコンポーネント
- データの表示・非表示切り替えに関するコンポーネント
- ナビゲーションに関するコンポーネント
- 便利なHooks
基礎編では、デスクトップアプリやモバイルアプリを開発する文脈でも基礎とされることが多い、レイアウト、テキスト表示、画像表示について主に扱います。応用編では、特定の目的に特化したコンポーネントについて解説します。また、React Hooksで作られた便利なインターフェースも用意されていますが、こちらは応用編で扱います。
レイアウトに関するコンポーネント
それではまず、レイアウトに関するコンポーネントを見ていきましょう。表1の9種類があります。
| コンポーネント | 概要 |
|---|---|
| Aspect Ratio | 縦横比を維持した領域を作る。 |
| Box | コンポーネントを囲んだ領域を作る。 |
| Center | 中身を中央寄せで配置する。 |
| Container | 大きな画面の中で中央寄せのコンテンツ表示領域を作る。 |
| Flex | Flexboxが有効になったBox。 |
| Grid | CSS Grid Layoutが有効になったBox。 |
| Simple Grid | 複雑でない形でCSS Grid Layoutを扱う。 |
| Stack | 縦または横の一方向に要素を並べる。 |
| Wrap | flex-wrapが有効になった領域を作る。 |
代表的なものについて解説します。
CSSに組み込まれているレイアウトシステム
Chakra UIには、<Flex>や<Grid>など、CSSに元々あるレイアウトシステムをそのまま扱うためのコンポーネントがいくつか存在しています。ここで簡単に、CSSに組み込まれたレイアウトシステムについて解説しておきましょう。
1つ目は主に<Flex>で利用できる Flexbox (フレックスボックス)です。これはCSSでdisplay: flexを指定した要素の中で利用できます。Flexboxは「要素を1方向に並べる」という特性を持ったレイアウトシステムです。縦方向、または横方向のどちらかに要素を並べることができます。中央寄せ・左寄せ・右寄せ・上寄せ・下寄せといった調整が柔軟に行えるため、重宝されています。また、<Wrap>コンポーネントでは、Flexboxのflex-wrap: wrapという指定が有効になっています。これは、Flexboxで要素を並べていく中で親要素の端にぶつかってしまった場合に、折り返して次の段に続きが並ぶというものです。これもまた重宝されています。
2つ目は主に<Grid>で利用できる CSS Grid Layout (シーエスエスグリッドレイアウト)です。これはCSSでdisplay: gridを指定した要素の中で利用できます。CSS Grid Layoutは「要素を格子上に並べる」という特性を持ったレイアウトシステムです。<table>要素と少し似ていますが、<table>要素は表データを表現するのを目的としているのに対して、こちらは要素を並べることに特化しており、どんな要素でも並べることができます。Webサイトのレイアウト定義(ヘッダー、フッター、メニュー、メインなど)を並べる際には活躍すると思います。
MDNのドキュメントにより詳しい情報があるので、気になる方は以下をご覧ください。
Box
基本となるのが<Box>です。基本的に<div>としてレンダリングされることもあり、<div>に近い使い方をします(リスト1)。
<Box w="100px" h="100px" bgColor="teal.400" p="2"> I am Box. </Box>
単に<div>を使う場合との違いとして、スタイルを属性で定義するChakra UIらしい機能が利用できます。今回は「高さ100px、幅100px、背景色はティールの400番、paddingは"2"(0.5rem)」というスタイルを付けました。リスト1を表示すると、図1のようになります。
属性で設定したスタイル通りの見た目になりましたね。
Container
さて、小さい領域は<Box>やそこから派生したコンポーネントを扱いますが、ページの一番外側を扱うコンポーネントとして、<Container>が用意されています(リスト2)。
<Container py="3" maxW="600px">
<Box />
{/* 各種コンテンツ */}
</Container>
リスト2を使うと、図2のように、最大の幅を決めてコンテンツを表示できます。
画面サイズが大きく横長になった現代では、左右に余白を設けて、中央にコンテンツの表示領域を設けることが一般的になりました。<Container>はmaxWidth属性(maxWとも書ける)で指定した幅で子要素を表示できる、便利なコンポーネントです。デフォルトでは60文字を表す60chの幅になっています。
<Container>の魅力はこれだけではありません。Chakra UIは全体的にレスポンシブデザインへの対応が容易になるように設計されており、<Container>をスマートフォンで表示した場合、つまりmaxWidthより狭い幅で表示した場合には子要素がスマートフォンの幅まで狭まります(図3)。
この特性を活用して、Chakra UIでのUI実装では基本的に<Container>の子要素の幅が最大幅となるようにコンテンツのスタイルを組むことが多くなります。以降のサンプルコードの実行例では、基本的に各コンポーネントは<Container>に包まれていることとします。
Center
次は<Center>です。子要素を中央に寄せて表示します(リスト3)。昔からHTMLを触っている方は<center>要素と近い動きをするといえばわかりやすいかもしれませんが、このコンポーネントでは<center>要素を使わず、Flexboxで中央寄せを実現しています。
<Center w="full" h="200" borderWidth="1px"> <Box w="100px" h="100px" bgColor="teal.400" p="2">I am Box.</Box> </Center>
わかりやすさのためにborderWidth="1px"を付けてあります。リスト3を表示すると、図4のようになります。
Boxが領域の中央に表示されました。後述する<Flex>でも実現可能ではありますが、手軽に中央寄せを実現する手段として重宝するので、覚えておくとよいでしょう。
Stack
アプリケーションを作っていると、要素を縦や横の一方向に並べたくなることがよくあります。それを簡便に行うためのコンポーネントが<Stack>です。用途に合わせて、次の3種類が用意されています。
- VStack:子要素を縦方向に並べる
- HStack:子要素を横方向に並べる
- Stack:子要素を縦方向や横方向に並べる
最も汎用的なのが<Stack>で、そこから並べる方向限定したのが<VStack>や<HStack>という立場になっています。それぞれの動作を見ていきましょう(リスト4)。
{/* (1) VStackの例 */}
<VStack spacing="3">
<Box w="full" h="100px" bgColor="teal.400" p="2">I am Box.</Box>
<Box w="full" h="100px" bgColor="teal.400" p="2">I am Box.</Box>
<Box w="full" h="100px" bgColor="teal.400" p="2">I am Box.</Box>
</VStack>
{/* (2) HStackの例 */}
<HStack spacing="3">
<Box w="full" h="100px" bgColor="teal.400" p="2">I am Box.</Box>
<Box w="full" h="100px" bgColor="teal.400" p="2">I am Box.</Box>
<Box w="full" h="100px" bgColor="teal.400" p="2">I am Box.</Box>
</HStack>
{/* (3) Stackの例 */}
<Stack direction={["column", "row"]} spacing="3">
<Box w="full" h="100px" bgColor="teal.400" p="2">I am Box.</Box>
<Box w="full" h="100px" bgColor="teal.400" p="2">I am Box.</Box>
<Box w="full" h="100px" bgColor="teal.400" p="2">I am Box.</Box>
</Stack>
まずは(1)の<VStack>ですが、「V」は「Vertical」を表しており、子要素を縦方向に並べる機能を持っています。表示すると図5のようになります。
縦方向に並びましたね。spacing="3"を付けたことで、子要素の間に0.75remの隙間ができています。Stack系のコンポーネントを使う大きな利点として、このように簡単に隙間を空けられるというものがあります。
次は(2)の<HStack>です。「H」は「Horizontal」を表しており、子要素を横方向に並べる機能を持っています。表示すると図6のようになります。
今度は横方向に並びました。<VStack>と同様に、要素間に隙間ができています。それでは最後に、(3)の<Stack>を見てみましょう。<Stack>はdirection要素にdirection="column"やdirection="row"といったflex-directionの値を指定することで、子要素を並べる方向を制御できます。
それだけならば<VStack>や<HStack>でも代用できるのですが、少し特殊な記法として、direction={["column", "row"]}のように配列を与えて、レスポンシブ対応をさせることもできます。配列の第一要素はスマートフォンでの設定、第二要素がデスクトップでの設定です。そのため、(3)のように書くだけで、図7、図8のようにデスクトップとスマートフォンで別方向に要素を並べることができるのです。
Stack系のコンポーネントを上手に使い分けることで、要素を並べるUIを短時間で実装できそうですね。
Aspect Ratio
このジャンルで一番の変わり種は、この<AspectRatio>です。子要素を特定の縦横比で表示します。リスト5の例を見てみましょう。
<HStack spacing="5">
<AspectRatio w="200px" ratio={4 / 3} bgColor="pink.300">{/* (1) */}
<Box>Width: 200px</Box>
</AspectRatio>
<AspectRatio w="160px" ratio={4 / 3} bgColor="pink.300">{/* (2) */}
<Box>Width: 160px</Box>
</AspectRatio>
<AspectRatio w="120px" ratio={4 / 3} bgColor="pink.300">{/* (3) */}
<Box>Width: 120px</Box>
</AspectRatio>
</HStack>
<AspectRatio w="full" ratio={16 / 9} bgColor="pink.300" mt="5">{/* (4) */}
<Box>Width: full</Box>
</AspectRatio>
<AspectRatio>はratio(比率)属性に分数(に見える割り算)を渡すことで比率を設定します。計算結果が1より大きければ横長に、小さければ縦長に、ちょうど1なら正方形になります。(1)、(2)、(3)の例では、どれも4:3の比率で横幅だけを変えました。(4)の例では、横幅は親要素の幅いっぱいにしつつ、16:9の比率になるようにしました。すると、図9のように表示されます。
Box側では特にサイズを指定していませんが、指定した比率と大きさになりました。動画ウィジェットを埋め込むときなどに重宝することになるでしょう。
その他のコンポーネント
他にもコンポーネントはありますが、特定のCSSを扱うだけなので、簡単な紹介だけにさせてください。<Flex>はdisplay: flexが有効になっているだけで、ほとんど<Box>と同じ機能です。<Wrap>も同様で、こちらはさらにflex-wrapが有効になっています。flex-wrapとspacingの組み合わせは便利なので、重宝することになるでしょう。
<Grid>はdisplay: gridが有効になっている<Box>です。CSS Grid Layoutに準拠したグリッド表示ができます。<SimpleGrid>は<Grid>を少し簡便に扱えるようにしたものです。
ここまで解説したコンポーネント群を利用すれば、大抵のレイアウトをすんなりと組むことができるでしょう。
