Webデザインやガジェット、格安SIMの情報ブログ

CSSと少しのJSで作るページスクロールできるモーダルウィンドウ

某案件で対応したモーダルウィンドウ実装が中々曲者だったので、同じような実装を強いられた時に使いまわせるように自分用のメモとして残しておきます。

  • レスポンシブ対応
  • モーダルウィンドウ内でスクロール出来る
  • 複数設置対応
  • 基本動作はCSS3で対応(古いIE非対応)
  • スクロールバーの関係で少しJS使う

※本ページは広告・アフィリエイトプログラムにより収益を得ています。

スポンサーリンク

デモ・ダウンロード

何はともあれ、まずはサンプルをご確認下さい。CodePenやサンプルページからもコードを確認可能です。

See the Pen scroll modal window by tokumewi (@tokumewi) on CodePen.

全ソースコード

全ソースコードを載せた後に個別で解説していきます。テキストはスクロール対応を見せるためなのでなんでも良いです。

HTML


<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>scroll modal window</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>

<input type="checkbox" id="modal01" class="modalCheck">
<input type="checkbox" id="modal02" class="modalCheck">
<div class="wrapper">
    <div class="mainVisual main01 flex center">
            <div class="btn"><label for="modal01">Modal Open</label></div>
    <!-- /.mainVisual --></div>
    <div class="content">
            <h1 class="ttl">宮沢賢治「ポラーノの広場」</h1>
            <p>あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。</p>
            <p>あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。</p>
            <p>あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。</p>
            <div class="btn small"><label for="modal01">Modal Open</label></div>
    <!-- /.content --></div>
    <div id="modal01Con" class="modalWrap">
        <div class="modalBg"><label for="modal01" class="closeModal"></label></div>
        <div class="modalCon">
            <div class="modalInner">
                <div class="modalCloseBtn"><label for="modal01" class="closeModal">×</label></div>
                <h1 class="ttl modalTtl">宮沢賢治「ポラーノの広場」</h1>
                <div class="modalText">
                    <div class="modalCover"><img src="https://unsplash.it/1024/768?image=1003" alt=""></div>
                    <p>あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。</p>
                    <p>あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。</p>
                    <p>あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。</p>
                    <div class="btn small"><label for="modal01">× Modal Close</label></div>
                <!-- /.modalText --></div>
            <!-- /.modalInner --></div>
        <!-- /.modalCon --></div>
    <!-- /.modalWrap --></div>
    
    <div class="mainVisual main02 flex center">
            <div class="btn"><label for="modal02">Modal Open</label></div>
    <!-- /.mainVisual --></div>
    <div class="content">
            <h1 class="ttl">夏目漱石「吾輩は猫である」</h1>
            <p>吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。この書生というのは時々我々を捕えて煮て食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始であろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶だ。その後猫にもだいぶ逢ったがこんな片輪には一度も出会わした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙を吹く。どうも咽せぽくて実に弱った。これが人間の飲む煙草というものである事はようやくこの頃知った。この書生の掌の裏でしばらくはよい心持に坐っておったが、しばらくすると非常な速力で運転し始めた。書生が動くのか自分だけが動くのか分らないが無暗に眼が廻る。胸が悪くなる。到底助からないと思っていると、どさりと音がして眼から火が出た。それまでは記憶しているがあとは何の事やらいくら考え出そうとしても分らない。</p>
                    <p>吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。この書生というのは時々我々を捕えて煮て食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始であろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶だ。その後猫にもだいぶ逢ったがこんな片輪には一度も出会わした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙を吹く。どうも咽せぽくて実に弱った。これが人間の飲む煙草というものである事はようやくこの頃知った。この書生の掌の裏でしばらくはよい心持に坐っておったが、しばらくすると非常な速力で運転し始めた。書生が動くのか自分だけが動くのか分らないが無暗に眼が廻る。胸が悪くなる。到底助からないと思っていると、どさりと音がして眼から火が出た。それまでは記憶しているがあとは何の事やらいくら考え出そうとしても分らない。</p>
                    <p>吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。この書生というのは時々我々を捕えて煮て食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始であろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶だ。その後猫にもだいぶ逢ったがこんな片輪には一度も出会わした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙を吹く。どうも咽せぽくて実に弱った。これが人間の飲む煙草というものである事はようやくこの頃知った。この書生の掌の裏でしばらくはよい心持に坐っておったが、しばらくすると非常な速力で運転し始めた。書生が動くのか自分だけが動くのか分らないが無暗に眼が廻る。胸が悪くなる。到底助からないと思っていると、どさりと音がして眼から火が出た。それまでは記憶しているがあとは何の事やらいくら考え出そうとしても分らない。</p>
            <div class="btn small"><label for="modal02">Modal Open</label></div>
    <!-- /.content --></div>
    <div id="modal02Con" class="modalWrap">
        <div class="modalBg"><label for="modal02" class="closeModal"></label></div>
        <div class="modalCon">
            <div class="modalInner">
                <div class="modalCloseBtn"><label for="modal02" class="closeModal">×</label></div>
                <h1 class="ttl modalTtl">夏目漱石「吾輩は猫である」</h1>
                <div class="modalText">
                    <div class="modalCover"><img src="https://unsplash.it/1024/768?image=40" alt=""></div>
                    <p>吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。この書生というのは時々我々を捕えて煮て食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始であろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶だ。その後猫にもだいぶ逢ったがこんな片輪には一度も出会わした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙を吹く。どうも咽せぽくて実に弱った。これが人間の飲む煙草というものである事はようやくこの頃知った。この書生の掌の裏でしばらくはよい心持に坐っておったが、しばらくすると非常な速力で運転し始めた。書生が動くのか自分だけが動くのか分らないが無暗に眼が廻る。胸が悪くなる。到底助からないと思っていると、どさりと音がして眼から火が出た。それまでは記憶しているがあとは何の事やらいくら考え出そうとしても分らない。</p>
                    <p>吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。この書生というのは時々我々を捕えて煮て食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始であろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶だ。その後猫にもだいぶ逢ったがこんな片輪には一度も出会わした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙を吹く。どうも咽せぽくて実に弱った。これが人間の飲む煙草というものである事はようやくこの頃知った。この書生の掌の裏でしばらくはよい心持に坐っておったが、しばらくすると非常な速力で運転し始めた。書生が動くのか自分だけが動くのか分らないが無暗に眼が廻る。胸が悪くなる。到底助からないと思っていると、どさりと音がして眼から火が出た。それまでは記憶しているがあとは何の事やらいくら考え出そうとしても分らない。</p>
                    <p>吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。この書生というのは時々我々を捕えて煮て食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始であろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶だ。その後猫にもだいぶ逢ったがこんな片輪には一度も出会わした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙を吹く。どうも咽せぽくて実に弱った。これが人間の飲む煙草というものである事はようやくこの頃知った。この書生の掌の裏でしばらくはよい心持に坐っておったが、しばらくすると非常な速力で運転し始めた。書生が動くのか自分だけが動くのか分らないが無暗に眼が廻る。胸が悪くなる。到底助からないと思っていると、どさりと音がして眼から火が出た。それまでは記憶しているがあとは何の事やらいくら考え出そうとしても分らない。</p>
                    <div class="btn small"><label for="modal02">× Modal Close</label></div>
                <!-- /.modalText --></div>
            <!-- /.modalInner --></div>
        <!-- /.modalCon --></div>
    <!-- /.modalWrap --></div>
