【ソースコード】上級編:メディアサイト/グリッドレイアウト

目次

※コーディングの解説はCSSのコメントを参照

ディレクトリ構成

    
media
 ├─img
 │  ├─favicon.ico
 │  ├─logo.svg
 │  ├─pickup1.jpg ~ pickup9.jpg
 │  └─feature1.jpg ~ feature9.jpg
 │
 ├─css
 │  └─style.css
 │
 ├─js
 │  └─main.js
 │
 ├─video
 │  └─video.mp4
 │
 └─index.html
    
  

HTML(index.html)

別タブで開く
index.html

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Sneakers</title>
    <meta name="description" content="テキストテキストテキストテキストテキストテキストテキストテキス">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="shortcut icon" href="img/favicon.ico">
    <link rel="stylesheet" href="https://unpkg.com/ress/dist/ress.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick.min.css">
    <link rel="stylesheet" href="css/style.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick.min.js"></script>
    <script src="js/main.js"></script>
  </head>

  <body>
    <header id="header">
      <h1 class="site-title">
        <a href="index.html"><img src="img/logo.svg" alt="Sneakers"></a>
      </h1>

      <nav id="navi">
        <ul class="nav-menu">
          <li><a href="#pickup">PICK UP</a></li>
          <li><a href="#feature">FEATURE</a></li>
          <li><a href="#contact">CONTACT</a></li>
        </ul>
        <ul class="nav-sns">
          <li><a href="https://twitter.com/" target="_blank">Twitter</a></li>
          <li><a href="https://www.facebook.com/" target="_blank">facebook</a></li>
          <li><a href="https://www.instagram.com/" target="_blank">instagram</a></li>
        </ul>
      </nav>

      <div class="toggle_btn">
        <span></span>
        <span></span>
        <span></span>
      </div>

      <div id="mask"></div>
    </header>

    <main id="main">
      <div id="video">
        <video id="bg-video" src="video/video.mp4" loop autoplay muted playsinline></video>
      </div>

      <section id="pickup">
        <h2 class="sec-title">PICK UP</h2>
        <ul class="slick-area">
          <li><img src="img/pickup1.jpg" alt="ピックアップ1 テキストテキスト"></li>
          <li><img src="img/pickup2.jpg" alt="ピックアップ2 テキストテキスト"></li>
          <li><img src="img/pickup3.jpg" alt="ピックアップ3 テキストテキスト"></li>
          <li><img src="img/pickup4.jpg" alt="ピックアップ4 テキストテキスト"></li>
          <li><img src="img/pickup5.jpg" alt="ピックアップ5 テキストテキスト"></li>
          <li><img src="img/pickup6.jpg" alt="ピックアップ6 テキストテキスト"></li>
          <li><img src="img/pickup7.jpg" alt="ピックアップ7 テキストテキスト"></li>
          <li><img src="img/pickup8.jpg" alt="ピックアップ8 テキストテキスト"></li>
          <li><img src="img/pickup9.jpg" alt="ピックアップ9 テキストテキスト"></li>
        </ul>
      </section>

      <section id="feature">
        <h2 class="sec-title">FEATURE</h2>
        <div class="grid">
          <div class="item">
            <img class="fadein" src="img/feature1.jpg" alt="">
            <div class="item-content">
              <p class="item-cat">category</p>
              <p class="item-text">テキストテキストテキストテキストテキストテキストテキストテキスト</p>
              <p class="item-date">XXXX.XX.XX</p>
            </div>
          </div>

          <div class="item">
            <img class="fadein" src="img/feature2.jpg" alt="">
            <div class="item-content">
              <p class="item-cat">category</p>
              <p class="item-text">テキストテキストテキストテキストテキストテキストテキストテキスト</p>
              <p class="item-date">XXXX.XX.XX</p>
            </div>
          </div>

          <div class="item">
            <img class="fadein" src="img/feature3.jpg" alt="">
            <div class="item-content">
              <p class="item-cat">category</p>
              <p class="item-text">テキストテキストテキストテキストテキストテキストテキストテキスト</p>
              <p class="item-date">XXXX.XX.XX</p>
            </div>
          </div>

          <div class="item">
            <img class="fadein" src="img/feature4.jpg" alt="">
            <div class="item-content">
              <p class="item-cat">category</p>
              <p class="item-text">テキストテキストテキストテキストテキストテキストテキストテキスト</p>
              <p class="item-date">XXXX.XX.XX</p>
            </div>
          </div>

          <div class="item">
            <img class="fadein" src="img/feature5.jpg" alt="">
            <div class="item-content">
              <p class="item-cat">category</p>
              <p class="item-text">テキストテキストテキストテキストテキストテキストテキストテキスト</p>
              <p class="item-date">XXXX.XX.XX</p>
            </div>
          </div>

          <div class="item">
            <img class="fadein" src="img/feature6.jpg" alt="">
            <div class="item-content">
              <p class="item-cat">category</p>
              <p class="item-text">テキストテキストテキストテキストテキストテキストテキストテキスト</p>
              <p class="item-date">XXXX.XX.XX</p>
            </div>
          </div>

          <div class="item">
            <img class="fadein" src="img/feature7.jpg" alt="">
            <div class="item-content">
              <p class="item-cat">category</p>
              <p class="item-text">テキストテキストテキストテキストテキストテキストテキストテキスト</p>
              <p class="item-date">XXXX.XX.XX</p>
            </div>
          </div>

          <div class="item">
            <img class="fadein" src="img/feature8.jpg" alt="">
            <div class="item-content">
              <p class="item-cat">category</p>
              <p class="item-text">テキストテキストテキストテキストテキストテキストテキストテキスト</p>
              <p class="item-date">XXXX.XX.XX</p>
            </div>
          </div>

          <div class="item">
            <img class="fadein" src="img/feature9.jpg" alt="">
            <div class="item-content">
              <p class="item-cat">category</p>
              <p class="item-text">テキストテキストテキストテキストテキストテキストテキストテキスト</p>
              <p class="item-date">XXXX.XX.XX</p>
            </div>
          </div>
        </div>
      </section>

      <section id="contact">
        <h2 class="sec-title">CONTACT</h2>
        <div class="content">
          <div class="contact-info">
            <p>テキストテキストテキスト</p>
            <p>
              テキストテキストテキストテキストテキストテキストテキストテキストテキスト
              テキストテキストテキストテキストテキストテキストテキストテキストテキスト
              テキストテキストテキストテキストテキストテキストテキストテキストテキスト
            </p>
            <p>
              テキストテキストテキストテキストテキストテキストテキストテキストテキスト
              テキストテキストテキストテキストテキストテキストテキストテキストテキスト
              テキストテキストテキストテキストテキストテキストテキストテキストテキスト
            </p>
          </div>

          <div class="contact-form">
            <form action="#">
              <dl>
                <dt><label for="name">Name:</label></dt>
                <dd><input type="text" id="name" name="your-name"></dd>
                <dt><label for="email">Mail:</label></dt>
                <dd><input type="email" id="email" name="your-email"></dd>
                <dt><label for="message">Message:</label></dt>
                <dd><textarea id="message" name="your-message"></textarea></dd>
              </dl>
              <div class="button"><input type="submit" value="SEND"></div>
            </form>
          </div>
        </div>
      </section>
    </main>

    <footer id="footer">
      <p>&copy; Sneakers</p>
    </footer>

  </body>
