JavaScript辞書

ハンバーガーメニュー

スライドショー

https://unpkg.com/swiper@8/swiper-bundle.min.cssは、CSSファイルをCDN(Content Delivery Network)から読み込むURLです。このURLには以下の意味があります。

  1. https://unpkg.com/:
    • unpkgは、CDNサービスの一種で、NPM(Node Package Manager)に登録されているパッケージをインターネット上で簡単に配布できるようにするサービスです。これにより、NPMパッケージをインストールすることなく、URLから直接読み込んで使うことができます。
  2. swiper@8:
    • これは「Swiper」というライブラリのバージョンを指定しています。@8はバージョン8のパッケージを指しており、特定のバージョンのSwiperを利用するために書かれています。
    • Swiperは、レスポンシブでタッチ対応のスライダー(カルーセル)ライブラリで、ウェブサイトにスライドショーやカルーセルを簡単に実装するために使用されます。
  3. swiper-bundle.min.css:
    • これは、Swiperのスタイルシート(CSSファイル)の名前です。swiper-bundleは、Swiperの全機能をまとめたCSSファイルであることを示しています。
    • min.cssは、このファイルが「minified(縮小版)」であることを示しています。これは、スペースや改行、不要なコメントが削除された、ファイルサイズを小さくしたバージョンで、読み込み速度を改善するために使われます。
<script>
  const swiper = new Swiper(".swiper", {
    // Optional parameters
    loop: true,

    // If we need pagination
    pagination: {
      el: ".swiper-pagination",
    },

    // Navigation arrows
    navigation: {
      nextEl: ".swiper-button-next",
      prevEl: ".swiper-button-prev",
    },
  })
</script>

このスクリプトは、人気のあるスライダーライブラリ「Swiper.js」を使って、スライドショー機能を設定するためのコードです。以下は各部分の説明です。

1. const swiper = new Swiper(".swiper", { ... });

  • Swiperクラスの新しいインスタンスを作成し、swiperという変数に格納しています。
  • .swiperは、スライダー要素を指定するクラスセレクターです。このクラスが付与されたHTML要素に対してスライダー機能を適用します。

2. loop: true,

  • スライドが最後まで到達したら、最初のスライドに自動的に戻るループ機能を有効にしています。trueは「有効」を意味します。

3. pagination: { el: ".swiper-pagination" },

  • スライダーにページネーション(インジケーターのようなもの)を追加します。elページネーションを表示する要素のクラス(.swiper-pagination)を指定しています。

4.navigation: { nextEl: ".swiper-button-next", prevEl: ".swiper-button-prev" },

  • スライダーのナビゲーションボタン(次へ、前へ)を設定しています。nextElで「次のスライド」ボタン、prevElで「前のスライド」ボタンの要素を指定します。それぞれのボタンに.swiper-button-nextおよび.swiper-button-prevというクラスが付与されている必要があります。

全体の動作

このコードは、指定されたHTMLの要素に対してスライドショー機能を実装します。スライドはループし、ページネーションとナビゲーションボタンが使用可能です。

その他疑問

.swiper-button-prev__origin{
  position:absolute;
  top: 0;
  bottom: 0; /* 追加 */
  left: 20px; /* 追加 */
  margin-top: auto; /* 追加 */
  margin-bottom: auto; /* 追加 */
  z-index: 10;
  width: 60px;
  height: 60px;
}

このスタイル定義では、.swiper-button-prev__originという要素の位置やサイズ、中央揃えの方法が指定されています。それぞれのプロパティがどのように作用しているかを詳しく解説します。

1. position: absolute;

  • 要素を絶対配置にします。これにより、通常のドキュメントフローから外れ、親要素(position: relative;などで位置指定された要素)に対して位置が指定されます。

2. top: 0;bottom: 0;

  • top: 0;bottom: 0; によって、この要素は上下の両端にぴったりくっつくように配置されます。要素の高さはその親要素に依存するため、親の高さに応じて要素が上下に引き伸ばされることはありません。
  • これによって、要素は上下の位置を0に固定されるため、要素の高さに関係なく、上下のマージンが均等になる準備が整います。

3. margin-top: auto;margin-bottom: auto;

  • top: 0;bottom: 0; を設定した状態で、margin-top: auto;margin-bottom: auto; を追加することで、要素を親要素の上下中央に配置します。
  • autoを使うことで、余白が自動的に計算され、上下の空きスペースが均等に割り振られます。その結果、要素が上下中央に揃います。

