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
970
dialog要素でつくるモーダルダイアログ
yomotsu
September 16, 2022
Tweet
Share
More Decks by yomotsu
See All by yomotsu
three.jsとRapierでレースゲームが3日でできた話
yomotsu
0
450
PBR in three.js
yomotsu
1
850
IE to Edge
yomotsu
1
320
A Camera Control Library for three.js
yomotsu
1
1.1k
Let’s try AR on mobile Web with <model-viewer>
yomotsu
0
530
WebXR: Beyond WebGL
yomotsu
2
1.7k
Non-DOM components with WebGL in Vue.js
yomotsu
5
12k
WebGL Libs for WebApp Frameworks
yomotsu
4
7.8k
How do you show assets loading?
yomotsu
1
980
Other Decks in Programming
See All in Programming
Writing documentation can be fun with plugin system
okuramasafumi
0
120
Multi Step Form, Decentralized Autonomous Organization
pumpkiinbell
1
730
2024年のkintone API振り返りと2025年 / kintone API look back in 2024
tasshi
0
220
Amazon Q Developer Proで効率化するAPI開発入門
seike460
PRO
0
110
Kubernetes History Inspector(KHI)を触ってみた
bells17
0
220
iOSエンジニアから始める visionOS アプリ開発
nao_randd
3
130
負債になりにくいCSSをデザイナとつくるには?
fsubal
9
2.4k
富山発の個人開発サービスで日本中の学校の業務を改善した話
krpk1900
4
380
[JAWS-UG横浜 #80] うわっ…今年のServerless アップデート、少なすぎ…?
maroon1st
1
180
パスキーのすべて ── 導入・UX設計・実装の紹介 / 20250213 パスキー開発者の集い
kuralab
3
760
JavaScriptツール群「UnJS」を5分で一気に駆け巡る!
k1tikurisu
9
1.8k
Honoのおもしろいミドルウェアをみてみよう
yusukebe
1
210
Featured
See All Featured
Thoughts on Productivity
jonyablonski
69
4.5k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
Docker and Python
trallard
44
3.3k
Java REST API Framework Comparison - PWX 2021
mraible
28
8.4k
Building Flexible Design Systems
yeseniaperezcruz
328
38k
Visualization
eitanlees
146
15k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
100
18k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.1k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
133
33k
Rails Girls Zürich Keynote
gr2m
94
13k
The Language of Interfaces
destraynor
156
24k
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