</html>


CSS(style.css)

別タブで開く
style.css

@charset "UTF-8";

html {
  font-size: 100%;
}
body {
  color: #121212;
  font-size: 0.9rem;
  line-height: 1.7;
}
a {
  color: #121212;
  text-decoration: none;
}
img {
  max-width: 100%;
}
li {
  list-style: none;
}
.site-title {
  line-height: 1px;
}
.site-title a {
  display: block;
}
.sec-title {
  font-size: 2.25rem;
  margin-bottom: 30px;
  text-align: center;
}
/*
フェード表示させる要素に使用するためのクラス
*/
.fadein {
  opacity : 0;
  transform: translateY(20px);
  transition: all 1s;
}

/*-------------------------------------------
ヘッダー
-------------------------------------------*/
/*
「position: fixed;」でヘッダーを固定し、「z-index: 10;」で前面に表示
※他のコンテンツでpositionをrelative、absolute、fixedのいずれかに
設定している場合は、z-indexの数値が大きい方が前面に表示される
*/
#header {
  width: 100%;
  display: flex;
  justify-content: space-between;
  padding: 20px 40px;
  position: fixed;
  z-index: 10;
  background-color: #fff;
}
/*
ハンバーガーメニュー
解説は、「中級編:ストアサイト(インテリア)」のCSS参照
*/
#navi {
  display: block;
  position: fixed;
  top: 0;
  left: -300px;
  bottom: 0;
  width: 300px;
  color: #fff;
  padding: 60px 25px;
  background-color: #121212;
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  transition: all .5s;
  z-index: 20;
  opacity: 0;
}
#navi a {
  color: #fff;
}
.open #navi {
  left: 0;
  opacity: 1;
}
#navi ul {
  margin: 0;
  padding: 0;
}
#navi ul.nav-menu {
  margin-bottom: 60px;
  border-top: solid 1px #fff;
}
#navi ul.nav-menu li {
  position: relative;
  margin: 0;
  padding: 20px 0;
  border-bottom: solid 1px #fff;
}
#navi ul.nav-sns li {
  padding: 5px 0;
}
.toggle_btn {
  display: block;
  position: fixed;
  top: 25px;
  right: 45px;
  width: 30px;
  height: 30px;
  transition: all .5s;
  cursor: pointer;
  z-index: 20;
}
.toggle_btn span {
  display: block;
  position: absolute;
  left: 0;
  width: 30px;
  height: 2px;
  background-color: #333;
  border-radius: 4px;
  transition: all .5s;
}
.toggle_btn span:nth-child(1) {
  top: 4px;
}
.toggle_btn span:nth-child(2) {
  top: 14px;
}
.toggle_btn span:nth-child(3) {
  bottom: 4px;
}
.open .toggle_btn span {
  background-color: #fff;
}
.open .toggle_btn span:nth-child(1) {
  -webkit-transform: translateY(10px) rotate(-315deg);
  transform: translateY(10px) rotate(-315deg);
}
.open .toggle_btn span:nth-child(2) {
  opacity: 0;
}
.open .toggle_btn span:nth-child(3) {
  -webkit-transform: translateY(-10px) rotate(315deg);
  transform: translateY(-10px) rotate(315deg);
}
#mask {
  display: none;
  transition: all .5s;
}
.open #mask {
  display: block;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: #000;
  opacity: .8;
  z-index: 10;
  cursor: pointer;
}