4. width: 60px;height: 60px;

  • 要素の幅と高さをそれぞれ60pxに固定します。この指定がなければ、要素のコンテンツに応じてサイズが変動してしまう可能性があります。具体的には、ナビゲーションボタンの大きさを均一に保ち、クリックしやすくするために、この固定サイズが役立ちます。

結果としての効果

  • この設定により、.swiper-button-prev__originという要素は、親要素の上下中央に配置され、60px四方の正方形として表示されます。
  • position: absolute; により自由に配置できる状態にし、topbottom を0にすることで上下いっぱいに配置される準備をし、margin-top: auto;margin-bottom: auto; で要素を中央揃えにしています。

この配置は、スライドのナビゲーションボタンが常に上下中央に来て、一定のサイズで見やすく操作しやすい位置に保たれることを意図しています。

補足:top: 0; bottom: 0; などを設定しない理由。

.swiper-slide-image {
width: 100%;
height: 100%;
object-fit: contain;
}

.swiper-slide-imageに対して top: 0;bottom: 0; などの位置指定をしない理由は、以下の点にあります。

1. width: 100%height: 100% の指定が目的に合っているため

  • このスタイルでは、スライド内の画像がスライド領域全体にフィットするように width: 100%;height: 100%; を指定しています。
    • width: 100%; により、画像の幅が親要素(スライド)の幅に合わせられます。
    • height: 100%; により、画像の高さも親要素(スライド)の高さに合わせられます。
  • このため、スライド全体を画像が占有する形で表示されるため、画像を上下や左右に揃えるための topbottom の指定は不要です。

2. object-fit: contain; の効果

  • object-fit: contain; は、画像の縦横比を保ちながら、画像全体が親要素内に収まるように配置されます。
    • これにより、画像が親要素の枠内で中央に収まり、縮小されて表示されます。親要素が長方形でも正方形でも、画像全体が見える形で表示されます。
    • topbottom を指定する必要がないのは、この object-fit の指定によって、画像が自動的に縦横の位置を調整してくれるためです。

3. 画像自体の配置に関係がないため

  • 画像はスライド全体を占めるように指定されているため、CSSで上下や左右の位置を細かく調整する必要がありません。
    • topbottom などは、主に 絶対配置 (position: absolute;) などで使われることが多く、要素を特定の場所に固定する目的で使用します。
    • しかし、ここではスライド内に画像がフルサイズで表示されることを目指しているので、こうした位置指定は不要です。

結論

  • .swiper-slide-imageは画像をスライド全体にうまく収めるためのスタイル設定です。画像自体の縦横比を保ちながら親要素内に収めるため、topbottom などの位置指定をする必要がなく、サイズ指定と object-fit: contain; で適切に中央揃えや拡大縮小が自動的に行われるためです。

タブメニュー

タブをクリックすると、他のタブとコンテンツが非表示になり、そのクリックされたタブと対応するコンテンツが表示されます。これを実現するために、クリックイベントを使ってタブとコンテンツの表示・非表示を制御しています。

1.タブとコンテンツを取得

const tabs = document.querySelectorAll(".Tab")
const contents = document.querySelectorAll(".Content")

document.querySelectorAll という関数は、HTMLの中からクラス名が “Tab”“Content” の要素をすべて探してきます。tabs にはタブ(クリックできるボタン)の要素が入り、contents にはそれに対応するコンテンツ(表示される内容)の要素が入ります。

2. タブにクリックイベントを追加

tabs.forEach((tab) => {
  tab.addEventListener("click", toggleTab)
})
  • ここで、forEach という関数を使って、すべてのタブに対して1つずつ処理を行っています。
  • addEventListener("click", toggleTab) は、各タブが クリック されたときに toggleTab という関数を実行するように指示しています。

つまり、各タブをクリックすると、toggleTab 関数が実行されるように設定されています。

3. toggleTab 関数の中身

function toggleTab(event) {
  tabs.forEach((tab) => tab.classList.remove("TabIsActive"))
  contents.forEach((content) =>
    content.classList.remove("ContentIsActive")
  )
  
  const clickedTab = event.currentTarget
  clickedTab.classList.add("TabIsActive")

  const targetContent = document.getElementById(clickedTab.dataset.id)
  targetContent.classList.add("ContentIsActive")
}

(1) すべてのタブとコンテンツの状態をリセット

tabs.forEach((tab) => tab.classList.remove("TabIsActive"))
contents.forEach((content) => content.classList.remove("ContentIsActive"))

まず、クリックされたときに、すべてのタブから “TabIsActive” というクラスを外します(これにより、どのタブも選択されていない状態に戻ります)。それと同様に、すべてのコンテンツから “ContentIsActive” というクラスを外します(これにより、すべてのコンテンツが非表示になります)。

