0
0

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 1 year has passed since last update.

ヘッダーの追従固定化(jQuery利用・keyframes利用)

Posted at

お世話になっております。コウヤです。

先日、Webデザイン・コーディングの中級卒業課題を終え、プロの方にOKをいただきました!
続けて、PHPやWordpressあたりに手を付けようと思いますが、その前に、今回の課題で得たスキルをまとめていきたいと思います。

今回はページ内を移動した際に、ヘッダーが固定化されるようなデザインを考えていこうと思います。

追従ヘッダーとは

以下のように、ヘッダーがあります。
image.png

よく見かけるデザイン化と思いますが、ページ内スクロールをすると、以下のようにヘッダーが表示され、それを追従して固定化ように表示させることを考えます。
image.png

今回の作成において、スマートフォンによるレスポンシブ化は考慮しておりません。PCのみで考えます。(コードが長くなるため)

ヘッダー部分の作成

まずは追従させることは考慮せず、以下のヘッダー部分の作成をしていきます。(下記の赤枠の箇所)
image.png

追従機能を確認するため、HTMLでは「MissionVision」という形で xxxxxxxxxx という文字も入れております。

.index.html
    <!--first view(ヘッダメニュー)-->
    <header class="header">
        <div class="ly__wrapper_head">

            <div class="head__menu">
                <ul class="head__menu_area">
                    <li class="menu__item"><a href="#MissionVision">メニュー1</a></li>
                    <li class="menu__item"><a href="#CEO">メニュー2</a></li>
                    <li class="menu__item"><a href="#JobList">メニュー3</a></li>
                </ul>
            </div>      
        </div>
    </header>

<!--当社のMissionVision-->
   <main id="MissionVision">
        <div class="ly__wrapper_head">
            <div class="MissionVision__title_area">

                <h1>xxxxxxxxxxxxxxxxxxxxxxxxxxx</h1>
            </div>


            <div class="MissionVision__guide fadein">

                <h1>xxxxxxxxxxxxxxxx</h1>
                <p class="MissionVision__guide_sentence">
                    xxxxxxxxxxxxxxx
                    </p>
            </div>
            
            <div class="MissionVision__guide _reverse fadein">
                <p class="MissionVision__guide_sub_title">

                </p>
                <h1>xxxxxxxxxxxxxxxx
                </h1>
                <p class="MissionVision__guide_sentence">xxxxxxxxxxxxxxxxxxxxxxxxxxxx</p>
            </div>
        </div>
    </main>
style.css
  .header {
    border:1px solid red;
    height: 100px;
  }
  .head__menu {
    display: block;
  }

  .head__menu {
    margin:0 auto;
    line-height: 100px;
  }

  .head__menu_area {
    display: flex;
    flex-direction: row;
    align-items: center;
  }
  .head__menu_area li:not(:last-of-type) {
    margin-right: 25px;
  }
  .head__menu_area .menu__item a {
    color: red;
    font-family: Noto Sans JP;
    font-size: 12px;
    font-style: normal;
    font-weight: 400;
    line-height: normal;
  }


#MissionVision {
  margin-top: 191px;
  height: 1243px;
  background-image: url(../img/mission-bg.png);
  background-repeat: no-repeat;
  background-position: bottom center;
}
#MissionVision .MissionVision__title_area {
  text-align: center;
  margin-bottom: 132px;
}
#MissionVision .MissionVision__title_area .MissionVision__sub_title {
  display: inline-block;
  width: 98px;
  height: 12px;
  flex-shrink: 0;
  margin-bottom: 9px;
}
#MissionVision .MissionVision__title_area h1 {
  color: #333;
  font-family: Noto Sans JP;
  font-size: 20px;
  font-style: normal;
  font-weight: 700;
  line-height: normal;
}

このCSSの下にさらに以下のコードを追加します。

style.css
#MissionVision .MissionVision__title_area .MissionVision__sub_title {
/*上記と同じ*/
}

#MissionVision .MissionVision__title_area h1 {
/*上記と同じ*/
}

/*追従header*/
.header--sticky {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  opacity: 1;
  visibility: visible;
  animation: slideDown 0.3s ease-in-out;
  background-color: #ccccff;
  z-index: 20;
}

.header--sticky .menu__item a {
  color: red;
}

@keyframes kf-slideDown {
  0% {
    transform: translateY(-100%);
  }
  100% {
    transform: translateY(0%);
  }
}

説明します。.header--stickyというクラスはHTML上には記載はないですが、後ほどjQueryでそのクラスを追加するという処理を行います。

.header--sticky {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  opacity: 1;
  visibility: visible;
  animation: kf-slideDown 0.3s ease-in-out;
  background-color: #ccccff;
  z-index: 20;
}

追従操作をさせるため、positionではfixedを設定しています。
今回重要なのは、animationの箇所です。このanimationの箇所に記載のあるkf-slideDownは勝手につけた名前で、これが以下のkeyframesにかかってきます。

@keyframes kf-slideDown {
  0% {
    transform: translateY(-100%);
  }
  100% {
    transform: translateY(0%);
  }
}

この時点ではまだ動かないのでご注意ください。

ここでは何をしているかというと、animationで0.3sと指定していますが、この0.3秒の間に、最初の0%(0秒時点)ではヘッダはY軸(縦方向)に-100%の位置に隠れており、最後の100%(0.3秒時点)では0%の位置にヘッダがある状態となります。