/*-------------------------------------------
Main
-------------------------------------------*/
#main {
  padding-top: 80px;
}

/*-------------------------------------------
Video
-------------------------------------------*/
#bg-video {
  width: 100%;
}

/*-------------------------------------------
Pickup
-------------------------------------------*/
#pickup {
  width: 100%;
  padding: 100px 0 50px 0;
}
#pickup .slick-area {
  font-size: 0;
}
#pickup .slick-area li {
  padding: 0 30px;
}

/*-------------------------------------------
Feature
-------------------------------------------*/
#feature {
  max-width: 1240px;
  padding: 100px 16px 50px 16px;
  margin: -50px auto 10px auto;
}
/*
グリッドレイアウト
要素の最小サイズは300pxで、画面の幅にあわせて要素の幅が自動で変化する
repeatで全ての要素に対して適用
「gap: 26px;」で行と列の隙間を設定
*/
#feature .grid {
  display: grid;
  gap: 26px;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
#feature .grid .item {
  transition: all  0.3s ease;
  box-shadow: 0 0 8px 4px #ccc;
}
#feature .grid img {
  vertical-align: top;
}
#feature .grid .item-content {
  padding: 30px;
}
#feature .grid .item-cat {
  font-size: 0.75rem;
  margin-bottom: 20px;
}
#feature .grid .item-text {
  font-weight: bold;
  margin-bottom: 20px;
}
#feature .grid .item-date {
  font-size: 0.75rem;
  text-align: right;
}
/*-------------------------------------------
Contact
-------------------------------------------*/
#contact {
  color: #fff;
  background-color: #121212;
  padding: 50px 0;
}
#contact .sec-title {
  color: #fff;
}
#contact .content {
  max-width: 1240px;
  padding: 0 16px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
}
#contact .contact-info p {
  margin-bottom: 30px;
}
#contact .contact-info,
#contact .contact-form {
  width: 45%;
}
#contact .contact-form input,
#contact .contact-form textarea {
  width: 100%;
  background-color: #fff;
  padding: 10px;
  margin-bottom: 20px;
}
#contact .contact-form .button input {
  width: 200px;
  color: #fff;
  background-color: #121212;
  border: solid 1px #fff;
  padding: 12px 0;
  margin-bottom: 0;
}
#contact .contact-form .button input:hover {
  color: #202020;
  background-color: #fff;
}

