• スマホ時にナビが格納される一般的なヘッダー
  • スクロールに追従(position: fixed)
  • スマホナビはオーバーレイ&右からスライド
<header class="header_01" roll="banner">
  <h1 class="header_01--logo">
    <a href="#"><img src="/assets/images/common/logo.svg" alt=""></a>
  </h1>

  <button class="header_01--nav_btn">
    <span></span>
    <span></span>
    <span></span>
  </button>

  <nav class="header_01--nav">
    <div class="header_01--nav_inner">
      <ul class="header_01--links">
        <li class="header_01--links_item"><a href="#">コンテンツ1</a></li>
        <li class="header_01--links_item"><a href="#">コンテンツ2</a></li>
        <li class="header_01--links_item"><a href="#">コンテンツ3</a></li>
      </ul>
      <div class="header_01--cta">
        <a class="header_01--cta_btn u-visible_sp" href="#">お問い合わせ</a>
        <a class="header_01--cta_btn_primary u-hidden_sp" href="#">お問い合わせ</a>
      </div>
    </div>
  </nav>
</header><!-- /.header_01 -->
/* No context defined. */
  • Content:
    // =====================================================================================
    //
    // header_01
    //
    // =====================================================================================
    
    @use 'sass:math';
    @use 'scss/global' as g;
    @use 'scss/components/btn';
    
    // ※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
    // Roots外スタイル
    //  - ヘッダーをposition:fixedにするため全体枠に余白を作る
    //  - 例外的にRoots外のスタイリング(=ルール違反)を許容するか、該当の.scssへコピーしてください
    // ※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
    .all {
      padding-top: 53px;
    
      @include g.mq(tablet, pc) {
        padding-top: 53px;
      }
    }
    
    // -------------------------------------------------------------------------------------
    // 変数
    // -------------------------------------------------------------------------------------
    
    // スマホナビ展開アニメーションの継続時間
    $duration: 0.3s;
    
    // スマホナビ展開アニメーションのイージング
    $easing: g.$ease_out_cubic;
    
    // スマホナビ展開ボタンの継続時間
    $btn_duration: 0.3s;
    
    // スマホナビ展開ボタンのイージング
    $btn_easing: g.$ease_out_expo;
    
    // -------------------------------------------------------------------------------------
    // ヘッダー全体
    // -------------------------------------------------------------------------------------
    .header_01 {
      position: fixed;
      top: 0;
      left: 0;
      display: flex;
      justify-content: space-between;
      width: 100%;
      height: 53px;
      padding: 0 0 0 15px;
    
      @include g.mq(tablet, pc) {
        height: 70px;
        padding-left: 24px;
      }
    }
    
    // -------------------------------------------------------------------------------------
    // ヘッダー全体 > ロゴ
    // -------------------------------------------------------------------------------------
    .header_01--logo {
      width: 44px;
      margin: 20px 0 0;
    
      @include g.mq(tablet, pc) {
        width: 90px;
      }
    
      img {
        display: block;
        width: 100%;
      }
    }
    
    // -------------------------------------------------------------------------------------
    // ヘッダー全体 > ナビゲーション全体
    // -------------------------------------------------------------------------------------
    .header_01--nav {
      position: fixed;
      top: 0;
      left: 0;
      display: none;
      width: 100%;
      height: 100%;
      overflow-x: hidden;
      background: rgba(0, 0, 0, 0);
    
      @include g.mq(tablet, pc) {
        position: relative;
        display: flex;
        align-items: center;
        width: auto;
        padding: 0;
        overflow-y: visible;
        background: transparent;
      }
    
      &.is_open {
        display: block;
      }
    
      &.header_01-close_anim {
        display: block;
        animation: header_nav_toggle math.div($duration, 2) $easing reverse;
      }
    
      &.header_01-open_anim {
        display: block;
        animation: header_nav_toggle $duration $easing;
      }
    }
    
    @keyframes header_nav_toggle {
      0% {
        opacity: 0;
      }
      100% {
        opacity: 1;
      }
    }
    
    // -------------------------------------------------------------------------------------
    // ヘッダー全体 > ナビゲーション全体 > ナビゲーション内枠
    // -------------------------------------------------------------------------------------
    .header_01--nav_inner {
      position: absolute;
      top: 0;
      right: 0;
      width: 280px;
      min-height: 100%;
      padding: 53px 0 40px;
      background: g.$color_primary;
    
      @include g.mq(tablet, pc) {
        position: relative;
        display: flex;
        align-items: center;
        width: auto;
        min-height: auto;
        padding: 0;
        background: transparent;
      }
    
      .header_01-close_anim & {
        animation: header_nav_inner_toggle math.div($duration, 2) $easing reverse;
      }
    
      .header_01-open_anim & {
        animation: header_nav_inner_toggle $duration $easing;
      }
    }
    
    @keyframes header_nav_inner_toggle {
      0% {
        transform: translateX(280px);
      }
      100% {
        transform: translateX(0);
      }
    }
    
    // -------------------------------------------------------------------------------------
    // ヘッダー全体 > ナビゲーション全体 > ナビゲーション内枠 > リンク
    // -------------------------------------------------------------------------------------
    .header_01--links {
      margin: 0 0 70px;
      border-top: 1px solid #fff;
    
      @include g.mq(tablet, pc) {
        margin: 0;
        border: none;
      }
    }
    
    .header_01--links_item {
      border-bottom: 1px solid #fff;
    
      @include g.mq(tablet, pc) {
        display: inline-block;
        margin: 0 32px 0 0;
        border: none;
      }
    
      @include g.mq(tablet) {
        margin-right: 24px;
      }
    
      a {
        position: relative;
        display: block;
        padding: 16px 20px;
        color: #fff;
        text-align: left;
        background-image: url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 12 12"><path fill="%23fff" d="M2.8,10.9L7.8,6L2.8,1.1l0.7-0.7L9.2,6l-5.7,5.7L2.8,10.9z" /></svg>');
        background-repeat: no-repeat;
    
        background-position: right 16px top 50%;
        background-size: 12px 12px;
    
        @include g.mq(tablet, pc) {
          display: inline-block;
          padding: 0;
          color: g.$color_text_base;
          background: none;
        }
      }
    }
    
    // -------------------------------------------------------------------------------------
    // ヘッダー全体 > ナビゲーション全体 > ナビゲーション内枠 > Call to Action
    // -------------------------------------------------------------------------------------
    .header_01--cta {
      text-align: center;
    }
    
    // ※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
    // 他のRootsの拡張はルール違反だが、一旦そのまま(ルールの方を見直したほうが良さそうなため)
    // ※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
    .header_01--cta_btn {
      @extend .btn, .btn-s;
      outline: none;
    }
    
    .header_01--cta_btn_primary {
      @extend .btn, .btn-auto, .btn-primary;
      height: 70px;
      padding-top: 0;
      padding-bottom: 0;
      line-height: 70px;
    }
    
    // -------------------------------------------------------------------------------------
    // ヘッダー全体 > スマホメニュー展開ボタン
    // -------------------------------------------------------------------------------------
    .header_01--nav_btn {
      position: relative;
      z-index: 1;
      box-sizing: border-box;
      display: inline-block;
      width: 52px;
      height: 52px;
      cursor: pointer;
      background: g.$color_primary;
      transition: all $btn_duration $btn_easing;
    
      @include g.mq(tablet, pc) {
        display: none;
      }
    
      span {
        position: absolute;
        left: 16px;
        box-sizing: border-box;
        display: inline-block;
        width: 20px;
        height: 2px;
        background-color: #fff;
        transition: all $btn_duration $btn_easing;
    
        &:nth-of-type(1) {
          top: 17px;
        }
    
        &:nth-of-type(2) {
          top: 25px;
          opacity: 1;
        }
    
        &:nth-of-type(3) {
          bottom: 17px;
        }
      }
    
      &.is_close span:nth-of-type(1) {
        animation: header_nav_btn_bar01 $btn_duration $btn_easing forwards;
      }
    
      &.is_close span:nth-of-type(2) {
        transition: all $btn_duration $btn_easing;
      }
    
      &.is_close span:nth-of-type(3) {
        animation: header_nav_btn_bar03 $btn_duration $btn_easing forwards;
      }
    
      &.is_open span:nth-of-type(1) {
        animation: active_header_nav_btn_bar01 $btn_duration $btn_easing forwards;
      }
    
      &.is_open span:nth-of-type(2) {
        opacity: 0;
      }
    
      &.is_open span:nth-of-type(3) {
        animation: active_header_nav_btn_bar03 $btn_duration $btn_easing forwards;
      }
    }
    
    @keyframes header_nav_btn_bar01 {
      0% {
        transform: translateY(8px) rotate(45deg);
      }
      50% {
        transform: translateY(8px) rotate(0);
      }
      100% {
        transform: translateY(0) rotate(0);
      }
    }
    
    @keyframes header_nav_btn_bar03 {
      0% {
        transform: translateY(-8px) rotate(-45deg);
      }
      50% {
        transform: translateY(-8px) rotate(0);
      }
      100% {
        transform: translateY(0) rotate(0);
      }
    }
    
    @keyframes active_header_nav_btn_bar01 {
      0% {
        transform: translateY(0) rotate(0);
      }
      50% {
        transform: translateY(8px) rotate(0);
      }
      100% {
        transform: translateY(8px) rotate(45deg);
      }
    }
    
    @keyframes active_header_nav_btn_bar03 {
      0% {
        transform: translateY(0) rotate(0);
      }
      50% {
        transform: translateY(-8px) rotate(0);
      }
      100% {
        transform: translateY(-8px) rotate(-45deg);
      }
    }
    
  • URL: /components/raw/header_01/_header_01.scss
  • Filesystem Path: src/assets/_parts/frame/header/header_01/_header_01.scss
  • Size: 8.7 KB
  • Content:
    // =====================================================================================
    //
    // header_01
    //  - このファイルを「src/assets/js/frame」に移動の上、「js/main.js」から呼び出してください
    //  - 記述例:
    //      import header from './frame/header';
    //      header('header');
    //
    // =====================================================================================
    
    import $ from 'jquery';
    
    export default function (rootsName = 'header_01') {
      // スクロール無効化
      function disableScroll() {
        let scrollPosition;
        const body = document.getElementsByTagName('body')[0];
        const ua = window.navigator.userAgent.toLowerCase();
        const isiOS =
          ua.indexOf('iphone') > -1 ||
          ua.indexOf('ipad') > -1 ||
          (ua.indexOf('macintosh') > -1 && 'ontouchend' in document);
        const scrollBarWidth = window.innerWidth - document.body.clientWidth;
        body.style.paddingRight = scrollBarWidth + 'px';
        if (isiOS) {
          scrollPosition = -window.pageYOffset;
          body.style.position = 'fixed';
          body.style.width = '100%';
          body.style.top = scrollPosition + 'px';
        } else {
          body.style.overflow = 'hidden';
        }
      }
    
      // スクロール有効化
      function enableScroll() {
        let scrollPosition;
        const body = document.getElementsByTagName('body')[0];
        const ua = window.navigator.userAgent.toLowerCase();
        const isiOS =
          ua.indexOf('iphone') > -1 ||
          ua.indexOf('ipad') > -1 ||
          (ua.indexOf('macintosh') > -1 && 'ontouchend' in document);
        body.style.paddingRight = '';
        if (isiOS) {
          scrollPosition = parseInt(body.style.top.replace(/[^0-9]/g, ''));
          body.style.position = '';
          body.style.width = '';
          body.style.top = '';
          window.scrollTo(0, scrollPosition);
        } else {
          body.style.overflow = '';
        }
      }
    
      $(function () {
        const $nav = $('.' + rootsName + '--nav');
        const $navBtn = $('.' + rootsName + '--nav_btn');
    
        function open() {
          if ($nav.hasClass('is_animated')) {
            return;
          }
    
          disableScroll();
    
          $navBtn.removeClass('is_close').addClass('is_open');
    
          $nav
            .on('animationend webkitAnimationend', function () {
              $nav
                .off('animationend webkitAnimationend')
                .removeClass(rootsName + '-open_anim')
                .removeClass('is_animated');
            })
            .addClass('is_open')
            .addClass(rootsName + '-open_anim')
            .addClass('is_animated');
        }
    
        function close() {
          if ($nav.hasClass('is_animated')) {
            return;
          }
    
          $navBtn.removeClass('is_open').addClass('is_close');
    
          $nav
            .on('animationend webkitAnimationend', function () {
              $nav
                .off('animationend webkitAnimationend')
                .removeClass(rootsName + '-close_anim')
                .removeClass('is_animated')
                .removeClass('is_open');
    
              enableScroll();
            })
            .addClass(rootsName + '-close_anim')
            .addClass('is_animated');
        }
    
        $navBtn.on('click', function () {
          if ($navBtn.hasClass('is_open')) {
            close();
          } else {
            open();
          }
    
          return false;
        });
    
        $nav.on('click', function (e) {
          if ($(e.target).hasClass(rootsName + '--nav')) {
            close();
          }
        });
      });
    }
    
  • URL: /components/raw/header_01/header_01.js
  • Filesystem Path: src/assets/_parts/frame/header/header_01/header_01.js
  • Size: 3.3 KB