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


前回
前々回

上の記事で、とりあえず超シンプルなwebページができました。
次はヘッダーを作ってみたいと思います。
とりあえず、シンプルに「topのページ」「自己紹介ページ」「YouTubeの動画とかを一覧にしたページ」「問題とかが一覧になったページ」みたいな感じにしてみようと思います。
なので、まずはそれぞれに対応する.jsファイルを作ります:

/src/pages
|-- 404.js
|-- index.js
|-- about.js
|-- videos.js
|-- problems.js

about.jsの中身は、index.jsをコピペしたあとdescriptionの内容を「"自己紹介"」に変更したものとします。
videos.jsの中身は、index.jsをコピペしたあとdescriptionの内容を「"YouTube"」に変更したものとします。
problems.jsの中身は、index.jsをコピペしたあとdescriptionの内容を「"問題と解答"」に変更したものとします。
たとえば、videos.jsの中身は次のような感じです:

videos.js
const VideosPage = () => {
  const description = "YouTube";
  ...
}
export default VideosPage

さて、では、今4つのページ (と404 Not Foundのページ) が存在している状態になりましたので、
とりあえずナビゲーション的なヘッダーを作ってみたいと思います。

ヘッダーを作る

layout.jsにheaderをimportしておく

前回の記事で作ったheader.jsのファイルに色々書き込んでいくのですが、その前に、layout.jsheaderをimportして、ヘッダーを表示する場所に<Header/>と書きます:

layout.js
import * as React from "react"
import PropTypes from "prop-types"
import Header from "./header.js"  // この行を足します。

function Layout(props) {
  return (
    <main>
    <Header />   // この行を足します。
    {props.children}
    </main>
  )
}

Headerの編集

次に<Header/>の中身を記述するため、header.jsを編集していきます。
ナビゲーションはページ内リンクを記述するのが普通だと思うので、まず次のようにimportしておきます:

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

次に、大雑把にヘッダーを作ります:

header.js
const nav_list = ["Top", "About", "Videos", "Problems"];
const Header = () => {
  return (
    <header className={headerStyles.header_header}>
    <h1><Link to="/">IneQuality Bot</Link></h1>
    <NavList list={nav_list}/>
    </header>
  )
}

<Link to="~~~">がだいたい<a>タグのようなものです。ページ内リンクを相対パスで記述します。

<header>.Top_headerというCSSを適用したいのですが、
Reactの場合はそれをclassName={headerStyles.header_header}のようにして宣言します。
3行目にheaderStylesという形でCSSファイルをimportしているので、
headerStylesの中のheader_headerを適用するんだぞ」
という感じの命令になっています。
Top_headerの内容はまだ決めていません。

nav_listにはナビゲーションとして表示するもののリストを渡しており、
実際の表示は<NavList>に従うものとします。

<NavList>の中身ですが、とりあえずシンプルに、
nav_listの各項目を横に並べるリスト」
のような感じでいいかなと思います。
ですので、次のようにしてみます:

header.js
const NavList = (props) => {
  const listItems = props.list.map((item) => {
    return <ListItem key={item} navs={item} />
  });
  return (
    <nav className={headerStyles.header_nav}>
    <ul>
      {listItems}
    </ul>
    </nav>
  );
}

<NavList list={nav_list}/>で渡したnav_listprops.listで参照できます。
なので、上はだいたい次のようなHTMLを記述している感じです:

<nav className={headerStyles.header_nav}>
    <ul>
      <ListItem key={Top} navs={Top} />
      <ListItem key={About} navs={About} />
      <ListItem key={Videos} navs={Videos} />
      <ListItem key={Problems} navs={Problems} />
    </ul>
</nav>

このナビゲーションタグにはTop_navというCSSが適用されていますが、Top_navの内容はまだ決めていません。
リストをreturnするときにはkeyをつけなければならないというルールがあるので、適当にkeyを設定します。

次に<ListItem>の中身に入ります。
Topのリンクは"/"で、他のリンクは、例えば"/about"とかなので、そうなるようにコードを書きます:

header.js
const ListItem = (props) => {
  let page_link = "";
    if (props.navs === "Top") {
        page_link = "/";
    }
    else page_link = "/" + props.navs.toLowerCase();

  return (
    <li>
    <Link to={page_link}>
    {props.navs}
    </Link>
    </li>
  )
}

これだけです。特に変なことはしていません。
<ListItem navs={item}>で渡したitemというnav_listの項目はprops.navsで参照されます。
これは前回の記事でも述べた通りです。

CSSを書く

最低限のCSSを書きます。
まずは超シンプルに、左側にタイトル、右側にナビゲーション、という感じにします。
CSSの書き方はググればたくさん出てきます。

header.module.css
.header_header {
  padding: 0 15% 0 15%;
  border-bottom: 1px solid #cccccc;
}

.header_header h1 {
  padding-top: 5px;
}
.header_header h1 a {
  font-size: 30px;
  font-weight: 100;
  text-decoration: none;
}
.header_header h1 a:hover {
  background-color: #ededed;
}


.header_nav {
  margin-right: auto;
}
.header_nav ul {
  display: flex;
  list-style: none;
  padding: 0;
  margin: 0;
}
.header_nav ul li {
  padding: 0;
  margin: 0;
  margin-right: 30px;
}
.header_nav ul li a {
  text-decoration: none;
  font-size: 20px;
}
.header_nav ul li a:hover {
  background-color: #ededed;
}

ターミナルでgatsby developと打ってlocalhost:8000でチェックすると、こんな感じになってます:

あまりちゃんとCSSを書いていないので何だか変な感じがしますが、一応若干ヘッダーっぽい?ナビゲーションっぽい?です。

参考文献

リストとkey