ツイート
シェア
LINEで送る
B! はてぶでブックマーク
Pocketでブックマーク
RSSフィード

HTMLとCSSだけで簡単に作る。軽量なドロワーメニュー(ハンバーガーメニュー)

html5 css3 image
イラストダウンロードサイト【イラストAC】
の画像をもとに加工しています。

javaScriptを使わずにHTMLとCSSだけでドロワーメニューを作ります。ハンバーガーメニューとも言います。

スマホでよく見る3本線のボタンでメニューが出るやつです。

だれでも分かるように、サンプルコードを少しずつ作りながら説明します。

まずは完成したサンプルから。

See the Pen sample drawer menu fix by tadtadya (@tadtadya) on CodePen.

これをHTMLとCSSだけでつくります。

javaScriptを使わないで作る

サンプルをつくっていく前に、JavaScriptを使わないメリットから。

HTMLとCSSだけでつくるとWebサーバにリクエストする回数を最小限にできます。そのしくみは、

  • ブラウザからhttpリクエストを送信する。
  • Webサーバーから、すべてのコンテンツのHTMLを返す
  • ページを最初に表示するときは、閉じるボタン・メニューなどをかくす。
  • コンテンツを表示/非表示する動作をCSSでコントロールする。

これはコンテンツの表示・非表示の切り替えでページ遷移をしません。

また、コンテンツをリクエストで再取得しないとしても、JavaScriptのDOM操作がいらないので、その分だけブラウザの負荷を軽くできます。

あらかじめ、CSSですべての操作のスタイルが定義されているので、CSSOMの再展開がない。

(CSSOMはCSSのDOMみたいなもの。)

(JavaScriptのDOM, CSSOM操作の分がいらない。)

また、HTML, CSSに任せることでJavaScriptのコードを少なくできる。

サンプルコードの内容

今回はステップごとに進めていきます。分かりやすいところで区切っていくので必ず作れます。

サンプルコードでは次のコンテンツを用意します。

  • ページ全体のエリア
  • メニューの開閉ボタン
  • メニューエリア
  • ページ全体をおおう半透明シート

ここでウン?と思うのは『半透明シート』ですね?メニューを操作するときはそれ以外を操作をさせないために用意します。

各パーツの機能です。

ページ全体のエリア何もしない。
自由にページのコンテンツを配置する。
開くボタンメニューを表示する。
閉じるボタンメニューを閉じる。
メニューエリアメニューのコンテンツを入れるボックス。
ボタンで表示/非表示がコントロールされる。
半透明シートをタップ・クリックすると非表示。
半透明シートメニューが出ているとき
・ページ全体エリアにシートをかぶせる。
・ページ全体のコンテンツをタップ・クリックさせない。
・タップ・クリックするとメニューを閉じる。
・メニューを閉じると消える。

ステップ1 - パーツを作る

はじめにそれぞれのパーツを用意します。骨組みはHTMLで肉付けはCSSです。

まだ動きの機能はありません。見た目だけを作ります。

HTML全文
<head>
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css" integrity="sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ" crossorigin="anonymous">
</head>
<body>
  <header>
    <div class="menu-drawer">
      <input type="checkbox" id="chk" />
      <label class="btn" for="chk"></label>
      <label class="other" for="chk"></label>
      <div class="content">
        <h2><i class="fas fa-list-ul"></i>メニュー</h2>
        <div class="menu">
          <a href="#home"><i class="fas fa-home"></i>home</a>
          <a href="#contact"><i class="far fa-envelope"></i>contact</a>
          <a href="#phone"><i class="fas fa-phone"></i>phone</a>
          <a href="#search"><i class="fas fa-search"></i>search</a>
        </div>
        <p>© 20xx sample.com</p>
      </div>
    </div>
  </header>
  <div class="main-content">
    <h2 id="home">home</h2>
    <h2 id="contact">contact</h2>
    <h2 id="phone">phone</h2>
    <h2 id="search">search</h2>
  </div>
  <footer></footer>
</body>

<head>でアイコンフォントのFont Awesomeを読み込んでいます。ボタンのマークやメニュー項目のアイコンに使います。

使い方はかんたんです。

ヘッダ・フッタ

<header>, <footer>タグはHTML5から追加されました。HTML5からサイトのヘッダ・フッタはこのタグを使います。

サンプルでは<header>にドロワーメニュー(.menu-drawer)を追加しました。

メニューはどのページでも表示する『共通機能』だからです。

ページ全体エリア(.main-content)

サンプルではこのエリアがページ全体を覆います。サイトのコンテンツを追加します。

サンプルではメニューの仮のリンク先があるだけです。

ドロワーメニューのボタン

ドロワーメニューのボタンはチェックボックスとラベルで作りました。この理由はあと回しです。とりあえずこういうもんだと思ってください。