/*-------------------------------------------
フッター
-------------------------------------------*/
#footer {
  color: #fff;
  background-color: #121212;
  text-align: center;
  padding: 10px;
  font-size: 0.75rem;
}

/*-------------------------------------------
SP
-------------------------------------------*/
@media screen and (max-width: 600px) {
  .sec-title {
    font-size: 1.5rem;
    margin-bottom: 20px;
  }

  /*-------------------------------------------
  ヘッダー
  -------------------------------------------*/
  #header {
    padding: 20px 16px;
  }
  .toggle_btn {
    right: 20px;
  }

  /*-------------------------------------------
  Video
  -------------------------------------------*/
  /*
  「height: 100vh;」で画面の高さにあわせる
  「object-fit: cover;」で中央でトリミング
  */
  #bg-video {
    width: 100%;
    height: 100vh;
    object-fit: cover;
  }

  /*-------------------------------------------
  Pickup
  -------------------------------------------*/
  #pickup {
    padding: 80px 0;
  }
  #pickup .slick-area li {
    padding: 0 20px;
  }

  /*-------------------------------------------
  Feature
  -------------------------------------------*/
  #feature {
    padding: 80px 16px;
  }
  #feature .grid .item-content {
    padding: 16px;
  }

  /*-------------------------------------------
  Contact
  -------------------------------------------*/
  #contact {
    padding: 80px 0;
  }
  #contact .content {
    flex-direction: column;
  }
  #contact .contact-info,
  #contact .contact-form {
    width: 100%;
  }
  #contact .contact-form .button input {
    width: 100%;
  }
}


JavaScript(main.js)

別タブで開く
main.js

$(function(){
  /*=================================================
  スマホメニュー
  ===================================================*/
  // ハンバーガーメニューのクリックイベント
  // 解説は、「中級編:ストアサイト(インテリア)」参照
  $('.toggle_btn').on('click', function() {
    if (!$('#header').hasClass('open')) {
      $('#header').addClass('open');
    } else {
      $('#header').removeClass('open');
    }
  });

  // #maskのエリアをクリックした時にメニューを閉じる
  $('#mask').on('click', function() {
    $('#header').removeClass('open');
  });

  // リンクをクリックした時にメニューを閉じる
  $('#navi a').on('click', function() {
    $('#header').removeClass('open');
  });

  /*=================================================
  スムーススクロール
  ===================================================*/
  // ページ内リンクのイベント
  $('a[href^="#"]').click(function(){
    // リンクを取得
    let href= $(this).attr("href");
    // ジャンプ先のid名をセット
    let target = $(href == "#" || href == "" ? 'html' : href);
    // トップからジャンプ先の要素までの距離を取得
    let position = target.offset().top;
    // animateでスムーススクロールを行う
    // 600はスクロール速度で単位はミリ秒
    $("html, body").animate({scrollTop:position}, 600, "swing");
    return false;
  });

  /*=================================================
  PICK UP スライダー
  ===================================================*/
  // カルーセル用 jQueryプラグイン「slick」の設定
  // マニュアル:https://kenwheeler.github.io/slick/
  $('.slick-area').slick({
    arrows: false,
    centerMode: true,
    centerPadding: '100px',
    slidesToShow: 3,
    responsive: [
      {
        breakpoint: 768,
        settings: {
          centerPadding: '50px',
          slidesToShow: 1
        }
      }
    ]
  });

  /*=================================================
  スクロール時の画像フェード表示
  ===================================================*/
  // スクロール時のイベント
  $(window).scroll(function() {
    // fadeinクラスに対して順に処理を行う
    $('.fadein').each(function() {
      // スクロールした距離
      let scroll = $(window).scrollTop();
      // fadeinクラスの要素までの距離
      let target = $(this).offset().top;
      // 画面の高さ
      let windowHeight = $(window).height();
      // fadeinクラスの要素が画面下にきてから200px通過した
      // したタイミングで要素を表示
      if (scroll > target - windowHeight + 200) {
        $(this).css('opacity','1');
        $(this).css('transform','translateY(0)');
      }
    });
  });
});