メニュー

モーダルをCSSだけで実装してみて思った事


こんにちは佐野です。

先日の話ですが、とあるWEBサイトのモーダルの挙動に違和感を覚える事がありました。(※モーダルとはポップアップ表示されるコンテンツの事です。)
そのモーダルは「開く度にページトップに戻り」、「閉じると元の位置に戻る」と言った挙動をしていて、WEBに従事しているからか気になる挙動でした。

実装方法を詳しく見る様な事はしていないのですが、挙動的に恐らくJavaScriptで自作されたものかと思います。
その時、唐突にCSSだけでモーダルって作れるのかなって気になったんですよね。

と言う事で今回は実際にCSSだけでモーダルを作ってみたのでその方法と、作ってみて思った事を書きたいと思います。

今回は実用的な内容ではなく勉強の一環なので、CSS勉強中な人向けの内容です。

実装して思った事

作ってみて思う事は、モーダルを作るならJavaScriptは使った方がいいと言う事です。

要件次第ではCSSのみの実装でも大丈夫かもしれませんが、自身で運用するサイトでもない限りは柔軟に対応出る様にJavaScriptは使った方がいいです。

ただ、JavaScriptで実装しているものをCSSだけで再現できるのか、と言う興味はスキルアップの意味でも大切な事だと感じました。

今回はCSS3で追加された疑似クラスを使っていますが、今まで知らなかった事が多く、CSSの利便性を知るいいきっかけになりました。
なので、興味がある方は最後まで見てもらえたらと思います。

実装サンプルとコード

今回実装したものがこちらです。

See the Pen
oNNrbae
by otwo (@otwo)
on CodePen.

コード

次にコピペ用のコードを載せておきます。
モーダルのサイズなど若干違いはありますが、ほぼサンプルと同じものです。
挙動で気になる点はあるかもしれませんが色々変更しながら遊んでみてください。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
*{
  padding: 0;
  margin: 0;
}
.modal-open{
  display: inline-block;
  background-color: #666;
  color: #fff;
  margin: 10px;
}
.modal-open a{
  display: inline-block;
  padding: 5px;
  text-decoration: none;
  color: #fff;
}
/*** 以下モーダル用CSS ***/
.modal{
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  left: 0;
}
.modal:not(:target) {
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.5s, visibility 0.5s;
}
.modal:target{
  opacity: 1;
  visibility: visible;
  transition: opacity 0.5s, visibility 0.5s;
}
.modal .overlay{
  display: block;
  width: 100%;
  height: 100%;
  position: absolute;
  background-color: #000;
  opacity: 0.7;
  top: 0;
  left: 0;
}
.modal-wrapper{
  width: 100%;
  max-width: 650px;
  min-width: 300px;
  height: 100%;
  max-height: 550px;
  background-color: #fff;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.modal-contents{
  overflow: auto;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  position: relative;
}
.modal-content{
  margin: 25px;
}
.modal-close{
  position: absolute;
  top: 5px;
  right: 10px;
  text-decoration: none;
}
</style>
</head>
<body>
  <div class="modal-open"><a href="#modal">モーダルを開く</a></div>
  <div class="modal" id="modal">
    <a href="#!" class="overlay"></a>
    <div class="modal-wrapper">
      <div class="modal-contents">
        <a href="#!" class="modal-close">✕</a>
        <div class="modal-content">
          ここにテキストや画像を設置します。<br><br>
          テキストも見切れません。テキストも見切れません。テキストも見切れません。テキストも見切れません。テキストも見切れません。テキストも見切れません。テキストも見切れません。<br><br><br><br>
          内容に応じでスクロールも出ます。<br><br><br><br><br>
          内容に応じでスクロールも出ます。<br><br><br><br><br>
          内容に応じでスクロールも出ます。<br>
          終わり。
        </div>
      </div>
    </div>
  </div>
</body>
</html>

表示・非表示の切り替え方

続いて今回一番悩んだ、モーダルの表示と非表示の切り替えです。
チェックボックスを使った実装もありますが、今回は:target疑似クラスを使った実装を試しました。

:target 疑似クラス

この:targetがcss3で追加された疑似クラスです。
挙動については下記のサイトがわかりやすく書いているので確認してみてください。
:target – CSS: カスケーディングスタイルシート | MDN

簡単に説明すると、ページ内リンクをクリックするとURLの後ろにジャンプ先要素のIDが付きます。
「https://●●●.com/index.html#ID名」の様な感じです。
:targetはURLにIDが付いた形式の時だけ有効になるCSSが記述できる疑似クラスになります。
※サンプルはCodePenで表示しているので、この記事でURLの変化は確認できません。

と言う事でサンプルでの使い方の説明です。

.modal:not(:target) {
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.5s, visibility 0.5s;
}
.modal:target{
  opacity: 1;
  visibility: visible;
  transition: opacity 0.5s, visibility 0.5s;
}

.modal:not(:target)がモーダルが出ていない(URLにID名が入っていない)状態のスタイルです。
サンプルではモーダルを見えない様に隠しており、:targetの有効時(サンプルはURLに”#modal”がついている時)に0.5秒かけて表示に切り替えています。

モーダルを消す場合は:targetを存在しないIDに変更します。
サンプルではoverlayクラスのaタグhrefに”#!”の指定をしていますが、ページ内に存在しないIDなら何でも指定して大丈夫です。

実用が難しいと感じた点

ここまでに実用的ではないと感じたです。

・モーダルの表示切替でURLにIDが常に表示される。
・モーダルを表示した状態でページを更新するとモーダルが表示した状態から始まる。
・モーダル表示時に背景(メインコンテンツ)を固定できない。

サンプル作成の時点で3つほど感じました。
もっと細かい想定をすればもっと出てくるかもしれません。

背景の固定など、JavaScriptを使えば実装できるものがある以上、JavaScriptを使わない理由は今のところ見当たらないかと思います。

最後に

実務で使えるものとはなりませんでしたが、CSSの面白さを知る良いきっかけとなりました。
これを機会にCSSとJavaScriptで実装できるアニメーションの違いを考えてみてもいいかもしれませんね!

それではまた!

この記事をシェアする

  • twitter
  • facebook
  • Google+
  • B!はてブ
  • pocket
トップへ戻る

CONTACT

ゲーム開発、Webサイト制作に関するご相談等ございましたら、お気軽にお問い合わせください。

ゲーム開発に関する
お問い合わせはこちら

Webサイト制作に関する
お問い合わせはこちら