<!-- /.modalWrap --></div>

<!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> -->
<script src="js/modal.js"></script>
</body>
</html>

SCSS

お次はSCSSファイル。コンパイル環境が無い方はCSSファイルをご確認下さい。


/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, 
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section {
    display: block;
}
body {
    line-height: 1;
    -webkit-text-size-adjust: 100%;
}
ol, ul {
    list-style: none;
}
blockquote, q {
    quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
    content: '';
    content: none;
}
table {
    border-collapse: collapse;
    border-spacing: 0;
}

/* ここからモーダル用CSS */
@mixin transition {
    transition: 0.3s cubic-bezier(1,0,0,1);
}
$btnColor: #f44336;

html, body, .wrapper {
    width: 100%;
    height: 100%;
}
body {
    color: #333;
}
img {
    max-width: 100%;
    height: auto;
}

// flexbox
.flex {
    display: flex;
    &.center {
        align-items: center;
        justify-content: center;
    }
}

// コンテンツ
.content {
    max-width: 1080px;
    width: 92%;
    margin: 3em auto;
    .ttl {
        margin-bottom: 0.5em;
        padding-bottom: 0.25em;
        font-size: 2em;
        font-weight: bold;
        line-height: 1.3;
        border-bottom: 1px solid #dedede;
    }
    p {
        margin-bottom: 1em;
        line-height: 1.7;
    }
}

