モーダル

Featherlightのモーダル

HTML

    
<!-- Featherlight CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/featherlight@1.7.14/release/featherlight.min.css">

<!-- Featherlight JS -->
<script src="https://cdn.jsdelivr.net/npm/featherlight@1.7.14/release/featherlight.min.js"></script>


<div class="modalBox">
  <!-- 開くボタン -->
  <div class="modalOpen modalOpen-featherlight">
    <a href="javascript:void(0)" class="featherlight__link" data-featherlight="#featherlight__open">テスト03</a>
  </div>

  <!-- モーダル中身 -->
  <div id="featherlight__open" class="featherlight__open">
    <div class="featherlight__contents">
      <span class="test-number">テスト03</span>
    </div>
  </div>
</div>
    

CSS

コードの説明

    
/*******************************************
featherlight.js
*******************************************/
/* ↓↓↓リセット用↓↓↓ */
.featherlight .featherlight-content {
    width: 90%;
    height: 90%;
    max-height: none;
    margin: 0;
    padding: 0;
}

/* ↑↑↑リセット用↑↑↑ */


.modalOpen-featherlight {
    background-color: var(--red);
    border: 3px solid var(--red);
    padding: 0;

    &:hover {
        color: var(--red);
    }
}

.featherlight__link {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 100%;
    padding: 15%;
}

.featherlight__open {
    display: none;
}

#featherlight__open {
    background-color: rgba(0, 0, 0, 0.5);
}
    

JavaScript

コードの説明

    
  /*******************************************
モーダル内に閉じるボタン追加
*******************************************/

$(document).on('click', '.modalClose', function (e) {
  e.preventDefault();
  if ($.featherlight.current()) {
    $.featherlight.current().close();
  }
});
    

javascriptのみのモーダル

シンプルなモーダルには適しているが、複雑な機能が求められる場合はライブラリを使用した方が効率的なこともある。

【メリット】
軽量で速い、柔軟なカスタマイズ、依存性がない

【デメメリット】
コードが長くなる、古いブラウザなどで互換性問題が発生することがある、

HTML

    

<button class="btn modalOpen" data-target="modal01">
  1日の流れを見る
</button>

<!-- モーダル -->
<div class="modal modal-interview">
  <div class="section__inner modalBox-outer" id="modal-interview02">
    <div class="modalBox">
      <div class="modal__inner">
        <button class="modalClose modalClose-top"></button>
        <div class="modalMv ">
          <div class="modalMv__txtBox">
            <div class="modalMv__ttl">
              <p></p>
              <p></p>
            </div>
            <div class="modalMv__detail">
              <p></p>
            </div>
          </div><!-- modalMv__txtBox -->

          <div class="modalMv__img">
            <img src="img/interview/img02.jpg" width="950" height="1000" alt="">
          </div>
        </div><!-- modalMv -->

        <dl class="modal__q">
          <dt>
            <span class="q-icon"></span>
            <p>

            </p>
          </dt>
          <dd>
            <p>

            </p>
          </dd>
        </dl>

        <div class="btn-outer modalClose btn-outer-modal">
          <button class="btn">
            閉じる
          </button>
        </div>
      </div><!-- modal__inner -->
    </div><!-- modalBox-->
  </div><!-- modalBox-outer -->
</div><!-- modal -->


<!--↑↑↑ モーダル↑↑↑-->

    

CSS

コードの説明

    
/*******************************************
modal
*******************************************/
/* 共通
ーーーーーーーーーーーーーーーーーーー */
.no-scroll {
    overflow: hidden;

    body {
        overflow: scroll;
    }
}

.modal {
    /* 背景 */
    opacity: 0;
    visibility: hidden;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100vw;
    height: auto;
    background-color: var(--blue06);
    z-index: -100;
    overflow: auto;
    transition: var(--transitionBase);
}

.modalBox-outer {
    /* 最大幅*/
    position: absolute;
    width: min(100vw, 1000px);
    height: auto;
    top: 0;
    left: 50%;
    opacity: 0;
    visibility: hidden;
    transform: translate(-50%, 0);
    transition: var(--transitionBase);
    padding: clamp(40px, 10%, 140px) 0;
    z-index: -100;
}

.modalBox {
    position: relative;
    width: 100%;
    margin: 0 auto;
    background-color: var(--beige01);
    height: auto;
}

.active {
    opacity: 1;
    visibility: visible;
    z-index: 1000;

    .show.modalBox-outer {
        opacity: 1;
        visibility: visible;
        transform: translate(-50%, 0);
        z-index: 1001;
    }
}

.modal__inner {
    /* モーダル中身のインナー */
    width: min(100%, 915px);
    margin: 0 auto;
    padding: 65px 0;
}

.modalClose-top {
    position: absolute;
    content: "";
    width: 60px;
    aspect-ratio: 1;
    background-color: var(--blue01);
    border: 1px solid var(--blue01);
    top: 0;
    right: 0;
    border-radius: var(--borderRadiusCircle);
    transform: translate(50%, -50%);
    z-index: 10;
    transition: var(--transitionBase);

    &::before,
    &::after {
        position: absolute;
        content: "";
        width: 50%;
        height: 2px;
        top: 50%;
        left: 50%;
        background-color: var(--white);
        transition: var(--transitionBase);
    }

    &::before {
        transform: translate(-50%, -50%) rotate(45deg);
    }

    &::after {
        transform: translate(-50%, -50%) rotate(-45deg);
    }

    &:hover {
        background-color: var(--white);

        &::before,
        &::after {
            background-color: var(--black);
        }

    }
}