(2) クリックされたタブにクラスを追加

const clickedTab = event.currentTarget
clickedTab.classList.add("TabIsActive")

event.currentTarget で、クリックされたタブ(clickedTab)を取得します。そして、そのクリックされたタブに “TabIsActive” というクラスを追加します。このクラスを追加することで、タブが「選ばれている」状態になるスタイルが適用されます。

(3) 対応するコンテンツを表示

const targetContent = document.getElementById(clickedTab.dataset.id)
targetContent.classList.add("ContentIsActive")

clickedTab.dataset.id は、クリックされたタブに対応するコンテンツのIDを取得します。このIDをもとに、表示するべきコンテンツを探し出します(getElementById)。そのコンテンツに “ContentIsActive” というクラスを追加して、対応する内容を表示します。

.ContentIsActive {
  display: block;
}

display: block; は、要素を ブロック要素 として表示します。これにより、display: none; で非表示になっていた要素が、クリックされたタブに応じて再び 画面に表示 されるようになります。

1. ブロック要素とは?

幅をいっぱいに取る: ブロック要素は、親要素の幅に応じて 可能な限りの幅 を取り、通常は他の要素と 横並びにならない です。つまり、同じ親要素内に別の要素があっても、ブロック要素はその行を独占して表示されます。

  • 例えば、ブロック要素は段落(<p>)や見出し(<h1><h6>)のような要素によく使われます。

次の要素は新しい行に表示される: ブロック要素の後には、次の要素が 新しい行 に表示されます。つまり、ブロック要素が終わったら、その次の要素はブロック要素の下に配置されます。

display: block; のメリット

  • フレキシブルな幅:親要素の幅に応じて自動的にサイズが決まるため、レイアウトに柔軟性があります。
  • セマンティクスの管理:特定の要素(例えば画像やリンク)を明示的にブロック要素として扱うことで、ページの構造を意図的にコントロールできます。
  • レイアウトしやすい:他の要素と縦に並びたいときに便利です。ブロック要素として扱うことで、隣接する要素との距離を簡単に制御できます。

2. ブロック要素とインライン要素の違い

display: block; は、ブロック要素として表示するのに対し、display: inline;インライン要素 として表示します。

インライン要素の特徴

幅を取らない: インライン要素は、必要な幅だけを取り、余分な幅は取りません。たとえば、<span><a> 要素がインライン要素です。

他の要素と横並びになる: インライン要素は、親要素内で他の要素と 横並び に表示されます。

モーダルウィンドウ

.Modalクラス

.Modal {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 20;
  margin: auto;
  width: 400px;
  height: 200px;
  padding: 32px;
  color: #fff;
  background-color: #6ba6e7;
}

で

  top: 0;
  bottom: 0;
  left: 0;
  right: 0;

を入れる理由を考えてください

モーダルウィンドウを画面の中央に固定し、ウィンドウ全体にわたってモーダルが表示されるようにするためです。以下に詳しく理由を説明します。

1. モーダルを中央に表示するため

  • position: fixed; は、ブラウザのスクロール位置にかかわらず、画面全体に対して固定される位置指定を行うものです。この状態で、top: 0; bottom: 0; left: 0; right: 0; を指定することで、モーダルウィンドウの四方の位置をウィンドウの端にくっつけます。これにより、モーダルの表示領域が画面全体に広がり、その上で margin: auto; を使うことで、モーダルのサイズが固定されたまま、中央に自動的に配置されます。

2. 余計なスペースを消し、フルスクリーン化の基準を確保する

  • top: 0; bottom: 0; left: 0; right: 0; は、モーダルが画面の最上端 (top: 0)、最下端 (bottom: 0)、左端 (left: 0)、右端 (right: 0) に張り付く設定です。このことで、モーダルの余白やずれを防ぎ、ウィンドウの中央で完全にモーダルを見せるための基準を作ります。width: 400pxheight: 200px のようなモーダルの具体的なサイズ設定があるので、中央に表示されるモーダル自体はそのサイズで収まり、四方には余白が生まれます。

3. モーダルが一貫して中央に配置されるデザイン

  • 画面サイズやスクロールに依存せず、ユーザーがどの画面サイズで表示しても、常にモーダルが 中央に表示される デザインを実現するための設定です。position: fixed; で常に画面の決まった位置に表示され、四隅がゼロの位置に固定されることで、ページの他の要素に影響されることなく、視覚的に一貫した中央配置が可能になります。