// モーダル開閉チェックボックス
.modalCheck {
    display: none;
}

// メインビジュアル
.mainVisual {
    min-height: 240px;
    height: 50%;
    &.main01 {
        background: url(https://unsplash.it/1024/768?image=1003) no-repeat 50% 90%;
        background-size: cover;
    }
    &.main02 {
        background: url(https://unsplash.it/1024/768?image=40) no-repeat 50% 50%;
        background-size: cover;
    }
}

// ボタン
label {
    cursor: pointer;
}
.btn {
    text-align: center;
    label {
        display: inline-block;
        padding: 0.8em 1.5em;
        color: #fff;
        font-size: 24px;
        background-color: $btnColor;
        text-decoration: none;
        border-radius: 5px;
        @include transition;
        transition-property: background-color, box-shadow;
        box-shadow: 0px 0px 3px 0px rgba(0,0,0,0.3);
        &:hover {
            background-color: darken($btnColor, 10%);
            box-shadow: 0px 0px 12px 0px rgba(0,0,0,0.3);
        }
    }
    &.small label {
        font-size: 18px;
    }
}

// モーダルコンテンツ
.modalWrap, .modalBg {
    position:fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: 100%;
    margin: auto;
    z-index: 10;
}
.modalWrap {
    opacity: 0;
    visibility: hidden;
    @include transition;
    transition-property: opacity;
    will-change: opacity;
}

// モーダル背景(ラベルクリックで閉じる)
.modalBg {
    cursor: pointer;
    opacity: 0.7;
    background-color: #000;
    z-index: 2;
    label {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        display: block;
    }
}

// モーダルコンテンツ
.modalCon {
    position: absolute;
    top: 5%;
    left: 0;
    right: 0;
    width: 92%;
    max-width:640px;
    height: 86%;
    margin: auto;
    z-index: 3;
}
.modalInner {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    position: relative;
    height: 100%;
    padding: 0 1.5em 1.5em;
    cursor: default;
    background-color: #fff;
    border-radius: 5px;
    box-shadow: 0px 0px 12px 0px rgba(0,0,0,0.3);
}

// モーダル閉じるボタン
.modalCloseBtn {
    position: absolute;
    top: 0;
    right: 0;
    label {
        display: inline-block;
        padding: 0.5em;
        color: #333;
        text-decoration: none;
        font-size: 2em;
    }
}

// モーダル閉じる
.modalCheck:not(:checked) ~ .wrapper {
    > *:not(.modalWrap){
        filter: blur(0px);
    }
    .modalWrap {
        opacity:0;
        visibility: hidden;
    }
}

// モーダル開く
.modalCheck:checked ~ .wrapper {
    > *:not(.modalWrap){
        filter: blur(3px);
    }
}
$num: "";
@for $i from 0 through 2 {
  @if $i < 10 {
    $num: "0#{$i}";
  } @else {
    $num: $i;
  }
    #modal#{$num}:checked ~ .wrapper {
        #modal#{$num}Con {
            opacity: 1;
            visibility: visible;
        }
    }
}

// モーダルタイトル
.modalTtl {
    padding: 2em 0.5em 1.5em;
    font-size: 2em;
    line-height: 1.3;
    text-align: center;
}
.modalText {
    .modalCover {
        margin: 0 -1.5em 1em;
    }
    p {
        margin-bottom: 1em;
        line-height: 1.7;
    }
}

