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

  • ---

    LINEで送る
  • -

    ブックマーク
  • -

    pocket
  • -

    rss
html5 css3 image
イラストACの画像をもとに加工しています。

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

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

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

『Run Pen』を押すと、今回のソースコードサンプルが表示されます。これをHTMLとCSSだけでつくります。

javaScriptを使わないで作る

サンプルをつくっていく前に、JavaScriptを使わないメリットを説明します。

-> 説明がいらないという人はジャンプ

HTMLとCSSだけで作るメリットは、Webサーバにリクエストする回数を最小にすることです。そのしくみは

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

これは、コンテンツを表示したりかくしたりする動作を画面を遷移しないで行います。

またJavaScriptを使わないのでブラウザへの負荷が軽いです。結果的にWebページのパフォーマンスが向上ができます。

サンプルコードの内容

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

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

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

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

各パーツの機能です。

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

ステップ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>でアイコンフォントのFontAwesomeを読み込んでいます。ボタンのマークやメニュー項目のアイコンに使います。

使い方はかんたんです。

ヘッダ・フッタ

<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をつかってメニューを立て並びにしたところです。

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

-> だれでも分かる。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・CSSHTMLだけでメニューの動きをコントロールしているのは、チェックボックスと連動しているCSSのchecked疑似クラスです。

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

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

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

SNSでも記事を配信しています。
コメントを残す

*

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

top
この記事を気に入ったらぜひシェアも!!