メニューの本体が『.menu-drawer .content』です。サンプルでは少しのリストを追加しました。メニューの中身はすべてこの中に入れます。

あと、メニュー以外をクリック・タップしたときチェックボックスをオフにする半透明シートもラベルで作りました。

これもあとで説明します。



HTMLは以上です。とくにむずかしいことはないでしょう。メニューのボタン、半透明シートが気になるくらいでしょうか。

次のステップからすべてCSSで作業します。

ステップ2 - パーツに装飾をつける

ここまでのHTMLの実行結果を見てみましょう。

ここまでのHTML

home

contact

phone

search

まぁそうなりますね。骨がむき出しの状態です。CSSの最初はパーツに装飾をつけます。

まずはパーツ装飾のすべてのCSSはこちらです。

パーツの装飾
.menu-drawer .btn {
  font-size: 27px;
  background: #fff;
  width: 40px;
  padding: 4px 0;
  cursor: pointer;
  text-align: center;
  top: 0;
  right: 0;
}
.menu-drawer .btn::before, .menu-drawer .btn::after {
  font-family: "Font Awesome 5 Free";
  font-weight: 900;
}
.menu-drawer .btn::before {
  content: "\f0c9";
}
.menu-drawer .btn::after {
  content: "\f00d";
}
.menu-drawer .other {
  background: rgba(0, 0, 0, 0.2);
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
}
.menu-drawer .content {
  display: table;
  border: 1px solid #ebebeb;
  border-radius: 4px;
  background: #fff;
  width: 90vw;
  top: 34px;
  right: 0;
  text-align: center;
}
@media screen and (min-width: 415px) {
  .menu-drawer .content {
    width: 350px;
  }
}
.menu-drawer .content h2 {
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  background: #383838;
  margin: 0;
  padding: .7em;
  border-radius: 4px 4px 0 0;
}
.menu-drawer .content h2 i {
  color: #383838;
  background: #fff;
  border-radius: 50%;
  padding: .4em;
  margin-right: .5em;
}
.menu-drawer .content .menu {
  height: 210px;
  overflow-y: auto;
}
.menu-drawer .content a {
  border-bottom: 1px solid #ebebeb;
  padding: 1rem 0 0 0;
  text-decoration: none;
  color: #858585;
  display: block;
  width: 100%;
  display: flex;
  flex-flow: column;
}
.menu-drawer .content a i {
  font-size: 27px;
}
.menu-drawer .content p {
  color: #858585;
}

すぐに分からなければ一気に見る必要はないです。少しずつ分解して説明します。

メニュー開閉ボタン

メニューボタンの装飾
.menu-drawer .btn {
  font-size: 27px;
  background: #fff;
  width: 40px;
  padding: 4px 0;
  cursor: pointer;
  text-align: center;
  top: 0;
  right: 0;
}
.menu-drawer .btn::before, .menu-drawer .btn::after {
  font-family: "Font Awesome 5 Free";
  font-weight: 900;
}
.menu-drawer .btn::before {
  content: "\f0c9";
}
.menu-drawer .btn::after {
  content: "\f00d";
}

メニュー開閉ボタンは、チェックボックスのラベルを使っているので、そのラベルをボタン風にします。

ボタンのHTML
<input type="checkbox" id="chk" /><label class="btn" for="chk"></label>
ラベルのボタン風スタイル
.menu-drawer .btn {
  font-size: 27px;
  background: #fff;
  width: 40px;
  padding: 4px 0;
  cursor: pointer;
  text-align: center;
  top: 0;
  right: 0;
}

そして、ボタンのマークを::before, ::after疑似クラスでつくります。

マークはFont Awesomeのアイコンフォントをつかいます。

::before三本線。メニューを開く
::afterバッテン。メニューを閉じる
ラベルのボタン風スタイル
.menu-drawer .btn::before, .menu-drawer .btn::after {
  font-family: "Font Awesome 5 Free";
  font-weight: 900;
}
.menu-drawer .btn::before {
  content: "\f0c9";
}
.menu-drawer .btn::after {
  content: "\f00d";
}

ここまでのHTMLを実行してみましょう。

home

contact

phone

search

たいして変わってないですが、これでいいです。いまは開く・閉じるボタンのマークが出ればいいので。

(ボタンをタップ・クリックするとチェックボックスが変化します。)

半透明シート

メニューボタンの装飾
.menu-drawer .other {
  background: rgba(0, 0, 0, 0.2);
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
}

ページ全体にかぶせる半透明シートです。

ここはたいしたことないです。エリア全体をおおうサイズ指定と、半透明をrgba()をつかってうすい黒にしています。

半透明シートのHTML
<input type="checkbox" id="chk" /><label class="other" for="chk"></label>