4. ユーザーの注意を引くためのフルスクリーン的な挙動

  • モーダルは通常、特別なメッセージや操作を行うためのポップアップ要素です。画面全体に重ねて表示されることで、ユーザーの注意を強く引くことができます。このため、top: 0; bottom: 0; left: 0; right: 0; の指定によって、モーダルが画面全体に広がるようにし、背景を覆い、ユーザーがモーダル外をクリックしたり操作したりするのを防ぎ、内容に集中させることができます。

背景

.Overlay {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 10;
  width: 100vw;
  height: 100vh;
  background-color: rgba(0, 0, 0, 0.2);
}

.Overlay クラスのスタイル設定は、モーダルウィンドウなどの背後に半透明の背景を表示するためのものです。具体的に説明すると、以下のような意味を持っています。

1. position: fixed;

  • これは、要素を 画面全体に固定 するプロパティです。スクロールしても画面の表示領域に対して常に同じ位置に表示されます。つまり、ページがスクロールされても、.Overlay は画面全体を覆ったまま動かないという意味です。

2. top: 0; left: 0;

  • これにより、要素の左上の角が画面の左上隅 (top: 0left: 0) に固定されます。つまり、画面の左上からスタートして、右下まで広がるように配置 されます。

3. z-index: 10;

  • このプロパティは、要素の重なり順(表示の前後関係)を指定します。z-index: 10; とすることで、他の要素より前面に表示されます。例えば、z-index が 5 の要素よりも .Overlay は前面に表示されますが、z-index: 20 の要素よりは背面に表示されます。この例では、z-index: 20; のモーダルウィンドウが .Overlay の上に表示される想定です。

4. width: 100vw; height: 100vh;

  • width: 100vw; は、要素の幅をビューポートの横幅全体(100%)に設定します。vw はビューポート幅の単位で、画面全体の幅に対しての割合を表します。同様に、height: 100vh; は、要素の高さをビューポートの高さ全体に設定します。これにより、.Overlay画面全体を覆うサイズになります。

5. background-color: rgba(0, 0, 0, 0.2);

  • background-color で要素の背景色を指定しています。rgba(0, 0, 0, 0.2); の意味は、黒 (rgb(0, 0, 0)) に 20% の透明度 (0.2) を加えたものです。この設定により、黒い半透明の背景が表示されます。これは通常、モーダルウィンドウの背後に表示され、ユーザーがモーダル以外の部分にアクセスしにくくし、モーダル自体を目立たせるために使われます。

まとめ

.Overlay は、モーダルウィンドウやポップアップを表示する際に、背後に半透明の暗い背景を表示し、ユーザーの注意をモーダルに集中させるための要素です。この背景は、画面全体を覆い、他の操作を制限する役割を果たします。

4o

ドロップダウンメニュー

参考サイト

スクロールアニメーション

const sections = document.querySelectorAll(".Section")

      window.addEventListener("scroll", () => {
        animationByScroll()
      })

      function animationByScroll() {
        const scrollY = window.scrollY
        const windowHeight = window.innerHeight
        const INVIEW_HEIGHT = 200

        sections.forEach((section) => {
          const offsetTop = section.offsetTop

          if (scrollY + windowHeight > offsetTop + INVIEW_HEIGHT) {
            section.classList.add("SectionIsActive")
          }
        })
      }

このコードは、スクロールに応じて特定のセクションにアニメーションを追加する機能を実装しています。スクロールの位置に応じて、画面に現れたセクションにクラスを追加し、そのクラスに基づいてCSSアニメーションを行うことができます。各部分の意味を詳しく解説します。

画像引用:https://zenn.dev/hideki_climax/books/0e124eb17a67b3/viewer/20c56b

1. const sections = document.querySelectorAll(".Section")

  • これは、HTML内の class="Section" を持つすべての要素を取得し、sections という変数に保存しています。つまり、複数のセクション要素をまとめて取得しています。

2. window.addEventListener("scroll", () => { animationByScroll() })

  • このコードは、ユーザーがページをスクロールしたときに発生する「スクロールイベント」を監視しています。スクロールするたびに、animationByScroll() 関数が実行されます。

3. function animationByScroll()

  • これは、スクロール時に実行される関数です。この関数の中で、スクロールの位置やセクションの位置を確認し、条件を満たしたセクションに SectionIsActive クラスを追加します。

4. const scrollY = window.scrollY

  • ページのスクロール量(Y軸の位置)を取得しています。ページをどれだけ縦方向にスクロールしたかをピクセル単位で表します。

5. const windowHeight = window.innerHeight

  • これは、ブラウザの表示領域の高さ(ビューポートの高さ)を取得しています。これにより、現在の画面の高さがわかります。

