Firebase Hosting + GatsbyJSでWebサイトを作る 4 ヘッダーを作る続

18103 ワード

前回の記事でとりあえず超シンプルなヘッダーを作りましたが、このままだとなんだかダサいなあという感じがします。
そこで、今回はもう少しデザインをしていこうという話です。

しかし、デザインを一から考えて作っていくのは大変です。
たとえば、ハンバーガーメニューのようなものを一からCSS書いて作ってると本当に途方もないです。
ですが、このような「みんなが使っているもの」はたいていパッケージ化されているものです。
というわけで、今回はGoogleのMaterialデザインをベースに開発された、ReactのUIコンポーネントをインストールして使ってみます。
MaterialUIってやつです。
前よりマシなヘッダーになるといいですね!
とりあえずターミナルでプロジェクトのフォルダまで移動しておきます。

MUIのインストール

とりあえずMaterialUIのトップにあるコマンドをコピーしてターミナルに打ち込みます。

npm install @mui/material @emotion/react @emotion/styled

一応、package.jsonファイルの中身を確認します。

"dependencies": {
    "@emotion/react": "^11.9.0",
    "@emotion/styled": "^11.8.1",
    "@mui/material": "^5.6.0",
    ...
}

となっていればokです。
説明文的なやつを読むと、
MUI was designed with the Roboto font in mind. So be sure to follow these instructions. For instance, via Google Web Fonts:
と書いてあるので、とりあえずRobotoというフォントをインストールします。
前前回に設定した<Head>の中に

<link
  rel="stylesheet"
  href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
/>

と書いても良いのですが、ここではfontsourceを使ってインストールします。
ターミナルで

npm install @fontsource/roboto

を実行します。
ちなみに、他のフォントもこれでインストールできます。
フォントをいじろとすると別の設定が必要っぽいので、フォント関係はそのときにメモすることにします。
フォントのインストールが完了したら、今度はgatsby-browser.jsの中に次を書き込みます:

gatsby-browser.js
import "@fontsource/roboto"

以上でインストール完了です!

グローバルCSS

componentsのフォルダでもどこでもいいのですが、
global.cssというCSSファイルを作っておきます。

global.css
body, main {
  margin: 0;
  padding: 0;
}

これは「いつでも効かせておきたい」ので、gatsby-browser.jsの中に相対パスを書き込みます。
/src/components/layout/の中に作った場合は以下のようになります:

gatsby-browser.js
import "/src/components/layout/global.css"

ヘッダーを作る

とりあえずApp Barの説明のページに行き、好きにソースをコピペして改変します。
とりあえずheader.jsに前回書いたやつは消しちゃって、次のようにしてみます:

header.js
import * as React from "react"
import { Link } from "gatsby"
import * as styles from "./header.module.css"

import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography';
import Container from '@mui/material/Container';
import Button from '@mui/material/Button';

const pages = ['Home', 'About', 'Problems', 'Videos'];

const Header = () => {
  return (
    <AppBar position="static">
      <Container maxWidth="xl">
        <Toolbar disableGutters>
          <Typography
            variant="h6"
            noWrap
            component="div"
            sx={{ mr: 2, color: 'white', display: { xs: 'flex', md: 'flex' } }}
          >
          <Link to="/" className={styles.noline}>IneQualityBot</Link>
          </Typography>
          <Box sx={{ flexGrow: 1, display: { xs: 'none', md: 'flex' } }}>
            {pages.map((page) => {
              let page_link = "";
              if (page === "Home") {
                  page_link = "/";
              } else {
                page_link = "/" + page.toLowerCase();
              };
              return (
                <Button
                  sx={{ my: 2, color: 'white', display: 'block' }}
                  component={Link}
                  to={page_link}
                >
                  {page}
                </Button>
            )})}
          </Box>
        </Toolbar>
      </Container>
    </AppBar>
  );
};
export default Header;

で、CSSは次のようにします:

header.module.css
.noline {
  text-decoration: none;
  color: #ffffff;
}

なんかよくわかんないけどとりあえず適当にコピペ+改変をしただけです。
buildしてserveしてlocalhost:9000で確認するとこんな感じ:

だいぶヘッダーっぽいのでは!
aboutをクリックすると自己紹介ページに飛びます:

これだけでだいぶヘッダーっぽくなりました。嬉しい。
色とかはとりあえず後で考えることにします。

感想

CSSで一から作っていくとページ全体でガタガタしてきて統一感がなくなったりするのが問題点として挙げられます。
「部品を一から自作するコスト」と「MUIの振る舞いについて理解するコスト」はどちらもあまり変わらないと思うのですが、
自作した部品を統一感持って並べるのとかは結構難しく、ここが崩れるとサイトとして「なんかださい」ってなるので、それが理由でこういうのを頼った方がいいんだと思います。

参考

MUI
App Bar
Box
Button
Container
Toolbar
Typography