どうも、くまだです。
Micromodal.jsでアクセシビリティ対応モーダルの実装メモ。
Micromodal.jsとは
Micromodal.jsは、jQueryを使わずに素のJSでモーダルを実装できます。アクセシビリティ対応です。
例えば、
- モーダルが開いているときの背景スクロールの固定が簡単
- モーダルが開いているときはモーダル以外の操作不可
- ESCボタンでモーダルを閉じる
- 閉じるボタンでモーダルを閉じる
- 背景クリックでモーダルを閉じる
- モーダルを開いたらモーダル内で最初のフォーカス可能な要素に移動
といった操作ができます。
Micromodal.jsの使い方
CDNを読み込みます。
<script src="https://unpkg.com/micromodal/dist/micromodal.min.js"></script>
コードは以下になります。参考コードはこちら。
<div class="container">
<button data-my-modal-open="modal-1" class="button">Click Me!</button>
</div>
<div class="modal micromodal-slide" id="modal-1" aria-hidden="true">
<div class="modal__overlay" tabindex="-1" data-my-modal-close>
<div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="modal-1-title">
<header class="modal__header">
<h2 class="modal__title" id="modal-1-title">
Micromodal
</h2>
<button class="modal__close" aria-label="Close modal" data-my-modal-close></button>
</header>
<main class="modal__content" id="modal-1-content">
<p>
Try hitting the <code>tab</code> key and notice how the focus stays within the modal itself. Also, <code>esc</code> to close modal.
</p>
</main>
<footer class="modal__footer">
<button class="modal__btn modal__btn-primary">Continue</button>
<button class="modal__btn" data-my-modal-close aria-label="Close this dialog window">Close</button>
</footer>
</div>
</div>
</div>
/**************************\
Basic Modal Styles
\**************************/
.modal {
font-family: -apple-system,BlinkMacSystemFont,avenir next,avenir,helvetica neue,helvetica,ubuntu,roboto,noto,segoe ui,arial,sans-serif;
}
.modal__overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.6);
display: flex;
justify-content: center;
align-items: center;
}
.modal__container {
background-color: #fff;
padding: 30px;
max-width: 500px;
max-height: 100vh;
border-radius: 4px;
overflow-y: auto;
box-sizing: border-box;
}
.modal__header {
display: flex;
justify-content: space-between;
align-items: center;
}
.modal__title {
margin-top: 0;
margin-bottom: 0;
font-weight: 600;
font-size: 1.25rem;
line-height: 1.25;
color: #00449e;
box-sizing: border-box;
}
.modal__close {
background: transparent;
border: 0;
}
.modal__header .modal__close:before { content: "\2715"; }
.modal__content {
margin-top: 2rem;
margin-bottom: 2rem;
line-height: 1.5;
color: rgba(0,0,0,.8);
}
.modal__btn {
font-size: .875rem;
padding-left: 1rem;
padding-right: 1rem;
padding-top: .5rem;
padding-bottom: .5rem;
background-color: #e6e6e6;
color: rgba(0,0,0,.8);
border-radius: .25rem;
border-style: none;
border-width: 0;
cursor: pointer;
-webkit-appearance: button;
text-transform: none;
overflow: visible;
line-height: 1.15;
margin: 0;
will-change: transform;
-moz-osx-font-smoothing: grayscale;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-transform: translateZ(0);
transform: translateZ(0);
transition: -webkit-transform .25s ease-out;
transition: transform .25s ease-out;
transition: transform .25s ease-out,-webkit-transform .25s ease-out;
}
.modal__btn:focus, .modal__btn:hover {
-webkit-transform: scale(1.05);
transform: scale(1.05);
}
.modal__btn-primary {
background-color: #00449e;
color: #fff;
}
/**************************\
Demo Animation Style
\**************************/
@keyframes mmfadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes mmfadeOut {
from { opacity: 1; }
to { opacity: 0; }
}
@keyframes mmslideIn {
from { transform: translateY(15%); }
to { transform: translateY(0); }
}
@keyframes mmslideOut {
from { transform: translateY(0); }
to { transform: translateY(-10%); }
}
.micromodal-slide {
display: none;
}
.micromodal-slide.is-open {
display: block;
}
.micromodal-slide[aria-hidden="false"] .modal__overlay {
animation: mmfadeIn .3s cubic-bezier(0.0, 0.0, 0.2, 1);
}
.micromodal-slide[aria-hidden="false"] .modal__container {
animation: mmslideIn .3s cubic-bezier(0, 0, .2, 1);
}
.micromodal-slide[aria-hidden="true"] .modal__overlay {
animation: mmfadeOut .3s cubic-bezier(0.0, 0.0, 0.2, 1);
}
.micromodal-slide[aria-hidden="true"] .modal__container {
animation: mmslideOut .3s cubic-bezier(0, 0, .2, 1);
}
.micromodal-slide .modal__container,
.micromodal-slide .modal__overlay {
will-change: transform;
}
MicroModal.init({
openTrigger: 'data-my-modal-open',
closeTrigger: 'data-my-modal-close',
openClass: 'is-open',
disableScroll: true,
disableFocus: true,
awaitOpenAnimation: false,
awaitCloseAnimation: true,
debugMode: true
});
See the Pen Untitled by kuma0605 (@kuma0605) on CodePen.
基本的には以下の記述だけでもモーダルが表示されます。
MicroModal.init();
オプションは以下になります。
オプション | 意味 |
---|---|
onShow | モーダルが開かれた時に呼び出し。 |
onClose | モーダルが閉じられた時に呼び出し。 |
openTrigger | 起動用マークアップを指定 |
closeTrigger | 閉じる用マークアップを指定 |
openClass | モーダルが開かれているときに付与されるクラス名を指定 |
disableScroll | モーダル起動時のスクロールを禁止の設定 |
disableFocus | モーダル起動時に最初の要素にフォーカスされるのを止める |
awaitOpenAniamtion | モーダル起動時のアニメーションを待ってから最初の要素にフォーカス |
awaitCloseAnimation | モーダルを閉じられるときにアニメーションを待つ |
自作でモーダル作る場合、アクセシビリティも考慮するとけっこう大変なので、プラグイン使うのもいいかなと。(あとjQuery使わなくても使えるのがいい)
ここまで読んでくださりありがとうございました。