6. const INVIEW_HEIGHT = 200

  • これは、セクションが画面内に表示されていると判断するためのしきい値です。セクションが表示領域に入るタイミングを調整するため、表示領域より200ピクセル少ない位置を基準にしています。

7. sections.forEach((section) => { ... })

  • ページ内のすべてのセクションに対して、それぞれのセクションが画面に表示されているかどうかをチェックしています。

8. const offsetTop = section.offsetTop

  • セクションの上端が、ページ全体のどの位置にあるかを取得しています。セクションがページの上部からどれだけ離れているかをピクセル単位で表します。

9. if (scrollY + windowHeight > offsetTop + INVIEW_HEIGHT)

  • この条件文は、セクションが画面に表示されたかどうかを判断しています。具体的には、ユーザーがページをスクロールして、画面の下端がセクションの上端よりも200ピクセル以上下に来た場合に、セクションが表示されていると判断します。

10. section.classList.add("SectionIsActive")

  • 条件を満たしたセクションに「SectionIsActive」というクラスを追加します。このクラスは、後でCSSで定義されたアニメーションやスタイルを適用するために使用されます。

height: calc(100vh - 60px); の意味は、要素の高さを画面の高さ(ビューポートの高さ)から60ピクセル引いた値に設定するということです。

具体的な意味

  • 100vh は、ビューポート(表示領域)の高さを100%表します。つまり、画面の縦方向の全体の高さです。
  • 60px は、固定の60ピクセルを表します。
  • calc() は、CSSで使える関数で、異なる単位(例えば、vhpx)を組み合わせて計算するためのものです。

この式は、「画面の高さ100%から60ピクセル分を引いた値」を計算して、それを要素の高さとして設定しています。

使用例

例えば、ヘッダーやナビゲーションバーが60pxの高さを持っていて、その下のコンテンツ部分を画面の残りの高さに収めたい場合、このように計算して設定します。これにより、要素はヘッダーの高さを除いた画面の残りのスペース全体を使って表示されます。

.Main クラスのCSSは、要素のレイアウトや見た目を設定するものです。それぞれのプロパティの意味は以下の通りです。

1. width: 100%;

  • 幅を100%に設定しています。これは、親要素の幅に対して100%の大きさ、つまり親要素いっぱいに広がるという意味です。

2. padding-top: 12px;

  • 上側に12ピクセルの内側余白(パディング)を追加します。要素内の内容が、要素の上端から12ピクセル離れて配置されます。

3. padding-left: 32px; padding-right: 32px; padding-bottom: 32px;

  • 左、右、下側にもそれぞれ32ピクセルのパディングを追加します。これにより、要素内の内容がそれぞれの端から32ピクセル離れて表示されます。これは、テキストやコンテンツが要素の端にぴったりくっつかないようにするために使用します。