// SP時
@media (max-width: 640px) {
    .content {
        margin: 1.5em auto;
    }
    .modalInner {
        padding-left: 1em;
        padding-right: 1em;
    }
    .modalTtl {
        font-size: 1.5em;
        padding-bottom: 1em;
    }
    .modalText .modalCover {
        margin: 0 -1em 1em;
    }
}

JavaScript(jQuery)

最後にJavaScript。こちらはネイティブなJavaScriptとjQueryどちらも記載しています。お好みに合わせてどちらか一方をお使い下さい。


// ----------------------------------------
// 二重スクロールバー防止
// ----------------------------------------

// Pure JavaScript
var body = document.body;
var checkbox = document.getElementsByClassName('modalCheck');
for (var i = 0; i < checkbox.length; i++) {
    checkbox[i].addEventListener('click', function(){
        if (this.checked) {
            body.style.overflow = 'hidden';
        } else {
            body.style.overflow = 'visible';
        }
    });
}

// jQuery
/*$('.modalCheck').on('change', function(){
    if($(this).is(':checked')){
        $('body').css('overflow','hidden');
    } else {
        $('body').css('overflow','auto');
    }
});*/

コード解説

モーダルを表示する

モーダルの中身はこんな感じ。モーダル全体を囲む.modalWrapと背景オーバーレイ部分の.modalBgは上に覆いかぶさるため、position:fixed;で固定します。

モーダルを閉じる要素としてlabelタグを×ボタンと背景オーバーレイに入れておきます。


<div id="modal01Con" class="modalWrap">
    <div class="modalBg"><label for="modal01" class="closeModal"></label></div>
        <div class="modalCon">
            <div class="modalInner">
                <div class="modalCloseBtn"><label for="modal01" class="closeModal">×</label></div>
                <h1 class="ttl modalTtl">宮沢賢治「ポラーノの広場」</h1>
                <div class="modalText">
                    <div class="modalCover"><img src="https://unsplash.it/1024/768?image=1003" alt=""></div>
                    <p>あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。</p>
                    <p>あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。</p>
                    <p>あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。</p>
                <div class="btn small"><label for="modal01">× Modal Close</label></div>
            <!-- /.modalText --></div>
        <!-- /.modalInner --></div>
    <!-- /.modalCon --></div>
<!-- /.modalWrap --></div>

スクロールできるように高さの指定と overflow: auto;を合わせて指定するのがポイント。スマホでも滑らかにスクロールするには-webkit-overflow-scrolling: touch;を指定しました。

動作をアニメーションさせるためにtransitionをSCSSのmixinで指定し、transitionする要素をtransition-propertyで指定します。今回は透明・不透明を変更するのでopacityを入れました。

また、アニメーションするプロパティをwill-changeで指定することで、パフォーマンスが向上するようなので一緒に入れておきましょう。

注意点としてposition:fixed;またはposition: absolute;と、overflow: auto;は同じ要素に指定しないでください。iOSだとスクロールできなくなる不具合があります。

モーダルコンテンツ部分はwidth: 92%;max-width:640px;であまり横長にならないように幅を調整しました。表示位置や高さも微調整しています。


// モーダルコンテンツ
.modalWrap, .modalBg {
    position:fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: 100%;
    margin: auto;
    z-index: 10;
}
.modalWrap {
    opacity: 0;
    visibility: hidden;
    @include transition;
    transition-property: opacity;
    will-change: opacity;
}

// モーダル背景(ラベルクリックで閉じる)
.modalBg {
    cursor: pointer;
    opacity: 0.7;
    background-color: #000;
    z-index: 2;
    label {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        display: block;
    }
}

// モーダルコンテンツ
.modalCon {
    position: absolute;
    top: 5%;
    left: 0;
    right: 0;
    width: 92%;
    max-width:640px;
    height: 86%;
    margin: auto;
    z-index: 3;
}
.modalInner {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    position: relative;
    height: 100%;
    padding: 0 1.5em 1.5em;
    cursor: default;
    background-color: #fff;
    border-radius: 5px;
    box-shadow: 0px 0px 12px 0px rgba(0,0,0,0.3);
}

