14
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Rails5】ドロップダウンリスト(ハンバーガーメニュー)の実装(haml,scss編)〜メルカリクローンサイトの作成

Last updated at Posted at 2019-10-10

#背景
カリキュラムの過程でご存知メルカリのクローンサイトを作りました。
その際に、ヘッダーメニューにあるドロップダウンリスト(ハンバーガーメニュー?)を実装したのでその記録です。

仕上がりはこんな感じです。
Image from Gyazo

今回の実装ではカテゴリー名をDBから持ってきて、
その値をcollectionを使ってrenderにて表示させています。詳しくはこちらにまとめましたのでよかったらどうぞ。
【Rails5】ドロップダウンリストの実装(コントローラー編)メルカリクローンサイトの作成

#対象となる読者
CSSだけを使ってドロップダウンリストを実装したいよ〜って方
いつもhamlとsassで書いてるからhtml,cssだとちょっとわかんないなーって方

#要はdisplay: noneとかで隠して、hoverで出せばOK
まずは何個か参考記事を検索して読んでみましょう。
CSSで作ったドロップダウンメニューのドロップの動きいろいろ
【CSS】CSSだけで作るドロップダウンメニュー(多階層)

他にも色々な記事があるけど、まぁだいたいこのあたりを読むと、display:noneとかvisibilty:hiddenとかoverflow:hiddenで要素を隠して、隠した要素をhoverした時に変更して出現させているってわかりますね。

記事を参照にする時に大事だなって思うのは、
「その実装で、絶対に外せないポイントは何か?」
「いろんな記事で共通することは何か?」
を探すこと。

結局、記事を書いた人の背景とか環境と、自分が今作っている環境って同じじゃないし、
コピペしても、他のファイルの要素が影響したりすることもあって、
まぁ一発でうまく行くことってない。

だから複数の記事を参考にして、その要点を抽象化して抜き出すってことが大事。(自戒も込めて残しとこ)

#仕上がりコード

_header.html.haml
    .header__menu-box
      .header__menu-box--left
        %ul
          %li.header__menu-box--left__category
            = link_to category_index_path do
              = fa_icon "list-ul", class: 'header__menu-box--left__icon'
              カテゴリーから探す
            %ul.header__menu-box--left__parents -#親カテゴリの大枠
              %li.header__menu-box--left__parents__parent -#親カテゴリの中身
                = link_to "レディース", category_path(id: 1)
                %ul.header__menu-box--left__children -#子カテゴリの大枠
                  = render partial: "products/header_child", collection: @category_children1, as: "category"

           -#以下は"_header_child.html.haml"で切り出す部分
           %li.header__menu-box--left__children__child -#子カテゴリの中身
             = link_to "#{category.category}", category_path(id: category.id)
             %ul.header__menu-box--left__grand-children -#孫カテゴリーの大枠
               = render partial: "products/header_grand-child", collection: category.children, as: "children"

                      -#以下は"_header_grand-child.html.haml"で切り出す部分
              %li.header__menu-box--left__grand-children__grand-child -#孫カテゴリーの中身
                = link_to "#{children.category}", category_path(id: children)

              %li.header__menu-box--left__parents__parent
                = link_to "メンズ", category_path(id: 2)
                %ul.header__menu-box--left__children
                  = render partial: "products/header_child", collection: @category_children2, as: "category"

リストの中にリストをネストさせ、さらにリストをさせることで孫の階層までを作っています。


%ul%li親1
  %ul%li子1
    %ul%li孫1
      %li孫2
      %li孫3
      %li孫4
    %li子2
    %ul%li孫1
      %li孫2
      %li孫3
      %li孫4

 %li親2
  %ul%li子1
    %ul%li孫1
      %li孫2
      %li孫3
      %li孫4
    %li子2
    %ul%li孫1
      %li孫2
      %li孫3
      %li孫4


肝心のCSSはこちら
今回は特にアニメーションとか不要だったので、display:noneで隠して、
hoverした時にdisplay:blockにすることで出現するように実装しました。

実装の際は最初からdisplay:noneをかけずに、とりあえずblockと書いておいて、
absoluteの位置関係とかスタイルの調整をして、
最後にhoverした時の挙動を実装するって順番でやると
作業しやすかったです。

_header.scss

中略

  .header__menu-box {
    height: 46px;
    margin: 8px 0 0;
    display: flex;
    align-items: center;
    justify-content: space-between;

    &--left {
      display: flex;
      justify-content: space-between;
      &__icon {
        color: $main_red;
        font-size: 12px;
        margin-right: 4px;
      }
      ul {
        li.header__menu-box--left__category {
          font-weight: bold;
          font-size:14px;
          margin-right: 10px;
          height: 55px;
          line-height: 46px;
          position: relative;
          &:hover {
            color: $main_blue;
            ul {
              li {
                display: block;
                height: 44px;
              }
            }
          }
          ul {
            position: absolute;
            top: 44px;
            z-index: 1000;
            font-weight: normal;
            li {
              width: 220px;
              height: 0;
              display: none;
              background-color: white;
              &:hover {
                color: $main_blue;
                .header__menu-box--left__children {
                  &__child {
                    display: block;
                    height: 30px;
                  }
                }
              }
              a {
                @include dropMenu_aTag(44px);
                &:hover {
                  background-color: $main_red;
                  color: white;
                }
              }
              .header__menu-box--left__children {
                position: absolute;
                top: 0;
                left: 220px;
                z-index: 1000;
                height: 616px;
                background-color: white;
                border-right: 1px solid $main_gray;
                &__child {
                  width: 220px;
                  height: 0;
                  display: none;
                  background-color: white;
                  &:hover {
                    color: $main_blue;
                    .header__menu-box--left__grand-children {
                      &__grand-child {
                        display: block;
                        height: 30px;
                      }
                    }
                  }
                  a {
                    @include dropMenu_aTag(30px);
                    font-size: 14px;
                    &:hover {
                      background-color: #f3f3f3;
                    }
                  }
                  .header__menu-box--left__grand-children {
                    position: absolute;
                    top: 0;
                    left: 220px;
                    z-index: 1000;
                    height: 616px;
                    background-color: white;
                    border-right: 1px solid $main_gray;
    
                    &__grand-child {
                      width: 300px;
                      height: 0;
                      display: none;
                      background-color: white;
                      a {
                        @include dropMenu_aTag(30px);
                        font-size: 14px;
                        &:hover {
                          background-color: #f3f3f3;
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }

中略

@include dropMenu_aTag(30px);はmixinの呼び出し
$main_blueは変数の呼び出しです。

sassの書き方は他の記事をご参照くださいませ。

要点だけ抜き出すとこんな感じ。
これを階層分ネストを繰り返し、作りました。

     ul {
        li.header__menu-box--left__category {
          position: relative; 子要素のabsoluteのための記述
          &:hover {
       以下はマウスオーバーした時の挙動
            color: $main_blue;
            ul {
              li {
          出現させる記述をかく
                display: block;
                height: 44px;
              }
            }
          }
          ul {
            出現した時の位置をかく
            position: absolute;
            top: 44px;
            z-index: 1000;
            li {
              隠す記述をかく。上記のhoverで出現させる。
              height: 0;
              display: none;
             

はじめにも書きましたが、これをこのままコピペしても、多分うまくいかないと思います。
要点を掴んで適応させてくださいね

では。

14
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?