4. background-color: #eee;

  • 背景色を薄い灰色(#eee)に設定しています。これは全体のデザインや視認性を向上させるために使用されることが多いです。

スクロールアニメーション(IntersectionObserver利用)

  const observer = new IntersectionObserver(
      (entries) => {
      entries.forEach((entry) => {
       if (entry.isIntersecting) {
        entry.target.classList.add("SectionIsActive")
        }
      })
     },
     { threshold: 0.2 }
    )

    const sections = document.querySelectorAll(".Section")
    sections.forEach((section) => {
      observer.observe(section)
    })

このコードは、Intersection Observer API を使って、ページ上の .Section クラスを持つ要素が画面に入った時に、特定のクラスを追加する仕組みを作っています。つまり、ユーザーがスクロールしてセクションが見えるようになったら、そのセクションに「SectionIsActive」というクラスが追加され、CSSアニメーションなどが発動するという流れです。


1. const observer = new IntersectionObserver(...)

  • これは、Intersection Observer というAPIを使って、新しいオブザーバー(観察者)を作成しているところです。
  • 「特定の要素が画面に入ったかどうか」を監視する機能を提供しています。

2. (entries) => { entries.forEach((entry) => { ... }) }

  • entries は、観察対象のセクションの情報(エントリー)を持つリストです。このリストを1つずつチェックしています。
  • entry はそれぞれのセクションの状態を表しています。

3. if (entry.isIntersecting) { ... }

  • entry.isIntersecting は、セクションが「画面に入っているかどうか」を示す値です。
  • true ならそのセクションは表示領域に入っており、false ならまだ画面外にあるという意味です。

4. entry.target.classList.add("SectionIsActive")

  • 画面に入ったセクション(entry.target)に対して、「SectionIsActive」というクラスを追加します。
  • このクラスはCSSでアニメーションを定義しているかもしれません。このクラスが追加されることで、セクションがアニメーションするようになります。

5. { threshold: 0.2 }

  • しきい値(threshold)が0.2 と指定されています。これは、セクションの20%が画面に入った時点で「表示された」と判断するという意味です。
  • 例えば、セクション全体の20%が表示領域に入った時にクラスが追加されます。

6. const sections = document.querySelectorAll(".Section")

  • ページ内のすべての .Section クラスを持つ要素を取得し、sections という変数にまとめています。これで複数のセクションを一気に対象にできるようになります。

7. sections.forEach((section) => { observer.observe(section) })

  • すべてのセクションに対して、observer.observe() を使ってオブザーバーを設定しています。これにより、セクションが画面に入るかどうかを常に監視するようになります。

スムーススクロール

<body>
  <script src="https://cdn.jsdelivr.net/gh/cferdinandi/smooth-scroll@15/dist/smooth-scroll.polyfills.min.js"></script>
  <script>
    const scroll = new SmoothScroll('a[href*="#"]')
     header: "[data-scroll-header]"
  </script>
</body>

このコードは、Smooth Scroll というライブラリを使って、ページ内のリンクをスムーズにスクロールさせる機能を追加しています。それぞれの部分の意味を詳しく説明します。

1. <script src="https://cdn.jsdelivr.net/gh/cferdinandi/smooth-scroll@15/dist/smooth-scroll.polyfills.min.js"></script>

  • Smooth Scrollライブラリを読み込んでいます。このスクリプトタグによって、指定されたURLからライブラリを取得し、ページで使用できるようにします。
  • このライブラリを使うと、ページ内のリンク(アンカーリンク)をクリックしたときに、ページがスムーズにスクロールします。

2. <script> ブロック内のコード

const scroll = new SmoothScroll('a[href*="#"]')
  • 新しい SmoothScroll インスタンスを作成しています
  • 引数 'a[href*="#"]' は、ページ内のすべてのリンク(<a>タグ)で、href 属性に # を含むものを対象にしています。これは、同じページ内の特定の位置に移動するためのリンクです。

3. header: "[data-scroll-header]"

  • ここは誤って書かれている部分です。正しくは、オプションを指定する場合は new SmoothScroll('a[href*="#"]', { header: "[data-scroll-header]" }) のようにカッコ内にオプションを含める必要があります。
  • header: "[data-scroll-header]" は、スムーズスクロールを行うときに、特定のヘッダー要素の高さを考慮してスクロール位置を調整するための設定です。
  • この設定により、指定したヘッダー(data-scroll-header 属性を持つ要素)の高さを考慮し、リンクをクリックしたときにヘッダーの下に正確にスクロールすることができます。

アコーディオンメニュー

スクリプトの説明

const labels = document.querySelectorAll(".Menu-Item-Label") 

これは、document.querySelectorAll(".Menu-Item-Label") を使って、すべての .Menu-Item-Label クラスを持つ要素を取得し、labels という変数にリストとして保存しています。メニューの各項目を表しています。

labels.forEach((label) => {
  label.addEventListener("click", function (event) {
    const targetContent = event.currentTarget.nextElementSibling
    targetContent.classList.toggle("Menu-ItemIsOpen")
  })
})
  • labels.forEach() により、取得したラベルそれぞれに対してループを回します。
  • 各ラベルに対して、click イベントリスナーを設定します。これにより、ラベルがクリックされたときに何らかのアクションが実行されます。
  • event.currentTarget.nextElementSibling は、クリックされたラベルの次にある要素、つまりラベルに関連するコンテンツを取得します。これは、次の要素がメニューの内容(例えばサブメニューや詳細情報)であることを前提としています。
  • classList.toggle("Menu-ItemIsOpen") は、そのコンテンツに .Menu-ItemIsOpen クラスを追加または削除します。すでにクラスがあれば削除し、なければ追加します。これによって、メニューが開閉する効果が生まれます。

CSSの説明

.Menu-ItemIsOpen {
  height: auto;
}
  • .Menu-ItemIsOpen は、クリックによってメニューのアイテムが開いた時に適用されるクラスです。
  • height: auto; は、要素の高さを 自動に設定します。つまり、要素内のコンテンツに合わせて高さが決まり、コンテンツがすべて表示されるようになります。
    • メニューが閉じているときは高さが 0 だったり隠れていたりしますが、height: auto; を適用すると、コンテンツが完全に表示されるようになります。

全体の動き

  1. ユーザーがメニュー項目(ラベル)をクリックします。
  2. スクリプトがクリックされたラベルの次にあるコンテンツ(nextElementSibling)を取得し、そのコンテンツに .Menu-ItemIsOpen クラスを適用または解除します。
  3. .Menu-ItemIsOpen クラスによって、そのコンテンツの高さが auto になり、内容が表示されます。再度クリックするとクラスが外れ、コンテンツは再び隠れます(通常は height: 0 のようにして隠します)。
      const labels = document.querySelectorAll(".Menu-Item-Label")

      labels.forEach((label) => {
        label.addEventListener("click", function (event) {
          const label = event.currentTarget
          if (label.dataset.isOpen === "false") {
            const itemInner = label.nextElementSibling
            const content = itemInner.children[0]
            const targetHeight = content.offsetHeight
            itemInner.style.height = targetHeight + "px"

            setTimeout(function () {
              itemInner.style.height = "auto"
              label.dataset.isOpen = true
            }, 500)
          }

          if (label.dataset.isOpen === "true") {
            const itemInner = label.nextElementSibling
            const content = itemInner.children[0]
            const targetHeight = content.offsetHeight
            itemInner.style.height = targetHeight + "px"

            setTimeout(function () {
              itemInner.style.height = 0
              label.dataset.isOpen = false
            }, 1)
          }
        })
      })

このコードは、クリックしたメニュー項目の開閉アニメーションを実現するためのものです。具体的には、メニューをクリックすると、そのコンテンツの高さが自動で伸びたり縮んだりする動きをします。

  • メニュー項目 (.Menu-Item-Label) をクリックすると、その次にあるコンテンツが表示されたり、非表示になったりするアニメーションを作る。
  • 開くときはコンテンツの高さを auto にして、閉じるときは高さを 0 にすることで、アニメーション効果が出ます。

1. ラベル(メニュー項目)をすべて取得する

const labels = document.querySelectorAll(".Menu-Item-Label")

.Menu-Item-Label というクラスを持つすべての要素を取得します。これが「メニュー項目」のリストになります。

2. 各ラベルにクリックイベントを追加

labels.forEach((label) => {
  label.addEventListener("click", function (event) {

取得したすべてのラベルに対して、クリックされたときに実行される関数を設定しています。この関数が実行されるたびに、メニューを開いたり閉じたりします。

3. ラベルが閉じている場合 (isOpen === "false")

if (label.dataset.isOpen === "false") {
  • label.dataset.isOpen は、ラベルが今開いているか閉じているかを判断するためのものです。
  • “false” の場合は閉じているので、これから開くための動作を行います。

4. 閉じているラベルの次の要素(コンテンツ)を取得し、高さを設定

const itemInner = label.nextElementSibling
const content = itemInner.children[0]
const targetHeight = content.offsetHeight
itemInner.style.height = targetHeight + "px"
  • label.nextElementSiblingクリックしたラベルの次の要素(つまり、表示するコンテンツ)を取得します。
  • content.offsetHeight は、そのコンテンツの本来の高さを取得します(ピクセル単位)。
  • itemInner.style.height = targetHeight + "px" によって、その高さに基づいて要素の高さを動的に設定します。これで、アニメーション的にコンテンツが広がります。

5. コンテンツが開き終わった後に高さを auto に設定

setTimeout(function () {
  itemInner.style.height = "auto"
  label.dataset.isOpen = true
}, 500)
  • コンテンツが広がるまで 500ms 待ちます(アニメーションの時間)。
  • 広がった後に、高さを auto に設定します。auto にすることで、コンテンツが開いた後、サイズが変わっても適切な高さで表示されます。
  • 最後に、isOpen"true" にして、「このメニューは今開いていますよ」と記録します。

6. ラベルが開いている場合 (isOpen === "true")

if (label.dataset.isOpen === "true") {

isOpen === "true" の場合は、ラベルが今開いているので、次に閉じるための動作を行います。

7. 開いているラベルの高さを元に戻す

const itemInner = label.nextElementSibling
const content = itemInner.children[0]
const targetHeight = content.offsetHeight
itemInner.style.height = targetHeight + "px"

開いているコンテンツの高さを取得し、その高さを一時的に適用します。これは、閉じるときのスムーズなアニメーションのためです。

8. コンテンツを閉じるアニメーション

setTimeout(function () {
  itemInner.style.height = 0
  label.dataset.isOpen = false
}, 1)
  • 1ms 後に、コンテンツの高さを 0 にして、閉じるアニメーションを開始します。
  • これにより、メニュー項目が閉じると、内容がすべて隠れてしまいます。
  • 最後に、isOpen"false" に変更して、「このメニューは今閉じていますよ」と記録します。

サイトのナビゲーションとは?

サイトのナビゲーションとは、ウェブサイトの中で、訪問者が目的のページや情報にスムーズにたどり着けるように手助けする案内システムです。リンクやボタンを使って、ページ間を移動する道しるべのような役割を果たします。

ナビゲーションの例:

  • 上のメニューや横のメニューにある「ホーム」「ブログ」「お問い合わせ」などのリンク。
  • 記事の終わりにある「次へ」や「前へ」といったリンク。

グローバルナビゲーションとの違い

グローバルナビゲーションとは、サイト全体で共通して表示されるナビゲーションメニューです。サイト内のどのページにいても同じメニューが表示されるので、サイトのどこからでも主要なページに簡単にアクセスできます。

グローバルナビゲーションの特徴:

  • 全ページ共通: サイトのどのページを開いても同じメニューが表示される。
  • 主なページにアクセス: ホーム、サービス、会社情報、ブログ、コンタクトなど、サイトの重要なページがリンクされている。
  • 通常ヘッダーに表示: グローバルナビゲーションは、ページの上部(ヘッダー)に配置されていることが多い。

グローバルナビゲーションの例:

サイトの上部に表示されている「ホーム」「サービス」「お問い合わせ」などのリンクを含むメニュー。どのページにいても、このメニューを使って他のページにすぐ移動できる。

違いを簡単に説明すると:

グローバルナビゲーション: サイト全体に共通して表示され、常に同じメニューがある主要なリンクの集まり

サイトのナビゲーション: ページの移動を助ける案内システム全般。

addEventListener

addEventListener は、ある要素に「イベント」が発生したときに特定の動作をさせるための命令です。想像してみてください。ボタンをクリックすると、アラートが表示されるようにしたい場合です。

// ボタン要素を取得します。
const button = document.querySelector('button');

// ボタンがクリックされたときに動作させたい内容を定義します。
button.addEventListener('click', function() {
  alert('ボタンがクリックされました!');
});

addEventListener「リスナー(耳)」のようなものです。ボタンがクリックされる「音」を聞いて、クリックされたときに設定された動作(ここではアラートの表示)を行います。

removeEventListener

一方、removeEventListener は、「リスナー」を解除する命令です。つまり、イベントが発生しても反応しないようにすることができます。

// 同じボタン要素を取得します。
const button = document.querySelector('button');

// まずはリスナーを定義して追加します。
function showAlert() {
  alert('ボタンがクリックされました!');
}

button.addEventListener('click', showAlert);

// あとでリスナーを削除します。
button.removeEventListener('click', showAlert);

このコードでは、showAlert という関数を addEventListener に渡して、ボタンがクリックされたときにアラートを表示するようにしています。しかし、その後で同じ showAlert 関数を使ってremoveEventListener を呼び出しているので、ボタンをクリックしてももう何も起こりません。

ポイント

  1. addEventListener:リスナーを追加して、イベントが起こったときに特定の処理を行うようにする。
  2. removeEventListener:リスナーを解除して、イベントが起こっても何も反応しないようにする。

this

thisは、関数の中で使われる特別なキーワード、「その関数がどのオブジェクトから呼び出されたか」を指し示します。つまり、関数が「誰の中で」動いているかを教えてくれるものです。

thisが何を指すかは状況による

thisが何を指すかは、次の4つのケースで決まります。

(1) グローバル環境でのthis

もし関数が何のオブジェクトにも所属していない状態(グローバルスコープ)で呼ばれた場合、thiswindowオブジェクト(ブラウザの場合)またはglobalオブジェクト(Node.jsの場合)を指します。

(2) メソッドとしてのthis

オブジェクトのメソッド(オブジェクト内の関数)として呼ばれた場合、thisはそのオブジェクトを指します。

const student = {
  name: 'Yudai',
  greet: function() {
    console.log(this.name); // 'Yudai'
  }
};

student.greet(); // thisはstudentを指す

(3) コンストラクタ関数内のthis

新しいオブジェクトを作るための関数(コンストラクタ関数)で使うと、thisは新しく作られるオブジェクトを指します。

function Student(name) {
  this.name = name;
}

const yudai = new Student('Yudai');
console.log(yudai.name); // 'Yudai'

なぜthisがあるのか?

thisを使うことで、同じ関数でも色んなオブジェクトで使い回せる柔軟なプログラムが書けます。例えば、複数のキャラクターがいるゲームを作るときに、同じattack関数でもthisを使ってそれぞれのキャラクターの攻撃力を反映できる、といった具合です。

まとめ

  • this「どのオブジェクトが関数を呼び出したか」を指す。
  • 状況によってthisが何を指すかが変わる。
  • グローバル、メソッド、コンストラクタ、明示的な設定の4つのケースで使われる。