// モーダル閉じるボタン
.modalCloseBtn {
    position: absolute;
    top: 0;
    right: 0;
    label {
        display: inline-block;
        padding: 0.5em;
        color: #333;
        text-decoration: none;
        font-size: 2em;
    }
}

モーダル開閉動作はチェックボックスのON/OFFで

モーダル開閉はhtmlの1番上にあるチェックボックスをトリガーで行っています。これに続く.wrapper要素に内包される要素を操作しています。


<input type="checkbox" id="modal01" class="modalCheck">
<input type="checkbox" id="modal02" class="modalCheck">
<div class="wrapper">
~省略~
<!-- /.wrapper--></div>

チェックボックスのON/OFFを切り替えるのはlabel要素で対応。


<div class="btn"><label for="modal01">Modal Open</label></div>

チェックボックスのON/OFF状況を判定し、CSSを出し分けます。セレクタを~で繋げることで内包されていない隣接要素に対してCSSを適用できます。見た目の変化が分かりやすいように、モーダルウィンドウが展開されているときは背景をぼかすようにしています。


/* モーダル開閉チェックボックス */
.modalCheck {
    display: none;
}   

/* モーダル閉じる */
.modalCheck:not(:checked) ~ .wrapper {
    > *:not(.modalWrap){
        filter: blur(0px);
    }
    .modalWrap {
        opacity:0;
        visibility: hidden;
    }
}

/* モーダル開く */
.modalCheck:checked ~ .wrapper {
    > *:not(.modalWrap){
        filter: blur(3px);
    }
}

モーダルウィンドウ複数あった場合でも。指定した物が開くようにそれぞれのトリガーを設定します。SCSSだとfor文が使えるので記述も少なく対応できます。


/* モーダル展開用 */
$num: "";
@for $i from 0 through 2 { // 2の数字をモーダルの数に合わせて変更
    // 先頭0詰め表記に変更
    @if $i < 10 {
        $num: "0#{$i}";
    } @else {
        $num: $i;
    }
    #modal#{$num}:checked ~ .wrapper {
        #modal#{$num}Con {
            opacity: 1;
            visibility: visible;
        }
    }
}

スクロールバーの制御はJavaScriptで

スクロールバーの制御もCSSで行うつもりでしたが、どうしてもトリガーでbodyタグを制御することができず断念。JSでチェックボックスのON/OFFを判定して、チェック状況に応じてoverflowを切り替えています。

bodyタグをoverflow: hidden;を使い、はみ出た領域を切り取ることでブラウザ本来のスクロールバーを消しています。これをしないとスクロールバーが二重になってしまいます。

iOSの場合はこの方法を使っても背景部分がスクロール出来てしまうため、モーダル展開時はモーダルウィンドウ内以外タッチ無効などの処理が別途必要になります。


// ----------------------------------------
// 二重スクロールバー防止
// ----------------------------------------

// Pure JavaScript
var body = document.body;
var checkbox = document.getElementsByClassName('modalCheck');
for (var i = 0; i < checkbox.length; i++) {
    checkbox[i].addEventListener('click', function(){
        if (this.checked) {
            body.style.overflow = 'hidden';
        } else {
            body.style.overflow = 'visible';
        }
    });
}

// jQuery
/*$('.modalCheck').on('change', function(){
    if($(this).is(':checked')){
        $('body').css('overflow','hidden');
    } else {
        $('body').css('overflow','auto');
    }
});*/

まとめ

モーダル内でスクロールできるタイプはあまり見かけないので自作してみましたが、思っていたよりもあっさりと完成できました。ほぼすべての動作をCSSで実装しているのでスマホから見たときでも軽快に動作しています。

こうした方がいいよ!というアドバイスや不具合などがあれば是非教えてください。

コメントを残す

writer : 鹿
このブログを管理している鹿。Webデザインとガジェットが好き。