なんで半透明シートもチェックボックスと連携しているかは、あとで説明します。

メニューコンテンツ

メニューコンテンツの装飾
.menu-drawer .content {
  display: table;
  border: 1px solid #ebebeb;
  border-radius: 4px;
  background: #fff;
  width: 90vw;
  top: 34px;
  right: 0;
  text-align: center;
}
@media screen and (min-width: 415px) {
  .menu-drawer .content {
    width: 350px;
  }
}
.menu-drawer .content h2 {
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  background: #383838;
  margin: 0;
  padding: .7em;
  border-radius: 4px 4px 0 0;
}
.menu-drawer .content h2 i {
  color: #383838;
  background: #fff;
  border-radius: 50%;
  padding: .4em;
  margin-right: .5em;
}
.menu-drawer .content .menu {
  height: 210px;
  overflow-y: auto;
}
.menu-drawer .content a {
  border-bottom: 1px solid #ebebeb;
  padding: 1rem 0 0 0;
  text-decoration: none;
  color: #858585;
  display: block;
  width: 100%;
  display: flex;
  flex-flow: column;
}
.menu-drawer .content a i {
  font-size: 27px;
}
.menu-drawer .content p {
  color: #858585;
}

メニュー本体はただのボックスです。

メニュー本体のHTML
<div class="content">
  <h2><i class="fas fa-list-ul"></i>メニュー</h2>
  <div class="menu">
    <a href="#home"><i class="fas fa-home"></i>home</a>
    <a href="#contact"><i class="far fa-envelope"></i>contact</a>
    <a href="#phone"><i class="fas fa-phone"></i>phone</a>
    <a href="#search"><i class="fas fa-search"></i>search</a>
  </div>
  <p>© 20xx sample.com</p>
</div>
メニュー本体の枠のスタイル
.menu-drawer .content {
  display: table;
  border: 1px solid #ebebeb;
  border-radius: 4px;
  background: #fff;
  width: 90vw;
  top: 34px;
  right: 0;
  text-align: center;
}
@media screen and (min-width: 415px) {
  .menu-drawer .content {
    width: 350px;
  }
}

ポイントは、デバイスのサイズでメニューサイズを変えているところでしょうか?(@media)

ほかは色など基本的なことしかしてません。

メニューヘッダのスタイル
.menu-drawer .content h2 {
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  background: #383838;
  margin: 0;
  padding: .7em;
  border-radius: 4px 4px 0 0;
}
.menu-drawer .content h2 i {
  color: #383838;
  background: #fff;
  border-radius: 50%;
  padding: .4em;
  margin-right: .5em;
}

メニューのヘッダです。とくにむずかしいことはしてません。

メニューのスタイル
.menu-drawer .content .menu {
  height: 210px;
  overflow-y: auto;
}

メニューを配置するエリアです。高さを固定してスクロールをつけました。

メニューのフォントスタイル
.menu-drawer .content a {
  border-bottom: 1px solid #ebebeb;
  padding: 1rem 0 0 0;
  text-decoration: none;
  color: #858585;
  display: block;
  width: 100%;
  display: flex;
  flex-flow: column;
}
.menu-drawer .content a i {
  font-size: 27px;
}
.menu-drawer .content p {
  color: #858585;
}

メニューのフォントまわりです。

ポイントは、Flexをつかってメニューを立て並びにしたところです。

ほかはたいしたことありません。

ここまでのHTMLを実行してみましょう。

home

contact

phone

search

おー。やっとメニューらしくなりましたね?

そういえば、top, rightなどメニューの位置を指定したのに変わってません。

そこは、いまは無視してください。

次のステップで、コンテンツのコントロールをします。ここでメニューを完成させます。

ステップ3 - メニューの動きをコントロールする

ここがクライマックスです。

メニューのボタン機能、ボタンを押したときのメニューの動きをつけます。

CSSだけで行ないます。

メニューの動き
.menu-drawer .btn,
.menu-drawer .content,
.menu-drawer .other {
  position: fixed;
}
.menu-drawer .btn,
.menu-drawer .content {
  z-index: 1001;
}
.menu-drawer .other {
  z-index: 1000;
}

.menu-drawer #chk {
  display: none;
}
.menu-drawer #chk ~ .btn::before {
  display: block;
}
.menu-drawer #chk ~ .btn::after {
  display: none;
}
.menu-drawer #chk ~ .other {
  display: none;
}
.menu-drawer #chk:checked ~ .btn::before {
  display: none;
}
.menu-drawer #chk:checked ~ .btn::after {
  display: block;
}
.menu-drawer #chk:checked ~ .other {
  display: block;
}

