Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
dialog要素でつくるモーダルダイアログ
Search
yomotsu
September 16, 2022
Programming
0
860
dialog要素でつくるモーダルダイアログ
yomotsu
September 16, 2022
Tweet
Share
More Decks by yomotsu
See All by yomotsu
three.jsとRapierでレースゲームが3日でできた話
yomotsu
0
120
PBR in three.js
yomotsu
1
730
IE to Edge
yomotsu
1
280
A Camera Control Library for three.js
yomotsu
1
910
Let’s try AR on mobile Web with <model-viewer>
yomotsu
0
500
WebXR: Beyond WebGL
yomotsu
2
1.5k
Non-DOM components with WebGL in Vue.js
yomotsu
5
12k
WebGL Libs for WebApp Frameworks
yomotsu
4
7.7k
How do you show assets loading?
yomotsu
1
940
Other Decks in Programming
See All in Programming
Elm Form Validation
bkuhlmann
0
510
スクラムガイドのスプリントレトロスペクティブを改めて読みかえしてみた / Re-reading the Sprint Retrospective Section in the Scrum Guide
mackey0225
3
430
Ruby Pattern Matching
bkuhlmann
0
930
Git Lint
bkuhlmann
4
750
GitHub Copilotのススメ
marcy731
1
200
2 週間で Twitter Bot を作ってみた
contour_gara
0
390
新宿ダンジョンを可視化してみた
satoshi7190
2
260
DMMプラットフォームがTiDB Cloudを採用した背景
pospome
8
4.1k
Java 22 Overview
kishida
1
180
Ruby Function Composition
bkuhlmann
1
330
Build Apps for iOS, Android & Desktop in 100% Kotlin With Compose Multiplatform (mDevCamp 2024)
zsmb
0
330
VS Code をプロダクトにどう取り込むか
onomax
1
360
Featured
See All Featured
Designing on Purpose - Digital PM Summit 2013
jponch
110
6.5k
The Straight Up "How To Draw Better" Workshop
denniskardys
227
130k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
227
16k
YesSQL, Process and Tooling at Scale
rocio
164
13k
Product Roadmaps are Hard
iamctodd
44
9.7k
Designing the Hi-DPI Web
ddemaree
276
33k
Optimising Largest Contentful Paint
csswizardry
8
2.4k
10 Git Anti Patterns You Should be Aware of
lemiorhan
648
58k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
121
39k
[RailsConf 2023] Rails as a piece of cake
palkan
23
4k
Ruby is Unlike a Banana
tanoku
96
10k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
20
1.9k
Transcript
EJBMPHཁૉͰͭ͘Δ ϞʔμϧμΠΞϩά $PEFST)JHI 1BSU খࢁాߊߒ
w ը໘ͷ࠷લ໘ʹදࣔ͞ΕΔϘοΫε w ϘοΫεʹίϯςϯπ͕ల։͞ΕΔ w ด͡ΔϘλϯ͕͍͍ͭͯΔ w എ໘ʹΦʔόʔϨΠ͕͋Δ ϞʔμϧμΠΞϩάͱ
None
None
None
None
None
w ͍ͭಉ͡+4ϥΠϒϥϦΛͬͯ͠·͏ ʢΧελϚΠζͮ͠Β͍ʣ w Ϟʔμϧͷ[JOEFY͍ͭ͘ʹ͢Δʁ w λϒΩʔΛԡ͢ͱϞʔμϧ֎ʹҠಈͯ͠͠·͏ w 3FBDUͷDSFBUF1PSUBM
7VFͷ5FMFQPSU͕ඞཁ Ϟʔμϧͷ͓Έ
None
EJBMPHͰղܾͰ͖·͢ʂ
גࣜձࣾϐΫηϧάϦου খࢁాߊߒ @yomotsu
Ϟʔμϧ༻ͷཁૉEJBMPH ॏͳΓͷΈ $44ͰΧελϚΠζ EJBMPHͷऑ ͓ॻ͖
Ϟʔμϧ༻ͷཁૉ EJBMPH
w ɺچ༷ͷEJBMPH͕আ w ɺ)5.--JWJOH4UBOEBSEʹ ݱ༷ͰՃ w ɺ$ISPNJVNͰαϙʔτ w ɺ)5.-ͱͯ͠8$༷ʹՃ
EJBMPH
https://html.spec.whatwg.org/multipage/interactive-elements.html#the-dialog-element
<!-- モーダル --> <dialog id="my-modal"> <p>簡易モーダル</p> </dialog>
<!-- モーダル --> <dialog id="my-modal"> <p>簡易モーダル</p> </dialog> <!-- 開くボタン
--> <button type="button" onclick="document.querySelector('#my-modal').showModal();" > 開く </button>
<!-- モーダル --> <dialog id="my-modal"> <p>簡易モーダル</p> </dialog> <!-- 開くボタン
--> <button type="button" onclick="document.querySelector('#my-modal').showModal();" > 開く </button>
<!-- モーダル --> <dialog id="my-modal"> <p>簡易モーダル</p> </dialog> <!-- 開くボタン
--> <button type="button" onclick="document.querySelector('#my-modal').showModal();" > 開く </button>
<!-- モーダル --> <dialog id="my-modal"> <p>簡易モーダル</p> <button type="button" onclick="document.querySelector( '#my-modal'
).close();" > 閉じる </button> </dialog> <!-- 開くボタン --> <button type="button" onclick="document.querySelector('#my-modal').showModal();" > 開く </button>
None
w ɹ$ISPNF ɹ4BGBSJ ɹ'JSFGPY ͰαϙʔτࡁΈ w ඇαϙʔτϒϥβ͚
ϙϦϑΟϧ͕͋Δ EJBMPH
https://github.com/GoogleChrome/dialog-poly fi ll
ॏͳΓͷΈ
w [JOEFYͰࢦఆ͢Δ w ߴ͍͕લ໘ʹදࣔ w ͷॏͳΓ͕༏ઌ ʢελοΩϯάίϯςΩετʣ [JOEFYͷ͓͞Β͍
None
None
None
None
None
w ࠷લ໘ʹදࣔ͢ΔͨΊͷ͍ͭ͘ʁ w ೖΕࢠʹͳΔͱ ࠷લ໘ʹදࣔͰ͖ͳ͍ [JOEFYͷ͓Έ
w EJBMPHʹద༻͞ΕΔ ॏͳΓϨΠϠʔ w ඞͣ࠷લ໘ʹදࣔ͞ΕΔ w $44 [JOEFYͳͲ Ͱ͑ΒΕͳ͍
τοϓϨΠϠʔ
https://fullscreen.spec.whatwg.org/#top-layer
None
None
EJBMPH ࠷લ໘͕อূ͞Ε͍ͯΔ ελοΩϯάίϯςΩετͷೖΕࢠಥഁ
$44ͰΧελϚΠζ
w EJBMPHʹϒϥβ$44͕ޮ͍͍ͯΔɻ $44্ॻ͖Մೳ w എܠ෦ CBDLESPQηϨΫλͰ੍ޚͰ͖Δ ϙϦϑΟϧར༻࣌CBDLESPQ
$44ͰΧελϚΠζ
None
None
None
None
EJBMPHͷऑ എܠΫϦοΫͰด͍ͨ͡
None
EJBMPHΛΫϦοΫͨ͠ͱ͖ ΫϦοΫ͕ɺຊମΑΓ֎ͳΒ ด͡Δ
None
const $modal = document.querySelector( '#my-modal' ); $modal.removeEventListener( 'click', onDialogClick );
function onDialogClick( event ) { const elRect = $modal.getBoundingClientRect(); const isInDialog = elRect.top <= event.clientY && event.clientY <= elRect.bottom && elRect.left <= event.clientX && event.clientX <= elRect.right; // もし、内側をクリックしていたら、なにもしない if ( isInDialog ) return; // それ以外(外側をクリック)なら閉じる $modal.close(); }
const $modal = document.querySelector( '#my-modal' ); $modal.removeEventListener( 'click', onDialogClick );
function onDialogClick( event ) { const elRect = $modal.getBoundingClientRect(); const isInDialog = elRect.top <= event.clientY && event.clientY <= elRect.bottom && elRect.left <= event.clientX && event.clientX <= elRect.right; // もし、内側をクリックしていたら、なにもしない if ( isInDialog ) return; // それ以外(外側をクリック)なら閉じる $modal.close(); }
EJBMPHͷऑ ΞχϝʔγϣϯͰด͍ͨ͡
w ։͘ࡍʹɺ $44"OJNBUJPOTΛద༻͢Δ w ։͘ޙɺด͡Δલʹ DMBTTΛมߋͯ͠ $445SBOTJUJPOΛద༻͢Δ
Ξχϝʔγϣϯ
@keyframes fadeIn { 0% { opacity: 0; } 100% {
opacity: 1; } }
.myModal[open] { animation: fadeIn 1s 1; } .myModal[open]::backdrop { animation:
fadeIn 1s 1; } EJBMPH͕։͘ͱ PQFOଐੑ͕͘
None
.myModal:modal { animation: fadeIn 1s 1; } .myModal:modal::backdrop { animation:
fadeIn 1s 1; } NPEBMٖࣅΫϥε ϙϦϑΟϧͰ͖ͳ͍
w ։͘ࡍʹɺ $44"OJNBUJPOTΛద༻͢Δ w ։͘ޙɺด͡Δલʹ DMBTTΛมߋͯ͠ $445SBOTJUJPOΛద༻͢Δ
Ξχϝʔγϣϯ
dialog.myModal { opacity: 0; transform: scale( .9 ); transition: opacity
.5s, transform .5s; } dialog.myModal.-opening { opacity: 1; transform: scale( 1 ); }
const showModal = ( id ) => { const $modal
= document.getElementById( id ); $modal.showModal(); requestAnimationFrame( () => $modal.classList.add( '-opening' ) ); } ϑϨʔϜ͔ͬͯΒ ΫϥεΛ༩͢Δ
const closeModal = ( id ) => { const $modal
= document.getElementById( id ); $modal.classList.remove( '-opening' ); $modal.addEventListener( 'transitionend', $modal.close, { once: true } ); } ΞχϝʔγϣϯྃΛͬͯ DMPTF͢Δ
None
EJBMPHͷऑ εΫϩʔϧΛࢭΊ͍ͨ
None
<script src="https://unpkg.com/
[email protected]
/index.js"></script>
const showModal = ( id ) => { const $modal
= document.getElementById( id ); $modal.showModal(); noScroll.on(); // ϖʔδຊମͷεΫϩʔϧΛࢭ͢Δ $modal.addEventListener( 'cancel', onClose ); $modal.addEventListener( 'close', onClose ); } EJBMPHͷDMPTF DBODFM͔DMPTFΠϕϯτͰ ݕͰ͖Δ
const onClose = ( event ) => { noScroll.off(); //
ページ本体のスクロール抑止解除 const $modal = event.target; $modal.removeEventListener( 'cancel', onClose ); $modal.removeEventListener( 'close', onClose ); }
w جຊ͚ͩͳΒ+4΄΅ෆཁ w +4ίʔυѹతʹগͳ͍ ʢϒϥβ͕ɺ΄ͱΜͲͬͯ͘ΕΔʣ w ʮϒϥοΫϘοΫεʯ͕ͳ͍ w τοϓϨΠϠʔΛ͍͍ͨͳΒ
EJBMPHҰ ݁ہ+4͕ඞཁʁ
͓࣋ͪؼΓ༻ ίʔυ
https://github.com/codegrid/2022-09-16-cssnite-dialog
https://www.codegrid.net/series/2022-modal-dialog
·ͱΊ
w γϯϓϧ࣮ͳΒɺ+4ϥΠϒϥϦෆཁ w ΧελϚΠζ͍͢͠ɺ੍ޚ͍͢͠ w ࠷લ໘͕อূ͞ΕΔ τοϓϨΠϠʔ w ϑΥʔΧεɺΩʔϘʔυૢ࡞ɺSPMF੍ޚ
Ϟʔμϧઐ༻ͷཁૉͰ ʮ͍͍͜ͱʯͨ͘͞Μ
Ϟʔμϧ࣮ ͏ɺμϧ͘ͳ͍ʁ
͓ΘΓ !ZPNPUTV