.btn-outer-modal {
    width: min(100%, 400px);
    margin: max(6.5%, 40px) auto 0;
}



@media screen and (max-width:1024px) {
    .modal__inner {
        padding: 80px 15px;
    }

    .modalClose-top {
        top: 10px;
        right: 10px;
        transform: none;
    }
}

@media screen and (max-width:960px) {
    .modal__inner {
        padding-left: 15px !important;
        padding-right: 15px !important;
    }
}


@media screen and (max-width:768px) {


    .modalClose-top {
        width: 40px;

        &:hover {
            background-color: var(--blue01);

            &::before,
            &::after {
                background-color: var(--white);
            }

        }
    }

}









/* 共通
ーーーーーーーーーーーーーーーーーーー */
.modalMv {
    position: relative;
    margin: 0 auto max(8.81%, 35px);
}

.modalMv__txtBox {
    position: absolute;
    width: 100%;
    top: 9%;
    left: 0;
}

.modalMv__ttl {

    p {
        background-color: var(--blue04);
        color: var(--white);
        font-size: var(--font30);
        border-radius: var(--borderRadius10);
        width: fit-content;
        margin-bottom: 0.34em;
        line-height: 1.7;
        padding: 0 0.5em;

        &:last-child {
            margin-bottom: 0;
        }
    }
}

.modalMv__img {
    width: 64.44%;
    margin-left: auto;

    img {
        border-radius: var(--borderRadius10);
    }
}

.modalMv__detail {
    margin-top: 35px;

    p {
        font-size: var(--font19);
        line-height: 1.47;
    }
}

.modal__q {
    font-size: var(--font23);

    dt {
        display: flex;
        align-items: flex-start;
        justify-content: flex-start;
        gap: 10px;
        margin-bottom: 10px;

        p {
            flex: 1;
            font-size: var(--font23);
            line-height: 1.217;
        }
    }

    dd {
        margin-bottom: max(6.396%, 30px);
        background-color: var(--white);
        padding: 20px;
        border-radius: var(--borderRadius10);

        &:last-child {
            margin-bottom: 0;
        }
    }
}

.q-icon {
    position: relative;
    display: block;
    width: 1.74em;
    aspect-ratio: 1;
    transform: translateY(-15%);
    background-color: var(--blue04);
    border-radius: var(--borderRadiusCircle);

    &::before {
        position: absolute;
        content: "Q";
        font-size: 1em;
        color: var(--white);
        top: 50%;
        left: 50%;
        transform: translate(-50%, -60%);
        font-family: var(--notoSan);
    }
}

@media screen and (max-width: 768px) {
    .modalMv {
        display: flex;
        flex-direction: column-reverse;
        align-items: center;
        width: min(100%, 600px);
        margin-left: auto;
        margin-right: auto;
    }

    .modalMv__txtBox {
        position: initial;
    }

    .modalMv__img {
        width: min(100%, 400px);
        margin: 0 0 max(5%, 15px) 0;

        img {
            border-radius: var(--borderRadius10);
        }
    }

    .modalMv__detail {
        margin-top: max(3%, 10px);
    }

    .modal__q {
        dd {
            padding: 15px 10px;
        }
    }
}




/* 共通↑↑↑
ーーーーーーーーーーーーーーーーーーー */




    

JavaScript

コードの説明

    
/*******************************************
モーダル data-target="modal01"
*******************************************/
// モーダル開く
document.querySelectorAll('.modalOpen').forEach(btn => {
  btn.addEventListener('click', () => {
    const targetId = btn.dataset.target;
    const modal = document.getElementById(targetId)?.closest('.modal');
    const targetBox = document.getElementById(targetId);

    if (!modal || !targetBox) return;

    // 同じモーダル内の他の Box を非表示にする
    modal.querySelectorAll('.modalBox-outer').forEach(box => {
      box.style.display = 'none';
      box.classList.remove('show');
    });

    // 対象だけ表示
    targetBox.style.display = 'block';
    targetBox.classList.add('show');

    modal.classList.add('active');
    document.documentElement.classList.add('no-scroll');
  });
});

// モーダル閉じる
document.querySelectorAll('.modalClose').forEach(btn => {
  btn.addEventListener('click', () => {
    const modal = btn.closest('.modal');
    if (!modal) return;

    modal.classList.remove('active');

    // そのモーダル内の Box を全部閉じる
    modal.querySelectorAll('.modalBox-outer').forEach(box => {
      box.classList.remove('show');
      box.style.display = 'none';
    });

    // 他に開いてるモーダルがなければスクロール許可
    if (!document.querySelector('.modal.active')) {
      document.documentElement.classList.remove('no-scroll');
    }
  });
});


    

SweetAlert2のモーダル

HTML

    
                  <div class="modalOpen modalOpen-swal" id="swalModal__open">
                  テスト02
                </div>
    

JavaScript

コードの説明

    
                  // SweetAlert2のモーダルを開くためのボタン
                  const swalModalOpen = document.getElementById('swalModal__open');
                
                  // ボタンにクリックイベントを設定
                  swalModalOpen.addEventListener('click', function () {
                    Swal.fire({
                      title: 'テストモーダル',
                      text: 'SweetAlert2を使用したモーダルです。',
                      icon: 'info',
                      confirmButtonText: '閉じる'
                    });
                  });