Upgrade to Pro — share decks privately, control downloads, hide ads and more …

dialog要素でつくるモーダルダイアログ

yomotsu
September 16, 2022

 dialog要素でつくるモーダルダイアログ

yomotsu

September 16, 2022
Tweet

More Decks by yomotsu

Other Decks in Programming

Transcript

  1. EJBMPHཁૉͰͭ͘Δ ϞʔμϧμΠΞϩά $PEFST)JHI 1BSU  খࢁాߊߒ

  2. w ը໘ͷ࠷લ໘ʹදࣔ͞ΕΔϘοΫε w ϘοΫε಺ʹίϯςϯπ͕ల։͞ΕΔ w ด͡ΔϘλϯ͕͍͍ͭͯΔ w എ໘ʹΦʔόʔϨΠ͕͋Δ ϞʔμϧμΠΞϩάͱ͸

  3. None
  4. None
  5. None
  6. None
  7. None
  8. w ͍ͭ΋ಉ͡+4ϥΠϒϥϦΛ࢖ͬͯ͠·͏ 
 ʢΧελϚΠζͮ͠Β͍ʣ w Ϟʔμϧͷ[JOEFY͸͍ͭ͘ʹ͢Δʁ w λϒΩʔΛԡ͢ͱϞʔμϧ֎ʹҠಈͯ͠͠·͏ w 3FBDUͷDSFBUF1PSUBM

    ΍ 
 7VFͷ5FMFQPSU͕ඞཁ Ϟʔμϧͷ͓೰Έ
  9. None
  10. EJBMPHͰղܾͰ͖·͢ʂ

  11. גࣜձࣾϐΫηϧάϦου খࢁాߊߒ @yomotsu

  12.  Ϟʔμϧ༻ͷཁૉEJBMPH  ॏͳΓͷ࢓૊Έ  $44ͰΧελϚΠζ  EJBMPHͷऑ఺ ͓඼ॻ͖

  13. Ϟʔμϧ༻ͷཁૉ 
 EJBMPH

  14. w ೥ɺچ࢓༷ͷEJBMPH͕࡟আ w ೥ɺ)5.--JWJOH4UBOEBSEʹ 
 ݱ࢓༷Ͱ௥Ճ w ೥ɺ$ISPNJVNͰαϙʔτ w ೥ɺ)5.-ͱͯ͠8$࢓༷ʹ௥Ճ

    EJBMPH
  15. https://html.spec.whatwg.org/multipage/interactive-elements.html#the-dialog-element

  16. <!-- モーダル --> <dialog id="my-modal"> <p>簡易モーダル</p> </dialog>

  17. <!-- モーダル --> <dialog id="my-modal"> <p>簡易モーダル</p> </dialog> 
 <!-- 開くボタン

    --> <button type="button" onclick="document.querySelector('#my-modal').showModal();" > 開く </button>
  18. <!-- モーダル --> <dialog id="my-modal"> <p>簡易モーダル</p> </dialog> 
 <!-- 開くボタン

    --> <button type="button" onclick="document.querySelector('#my-modal').showModal();" > 開く </button>
  19. <!-- モーダル --> <dialog id="my-modal"> <p>簡易モーダル</p> </dialog> 
 <!-- 開くボタン

    --> <button type="button" onclick="document.querySelector('#my-modal').showModal();" > 開く </button>
  20. <!-- モーダル --> <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>
  21. None
  22. w ɹ$ISPNF 
 ɹ4BGBSJ 
 ɹ'JSFGPY 
 ͰαϙʔτࡁΈ w ඇαϙʔτϒϥ΢β޲͚

    
 ϙϦϑΟϧ͕͋Δ EJBMPH
  23. https://github.com/GoogleChrome/dialog-poly fi ll

  24. ॏͳΓͷ࢓૊Έ

  25. w [JOEFY͸਺஋Ͱࢦఆ͢Δ w ߴ͍஋͕લ໘ʹදࣔ w ਌ͷॏͳΓ͕༏ઌ 
 ʢελοΩϯάίϯςΩετʣ [JOEFYͷ͓͞Β͍

  26. None
  27. None
  28. None
  29. None
  30. None
  31. w ࠷લ໘ʹදࣔ͢ΔͨΊͷ஋͸͍ͭ͘ʁ w ೖΕࢠʹͳΔͱ 
 ࠷લ໘ʹදࣔͰ͖ͳ͍ [JOEFYͷ͓೰Έ

  32. w EJBMPHʹద༻͞ΕΔ 
 ॏͳΓϨΠϠʔ w ඞͣ࠷લ໘ʹදࣔ͞ΕΔ w $44 [JOEFYͳͲ Ͱ͸௒͑ΒΕͳ͍

    τοϓϨΠϠʔ
  33. https://fullscreen.spec.whatwg.org/#top-layer

  34. None
  35. None
  36. EJBMPH͸ 
 ࠷લ໘͕อূ͞Ε͍ͯΔ 
 ελοΩϯάίϯςΩετͷೖΕࢠ΋ಥഁ

  37. $44ͰΧελϚΠζ

  38. w EJBMPHʹ͸ϒϥ΢β$44͕ޮ͍͍ͯΔɻ 
 $44͸্ॻ͖Մೳ w എܠ෦෼͸ 
 CBDLESPQηϨΫλͰ੍ޚͰ͖Δ 
 ϙϦϑΟϧར༻࣌͸CBDLESPQ

    $44ͰΧελϚΠζ
  39. None
  40. None
  41. None
  42. None
  43. EJBMPHͷऑ఺ 
 എܠΫϦοΫͰด͍ͨ͡

  44. None
  45. EJBMPHΛΫϦοΫͨ͠ͱ͖ 
 ΫϦοΫ஍఺͕ɺຊମΑΓ֎ͳΒ 
 ด͡Δ

  46. None
  47. 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(); }
  48. 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(); }
  49. EJBMPHͷऑ఺ 
 ΞχϝʔγϣϯͰด͍ͨ͡

  50. w ։͘ࡍʹɺ 
 $44"OJNBUJPOTΛద༻͢Δ w ։͘௚ޙɺด͡Δ௚લʹ 
 DMBTTΛมߋͯ͠ 
 $445SBOTJUJPOΛద༻͢Δ

    Ξχϝʔγϣϯ
  51. @keyframes fadeIn { 0% { opacity: 0; } 100% {

    opacity: 1; } }
  52. .myModal[open] { animation: fadeIn 1s 1; } .myModal[open]::backdrop { animation:

    fadeIn 1s 1; } EJBMPH͕։͘ͱ PQFOଐੑ͕෇͘
  53. None
  54. .myModal:modal { animation: fadeIn 1s 1; } .myModal:modal::backdrop { animation:

    fadeIn 1s 1; } NPEBMٖࣅΫϥε͸ 
 ϙϦϑΟϧͰ͖ͳ͍
  55. w ։͘ࡍʹɺ 
 $44"OJNBUJPOTΛద༻͢Δ w ։͘௚ޙɺด͡Δ௚લʹ 
 DMBTTΛมߋͯ͠ 
 $445SBOTJUJPOΛద༻͢Δ

    Ξχϝʔγϣϯ
  56. dialog.myModal { opacity: 0; transform: scale( .9 ); transition: opacity

    .5s, transform .5s; } dialog.myModal.-opening { opacity: 1; transform: scale( 1 ); }
  57. const showModal = ( id ) => { const $modal

    = document.getElementById( id ); $modal.showModal(); requestAnimationFrame( () => $modal.classList.add( '-opening' ) ); } ϑϨʔϜ଴͔ͬͯΒ 
 ΫϥεΛ෇༩͢Δ
  58. const closeModal = ( id ) => { const $modal

    = document.getElementById( id ); $modal.classList.remove( '-opening' ); $modal.addEventListener( 'transitionend', $modal.close, { once: true } ); } Ξχϝʔγϣϯ׬ྃΛ଴ͬͯ 
 DMPTF͢Δ
  59. None
  60. EJBMPHͷऑ఺ 
 εΫϩʔϧΛࢭΊ͍ͨ

  61. None
  62. <script src="https://unpkg.com/no-scroll@2.1.1/index.js"></script>

  63. const showModal = ( id ) => { const $modal

    = document.getElementById( id ); $modal.showModal(); noScroll.on(); // ϖʔδຊମͷεΫϩʔϧΛ཈ࢭ͢Δ $modal.addEventListener( 'cancel', onClose ); $modal.addEventListener( 'close', onClose ); } EJBMPHͷDMPTF͸ 
 DBODFM͔DMPTFΠϕϯτͰ ݕ஌Ͱ͖Δ
  64. const onClose = ( event ) => { noScroll.off(); //

    ページ本体のスクロール抑止解除 const $modal = event.target; $modal.removeEventListener( 'cancel', onClose ); $modal.removeEventListener( 'close', onClose ); }
  65. w جຊ͚ͩͳΒ+4͸΄΅ෆཁ w +4ίʔυ͸ѹ౗తʹগͳ͍ 
 ʢϒϥ΢β͕ɺ΄ͱΜͲ΍ͬͯ͘ΕΔʣ w ʮϒϥοΫϘοΫεʯ͕ͳ͍ w τοϓϨΠϠʔΛ࢖͍͍ͨͳΒ

    
 EJBMPHҰ୒ ݁ہ+4͕ඞཁʁ
  66. ͓࣋ͪؼΓ༻ 
 ίʔυ

  67. https://github.com/codegrid/2022-09-16-cssnite-dialog

  68. https://www.codegrid.net/series/2022-modal-dialog

  69. ·ͱΊ

  70. w γϯϓϧ࣮૷ͳΒɺ+4ϥΠϒϥϦෆཁ w ΧελϚΠζ͠΍͍͢ɺ੍ޚ͠΍͍͢ w ࠷લ໘͕อূ͞ΕΔ τοϓϨΠϠʔ  w ϑΥʔΧεɺΩʔϘʔυૢ࡞ɺSPMF੍ޚ

    Ϟʔμϧઐ༻ͷཁૉͰ 
 ʮ͍͍͜ͱʯͨ͘͞Μ
  71. Ϟʔμϧ࣮૷͸ 
 ΋͏ɺμϧ͘ͳ͍ʁ

  72. ͓ΘΓ !ZPNPUTV