モーダルの実装は色々方法がありますが、↓w3schoolsの方法がシンプルでよさそうだったのでNuxt3で実装してみました。
環境
- Nuxt 3.14
- ssr: false
ゴールのイメージ

コード
// app.vue <template> <div> <button @click="open = true">Open Modal</button> <Modal v-if="open" @close="open = false" /> </div> </template> <script setup lang="ts"> const open = ref(false); </script> <style> 省略 </style>
// modal.vue <template> <div class="modal"> <div class="modal-content"> <span class="close" @click="$emit('close')">×</span> <p>Some text in the Modal..</p> </div> </div> </template> </script> <style> // styleは基本w3schoolsのExampleコピペ /* The Modal (background) */ .modal { position: fixed; /* Stay in place */ z-index: 1; /* Sit on top */ left: 0; top: 0; width: 100%; /* Full width */ height: 100%; /* Full height */ overflow: auto; /* Enable scroll if needed */ background-color: rgb(0,0,0); /* Fallback color */ background-color: rgba(0,0,0,0.4); /* Black w/ opacity */ } /* Modal Content/Box */ .modal-content { background-color: #fefefe; margin: 15% auto; /* 15% from the top and centered */ padding: 20px; border: 1px solid #888; width: 80%; /* Could be more or less, depending on screen size */ } /* The Close Button */ .close { color: #aaa; float: right; font-size: 28px; font-weight: bold; } .close:hover, .close:focus { color: black; text-decoration: none; cursor: pointer; } </style>
コード解説
モーダル(modal.vue)のstyleがどのような実装になっているか解説します
1.オーバーレイが画面全体にかかるようにposition: fixed;にする
class="modal"に、position: fixed;を設定することで、親要素の影響を受けずtop,left..等指定した場所に固定した要素を表示することができます

以下を指定することで、画面全体が覆われます
// class="modal" のstyle left: 0; top: 0; width: 100%; /* Full width */ height: 100%; /* Full height */
2.オーバーレイの子要素にモーダルを追加する
<div class="modal"> // position: fixed; で親要素から影響を受けない状態になっている <div class="modal-content"> // 親要素(class="modal")が画面全体に表示されているため子要素を中央寄せすればOK </div> </div>
以下で中央寄せしている
// class="modal-content" のstyle margin: 15% auto; /* 15% from the top and centered */
さいごに
モーダルの表示にtransformを使用するとposition: fixedが効かなくなる問題にぶち当たって、なにかいい方法はないかな?と思っていたら今回の実装方法の記事にたどり着きました。
position: fixedが効かなくなる問題は以下の記事でわかりやすく解説されていました(ありがたい)

