【最初の0%時点】
紫背景(緑枠)のヘッダは-100%の位置に隠れている状態
image.png

【最後の100%の時点】
紫背景は0%の位置に表示される状態
image.png

これは今回、0%と100%で行ったが、間に50%を入れることも可能ですので試してみてください。

jQueryで動作させる

それではjQueryで動作させます。以下のようにコードを書きます。

.script_JQ.js
/*追従ヘッダー */
window.addEventListener('scroll', function() {
	const header = document.querySelector('.header');
	const headerHeight = header.offsetHeight; // ヘッダーの高さを取得
	
	if ($(this).scrollTop() > 100) {
	  header.classList.add('header--sticky');
	  document.body.style.marginTop = headerHeight + 'px'; // コンテンツにヘッダーの高さ分の余白を設定
	} else {
	  header.classList.remove('header--sticky');
	  document.body.style.marginTop = '0'; // コンテンツの余白をリセット
	}
  });

まず、addEventListenerではscrollしたら動作するといった処理を設定しています。
ifの箇所で「スクロールの位置が100px」を超過したら、CSSで指定した**.header--sticky**をHTML内の.headerクラスの箇所に追加(add)します。

$(this).scrollTop() > 100

またもし100px未満の位置にスクロールがあった際には、marginTopの位置を0にして、headerコンテンツの余白を0にしています。

##コードまとめ

index.html

    <!--first view(ヘッダメニュー)-->
    <header class="header">
        <div class="ly__wrapper_head">

            <div class="head__menu">
                <ul class="head__menu_area">
                    <li class="menu__item"><a href="#MissionVision">メニュー1</a></li>
                    <li class="menu__item"><a href="#CEO">メニュー2</a></li>
                    <li class="menu__item"><a href="#JobList">メニュー3</a></li>
                </ul>
            </div>
          

        </div>

    </header>

    <!--メイン画像-->


    <main id="MissionVision">
        <div class="ly__wrapper_head">
            <div class="MissionVision__title_area">

                <h1>xxxxxxxxxxxxxxxxxxxxxxxxxxx</h1>
            </div>


            <div class="MissionVision__guide fadein">

                <h1>xxxxxxxxxxxxxxxx</h1>
                <p class="MissionVision__guide_sentence">
                    xxxxxxxxxxxxxxx
                    </p>
            </div>
            
            <div class="MissionVision__guide _reverse fadein">
                <p class="MissionVision__guide_sub_title">

                </p>
                <h1>xxxxxxxxxxxxxxxx
                </h1>
                <p class="MissionVision__guide_sentence">xxxxxxxxxxxxxxxxxxxxxxxxxxxx</p>
            </div>
        </div>
    </main>

style.css
@charset "UTF-8";
/*ベース
*********************/
body {
  color: #333333;
  font-family: "Noto Sans JP", sans-serif;
}

a {
  text-decoration: none;
  color: #333333;
}

img {
  height: auto;
  max-width: 100%;
}

.break {
  display: block;
}





/*レイアウト
*********************/

/********************/
/*★header
*********************/
.header {
  height: 60px;
}
.header .ly__wrapper_head {
  padding-left: 20px;
  padding-right: 20px;
}

.header .ly__wrapper_head {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
}

.head__menu {
  display: none;
}





  .header {
    border:1px solid red;
    height: 100px;
  }
  .head__menu {
    display: block;
  }

  .head__menu {
    margin:0 auto;
    line-height: 100px;
  }

  .head__menu_area {
    display: flex;
    flex-direction: row;
    align-items: center;
  }
  .head__menu_area li:not(:last-of-type) {
    margin-right: 25px;
  }
  .head__menu_area .menu__item a {
    color: red;
    font-family: Noto Sans JP;
    font-size: 12px;
    font-style: normal;
    font-weight: 400;
    line-height: normal;
  }
 

/*追従header*/
.header--sticky {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  opacity: 1;
  visibility: visible;
  animation: kf-slideDown 0.5s ease-in-out;
  background-color: #ccccff;
  z-index: 20;
}

.header--sticky .menu__item a {
  color: red;
}

@keyframes kf-slideDown {
  0% {
    transform: translateY(-100%);
  }

  100% {
    transform: translateY(0%);
  }
}

#MissionVision {
  margin-top: 191px;
  height: 1243px;
  background-image: url(../img/mission-bg.png);
  background-repeat: no-repeat;
  background-position: bottom center;
}
#MissionVision .MissionVision__title_area {
  text-align: center;
  margin-bottom: 132px;
}
#MissionVision .MissionVision__title_area .MissionVision__sub_title {
  display: inline-block;
  width: 98px;
  height: 12px;
  flex-shrink: 0;
  margin-bottom: 9px;
}
#MissionVision .MissionVision__title_area h1 {
  color: #333;
  font-family: Noto Sans JP;
  font-size: 20px;
  font-style: normal;
  font-weight: 700;
  line-height: normal;
}

script_JQ.js
/*追従ヘッダー */
window.addEventListener('scroll', function() {
	const header = document.querySelector('.header');
	const headerHeight = header.offsetHeight; // ヘッダーの高さを取得
	
	if ($(this).scrollTop() > 100) {
	  header.classList.add('header--sticky');
	  document.body.style.marginTop = headerHeight + 'px'; // コンテンツにヘッダーの高さ分の余白を設定
	} else {
	  header.classList.remove('header--sticky');
	  document.body.style.marginTop = '0'; // コンテンツの余白をリセット
	}
  });

0
0
2

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?