LoginSignup
18

More than 5 years have passed since last update.

GmailApp風のメニューを作ってみた

Last updated at Posted at 2015-03-09

GmailApp風のメニューをHTML, CSS, JavaScriptとで作成してみました。対応はiOS7以上・Android4以上です。

デモとソース

デモ (スマホ)
ソース

HTML

<body>
<div class="wrapper">
    <div class="side is-hide" id="side">
        <div class="side-header">
            <h2>side-header</h2>
        </div>
        <nav class="side-inner" id="side-inner">
            <ul>
                <li><a href="#">Menu1</a></li>
                <li><a href="#">Menu2</a></li>
                <li><a href="#">Menu3</a></li>
            </ul>
        </nav>
    </div>
    <div class="container is-transition" id="container">
        <header class="header slide">
            <h1>HEADER</h1>
            <div class="btn-wrap"><a href="javascript:void(0);" class="btn" id="btn"><span></span></a></div>
        </header>
        <main class="main slide" id="main">
            <h1>contents</h1>
            <ul>
                <li>
                    <a href="#">
                        <p>名前</p>
                        <dl>
                            <dt>題名</dt>
                            <dd>本文テキスト</dd>
                        </dl>
                    </a>
                </li>
                <li>
                    <a href="#">
                        <p>名前</p>
                        <dl>
                            <dt>題名</dt>
                            <dd>本文テキスト</dd>
                        </dl>
                    </a>
                </li>
                <li>
                    <a href="#">
                        <p>名前</p>
                        <dl>
                            <dt>題名</dt>
                            <dd>本文テキスト</dd>
                        </dl>
                    </a>
                </li>
            </ul>
        </main>
    </div>
</div>
<body>

続いて、</body>の前にJavaScriptを読み込む。

呼び出しはHTML内にしてみる。

<script src="js/sidemenu.js"></script>
<script>
    SIDE_MENU.METHOD({
        mainId: 'container',
        slideCls: 'slide',
        menuId: 'side',
        btnId: 'btn'
    });
    SIDE_MENU.INNER_SCROLL({
        scrollId: 'side-inner',
        fixHeaderHeight: 50
    });
</script>

SCSS

Gmail風なCSS

// =========================
// GENERAL
// =========================
.is-hide {
  display: none;
}

// =========================
// CONTAINER
// =========================
.container {
  position: relative;
  background-color: #fff;
  min-height: 100%;
  box-shadow: 0 -1px 2px rgba(0, 0, 0, .26);
  .slide {
    -webkit-transform: translate(0, 0);
    -moz-transform: translate(0, 0);
    transform: translate(0, 0);
  }

  // setting Transition
  &.is-transition {
    .slide {
      -webkit-transition: -webkit-transform 300ms cubic-bezier(0.1, 0.57, 0.1, 1);
      -moz-transition: -moz-transform 300ms cubic-bezier(0.1, 0.57, 0.1, 1);
      transition: transform 300ms cubic-bezier(0.1, 0.57, 0.1, 1);
    }
  }
}

// HEADER
.header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 50px;
  line-height: 50px;
  background-color: #eee;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .26);
  text-align: center;
  color: #666;
  z-index: 100;
  box-sizing: border-box;
}

// MAIN
.main {
  padding: 50px 0;
  position: absolute;
  z-index: 30;
  background-color: #fff;
  width: 100%;
  box-sizing: border-box;
  h1 {
    padding: 10px 20px;
  }
  li {
    border-top: 1px solid #ccc;
    line-height: 1.3;
  }
  a {
    display: block;
    padding: 8px 20px;
    color: #999;
    text-decoration: none;
  }
  p {
    font-size: 18px;
  }
  dd {
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
  }
}

// =========================
// TOGGLE BUTTON
// =========================
.btn-wrap {
  position: absolute;
  top: 5px;
  left: 5px;
}
.btn {
  width: 40px;
  height: 40px;
  display: block;
  position: relative;
  -webkit-transition: -webkit-transform 300ms ease;
  -moz-transition: -moz-transform 300ms ease;
  transition: transform 300ms ease;
  span,
  &:before,
  &:after {
    position: absolute;
    width: 20px;
    height: 2px;
    background-color: #666;
  }
  &:before,
  &:after{
    content: "";
  }
  &:before {
    top: 12px;
    left: 10px;
  }
  &:after {
    bottom: 12px;
    left: 10px;
  }
  span {
    top: 19px;
    left: 10px;
  }
}

// =========================
// OPEN
// =========================
.is-open {

  // CONTAINER
  &.container {
    .slide {
      -webkit-transform: translate(80%, 0);
      -moz-transform: translate(80%, 0);
      transform: translate(80%, 0);
    }
  }

  // TOGGLE BUTTON
  .btn {
    -webkit-transform: rotate(45deg);
    -moz-transform: rotate(45deg);
    transform: rotate(45deg);
    span {
      display: none;
    }
    &:before,
    &:after {
    }
    &:before {
      top: 10px;
      left: 19px;
      width: 2px;
      height: 20px;
    }
    &:after {
      top: 19px;
      left: 10px;
    }
  }
}

// =========================
// SIDE
// =========================
.side {
  color: #FFF;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  bottom: 0;
  z-index: 10;
  box-sizing: border-box;
  overflow: auto;
  background-color: #444;

}
.side-header {
  height: 50px;
  line-height: 50px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .26);
  padding: 0 5px;
  position: relative;
  z-index: 30;
  background-color: #444;
}
.side-inner {
  position: absolute;
  width: 80%;
  z-index: 20;

  // setting Transition
  &.is-transition {
    -webkit-transition: -webkit-transform 300ms cubic-bezier(0.1, 0.57, 0.1, 1);
    -moz-transition: -moz-transform 300ms cubic-bezier(0.1, 0.57, 0.1, 1);
    transition: transform 300ms cubic-bezier(0.1, 0.57, 0.1, 1);
  }
  li {
  }
  a {
    color: #fff;
    display: block;
    padding: 15px;
    font-size: 16px;
    text-decoration: none;
    font-weight: bold;
  }
}

やってみたこと

  • JavaScriptでボタンタップでクラスをつけてOPEN ⇔ CLOSE
  • OPENの時にメインコンテンツをtouchmoveするとメインコンテンツを動かす
  • touchendで位置を取得し、OPEN or CLOSE
  • OPENのときはメインコンテンツをスクロールさせない

問題点

  • メニューが長い時にスクロールさせなければいけない
  • メニューをtranslateで動かすが、ぎこちない
  • iOSではtranslateさせた中の要素にposition: fixed;が効かない
  • iOS8では横向きでposition: fixed;のヘッダーが崩れた

改善策

  • メニューのtouchmoveの時間に合わせてスムーズにスクロールさせた
  • position: fixed;が効かない部分は親要素じゃなくそれぞれをtranslateさせた
  • iOS8の横向きposition: fixed;は都度、対応しよう!

デモとソース

デモ (スマホ)
ソース

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
18