.menu-drawer #chk ~ .content {
  transform: translate(350%, 0);
  transition: transform 0.3s ease-in-out;
}
.menu-drawer #chk:checked ~ .content {
  transform: none;
}

メニューのポジション

メニューの固定ポジション
.menu-drawer .btn,
.menu-drawer .content,
.menu-drawer .other {
  position: fixed;
}
.menu-drawer .btn,
.menu-drawer .content {
  z-index: 1001;
}
.menu-drawer .other {
  z-index: 1000;
}

ステップ2でtop, rigthを定義しているのに位置が変わりませんでした。これを完成させます。

メニューボタン、メニュー本体、半透明シートは、タテにスクロールしても同じ位置で固定にしたいのでfixedをつかいます。

あとは、z-indexでコンテンツの重なりを定義します。

メニュー > 半透明シート > ページコンテンツ

メニューはつねにコントロールできるように一番上。

半透明シートは、メニューを出しているときページコンテンツを操作できないようにメニューとページコンテンツのあいだに重ねます。

ここまでのHTMLを実行してみましょう。

メニューの位置が決まりました。半透明シートも出てますね?

メニューの開閉ボタン、半透明シートをクリック・タップしてみてください。左上のチェックボックスが動くのが分かります。

あともう少しです。このチェックボックスまわりをつくれば完成です。

メニューの表示/非表示

メニュー表示・非表示
.menu-drawer #chk {
  display: none;
}
.menu-drawer #chk ~ .btn::before {
  display: block;
}
.menu-drawer #chk ~ .btn::after {
  display: none;
}
.menu-drawer #chk ~ .other {
  display: none;
}
.menu-drawer #chk:checked ~ .btn::before {
  display: none;
}
.menu-drawer #chk:checked ~ .btn::after {
  display: block;
}
.menu-drawer #chk:checked ~ .other {
  display: block;
}

.menu-drawer #chk ~ .content {
  transform: translate(350%, 0);
  transition: transform 0.3s ease-in-out;
}
.menu-drawer #chk:checked ~ .content {
  transform: none;
}

チェックボックスまわりの処理です。少しずつ分解して説明します。

メニュー表示の初期状態
.menu-drawer #chk {
  display: none;
}
.menu-drawer #chk ~ .btn::before {
  display: block;
}
.menu-drawer #chk ~ .btn::after {
  display: none;
}
.menu-drawer #chk ~ .other {
  display: none;
}

まずは初期状態です。

  • チェックボックス非表示(none)。
  • 開くボタン表示。閉じるボタン非表示。
  • 半透明シート非表示。

チェックボックスは機能だけが必要なので見えてはいけません。

最初はメニューをかくしたいので開くボタンだけを表示します。

半透明シートはメニューが出てるときだけ必要なのでかくします。

これはチェックボックスがついてないときの処理です。

ボタン機能
.menu-drawer #chk:checked ~ .btn::before {
  display: none;
}
.menu-drawer #chk:checked ~ .btn::after {
  display: block;
}
.menu-drawer #chk:checked ~ .other {
  display: block;
}

ここが最大のポイントです。チェックボックスがついたときの処理です。

こんどは開くボタンをかくして閉じるボタンを表示します。

半透明シートを表示します。

メニュー本体のコントロール
.menu-drawer #chk ~ .content {
  transform: translate(350%, 0);
  transition: transform 0.3s ease-in-out;
}
.menu-drawer #chk:checked ~ .content {
  transform: none;
}

メニュー本体もチェックボックスで動かします。

チェックがついていないときは、ページの右側に追いやってかくしておきます。

チェックがついているときは、かくしたものを元に戻します。

そしてtransitionで、メニューをスーッと出し入れして、なめらかなスライドにします。

ステップ4 - その他を整えて完成

もうこれでメニューはできているのですが、Webページのコンテンツ本体を整えて完成です。

ページ全体エリア
.main-content {
  height: 10000px;
  background: #cfefff;
  color: #383838;
  text-align: center;
}
.main-content h2 {
  height: 300px;
}

メニューのリンク先が分かりやすいように整形しました。

サンプルでは同一ページでジャンプしていますが、<a>リンクで別ページにジャンプしてもいいです。むしろこちらのほうが多いでしょう。

完成したHTMLを実行してみましょう。

まとめ

HTMLとCSSだけでメニューの動きをコントロールしているのは、チェックボックスと連動しているCSSのchecked疑似クラスです。

ポイントはこれだけといってもいいでしょう。

ほかにも、checked疑似クラスをつかうとHTML・CSSだけでできることがあります。

使い方は同じで、いろいろなことができますよ?

前の投稿
HTMLとCSSだけで簡単に作る。軽量なタブで表示内容を切り替え
HTMLとCSSだけで簡単に作る。軽量なON/OFF スイッチ
次の投稿
コメントを残す

*