Parallels Desktop 20%OFFセール中Check!

【CSS】モーダルダイアログのデザイン・アニメーションのアイデア集

CSSでモーダルダイアログをデザインする

やっほー。この記事ではモーダルダイアログのデザインを具体例を挙げて紹介します。

ダイアログのデザインはUX(ユーザエクスペリエンス)に配慮する必要があります。ユーザをイライラさせないいい感じのダイアログのデザインを紹介します。コピペして使ってちょんまげ。

目次

前提: dialog要素を使う

ここでは、HTMLの<dialog>要素を使ってJavaScriptで制御するモーダルダイアログをCSSでスタイリングする方法について解説します。

<dialog>要素を使ったダイアログの作成は下記の記事で解説していますので、あわせてご覧ください。

外観のスタイリング

ここで紹介するすべてのダイアログに共通する仕様は次のとおりです。

  • ダイアログはヘッダ/ボディ/フッタの3部、またはボディ/フッタの2部で構成されています。
  • ヘッダにはタイトル、ボディには本文、フッタにはボタンを表示します。
  • 横幅は固定、高さはコンテンツの長さによって変わります。
  • コンテンツが長い場合はスクロールバーが表示されます。このとき、ヘッダとフッタはスクロールに追従せず固定表示されます。

シンプル

わりとシンプルなデザインのダイアログです。テーマカラーを青(#0075c2)にしていますが、お好みで変更してくだちい。

シンプルAのコード

HTML
<dialog id="dialogSimpleA">
  <div class="inner">
    <div class="body">
      <p>一度入信したら、もう後戻りはできません。</p>
    </div>
    <div class="footer">
      <button class="button ok">OK</button>
    </div>
  </div>
</dialog>
CSS
/* ダイアログボックスのスタイリング */
#dialogSimpleA {
  width: 26em;         /* 幅 */
  max-height: 50%;    /* 高さ */
  border: none;       /* ボーダー */
  border-radius: 4px; /* 角丸 */
  box-shadow: 0 0 24px 4px rgba(0, 0, 0, 0.4); /* 影 */
  padding: 0;          /* パディング */
}
/* 背景 */
#dialogSimpleA::backdrop {
  background-color: rgba(0, 0, 0, 0.4); /* 半透明の黒で覆う */
}
/* ボディ */
#dialogSimpleA .body {
  background-color: #fff;
  padding: 1em;
}
/* フッタ */
#dialogSimpleA .footer {
  background-color: #fff;
  text-align: right;
  padding: 1em;
  position: sticky; /* スクロール時に固定 */
  bottom: 0;
}
/* ボタン */
#dialogSimpleA .button {
  width: 8em;
  height: 2.4em;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
#dialogSimpleA .button:hover {
  opacity: 0.8;
}
#dialogSimpleA .button.ok {
  background-color: #0075c2;
  color: #fff;
}

シンプルBのコード

HTML
<dialog id="dialogSimpleB">
  <div class="inner">
    <div class="header">入信の確認</div>
    <div class="body">
      <p>一度入信したら、もう後戻りはできません。本当に入信しますか?</p>
    </div>
    <div class="footer">
      <button class="button cancel">キャンセル</button>
      <button class="button ok">入信</button>
    </div>
  </div>
</dialog>
CSS
/* ダイアログボックスのスタイリング */
#dialogSimpleB {
  width: 26em;
  max-height: 50%;
  border: none;
  border-radius: 4px;
  box-shadow: 0 0 24px 4px rgba(0, 0, 0, 0.4);
  padding: 0;
}
/* 背景 */
#dialogSimpleB::backdrop {
  background-color: rgba(0, 0, 0, 0.4);
}
/* ヘッダ */
#dialogSimpleB .header {
  background-color: #0075c2;
  color: #fff;
  font-weight: bold;
  padding: 1em;
  position: sticky;
  top: 0;
}
/* ボディ */
#dialogSimpleB .body {
  background-color: #fff;
  padding: 1em;
}
/* フッタ */
#dialogSimpleB .footer {
  background-color: #fff;
  border-top: solid 1px #ddd;
  text-align: right;
  padding: 1em;
  position: sticky;
  bottom: 0;
}
/* ボタン */
#dialogSimpleB .button {
  width: 8em;
  height: 2.4em;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
#dialogSimpleB .button:hover {
  opacity: 0.8;
}
#dialogSimpleB .button.cancel {
  background-color: #e6eae6;
}
#dialogSimpleB .button.ok {
  background-color: #0075c2;
  color: #fff;
}

フラットデザイン

今流行りのフラットデザインです。←もう流行ってません。

フラットデザインAのコード

HTML
<dialog id="dialogFlatA">
  <div class="inner">
    <div class="body">
      <p>一度入信したら、もう後戻りはできません。</p>
    </div>
    <div class="footer">
      <button class="button ok">OK</button>
    </div>
  </div>
</dialog>
CSS
/* ダイアログボックスのスタイリング */
#dialogFlatA {
  width: 26em;
  max-height: 50%;
  border: none;
  padding: 0;
}
/* 背景 */
#dialogFlatA::backdrop {
  background-color: rgba(0, 0, 0, 0.6);
}
/* ボディ */
#dialogFlatA .body {
  background-color: #fff;
  padding: 1em 2em 1em;
}
/* フッタ */
#dialogFlatA .footer {
  background-color: #fff;
  padding: 0;
  position: sticky;
  bottom: 0;
}
/* ボタン */
#dialogFlatA .button {
  width: 100%;
  height: 4em;
  border: none;
  cursor: pointer;
}
#dialogFlatA .button:hover {
  opacity: 0.8;
}
#dialogFlatA .button.ok {
  background-color: #a7d28d;
  color: #fff;
}

フラットデザインBのコード

HTML
<dialog id="dialogFlatB">
  <div class="inner">
    <div class="header">入信の確認</div>
    <div class="body">
      <p>一度入信したら、もう後戻りはできません。本当に入信しますか?</p>
    </div>
    <div class="footer">
      <button class="button cancel">キャンセル</button>
      <button class="button ok">入信</button>
    </div>
  </div>
</dialog>
CSS
/* ダイアログボックスのスタイリング */
#dialogFlatB {
  width: 26em;
  max-height: 50%;
  border: none;
  padding: 0;
}
/* 背景 */
#dialogFlatB::backdrop {
  background-color: rgba(0, 0, 0, 0.6);
}
/* ヘッダ */
#dialogFlatB .header {
  background-color: #fff;
  color: #a7d28d;
  font-weight: bold;
  padding: 2em 2em 1em;
  position: sticky;
  top: 0;
}
/* ボディ */
#dialogFlatB .body {
  background-color: #fff;
  padding: 0 2em 1em;
}
/* フッタ */
#dialogFlatB .footer {
  background-color: #fff;
  padding: 0;
  position: sticky;
  bottom: 0;
  display: flex; /* ボタンを横並びにするためにフレックスボックスを使用 */
}
/* ボタン */
#dialogFlatB .button {
  width: 50%;
  height: 4em;
  border: none;
  cursor: pointer;
}
#dialogFlatB .button:hover {
  opacity: 0.8;
}
#dialogFlatB .button.cancel {
  background-color: #abb1ad;
  color: #fff;
}
#dialogFlatB .button.ok {
  background-color: #a7d28d;
  color: #fff;
}

ステッチ

まわりを糸で縫ったようなきゃわいいデザインです。縫い目の外側の領域をbox-shadowで表現しているので、次のような欠点があります。

  • ウインドウの境界が正確でない。
  • ウインドウに影をつけることはできない。

ステッチAのコード

HTML
<dialog id="dialogStitchA">
  <div class="inner">
    <div class="body">
      <p>一度入信したら、もう後戻りはできません。</p>
    </div>
    <div class="footer">
      <button class="button ok">OK</button>
    </div>
  </div>
</dialog>
CSS
/* ダイアログボックスのスタイリング */
#dialogStitchA {
  width: 26em;
  max-height: 50%;
  background: #eee7e0;
  box-shadow: 0px 0px 0px 10px #eee7e0; /* ステッチの外側 */
  border: dashed 3px #be8f68;           /* ステッチ */
  border-radius: 6px;
  padding: 0;
}
/* 背景 */
#dialogStitchA::backdrop {
  background-color: rgba(0, 0, 0, 0.6);
}
/* ボディ */
#dialogStitchA .body {
  background-color: transparent;
  padding: 0.5em 2em;
}
/* フッタ */
#dialogStitchA .footer {
  display: flex;           /* ボタンのセンタリング */
  justify-content: center; /* ボタンのセンタリング */
  align-items: center;     /* ボタンのセンタリング */
  background-color: #eee7e0;
  padding: 1em 2em;
  position: sticky;
  bottom: 0;
}
/* ボタン */
#dialogStitchA .button {
  border: none;
  padding: 1em 4em;
  border-radius: 6px;
  cursor: pointer;
}
#dialogStitchA .button:hover {
  opacity: 0.8;
}
#dialogStitchA .button.ok {
  background-color: #be8f68;
  color: #fff;
}

ステッチBのコード

HTML
<dialog id="dialogStitchB">
  <div class="inner">
    <div class="header">入信の確認</div>
    <div class="body">
      <p>一度入信したら、もう後戻りはできません。本当に入信しますか?</p>
    </div>
    <div class="footer">
      <button class="button cancel">キャンセル</button>
      <button class="button ok">入信</button>
    </div>
  </div>
</dialog>
CSS
/* ダイアログボックスのスタイリング */
#dialogStitchB {
  width: 26em;
  max-height: 50%;
  background: #eee7e0;
  box-shadow: 0px 0px 0px 10px #eee7e0;
  border: dashed 3px #be8f68;
  border-radius: 6px;
  padding: 0;
}
/* 背景 */
#dialogStitchB::backdrop {
  background-color: rgba(0, 0, 0, 0.6);
}
/* ヘッダ */
#dialogStitchB .header {
  background-color: #eee7e0;
  color: #000;
  font-weight: bold;
  padding: 1em 2em;
  position: sticky;
  top: 0;
}
/* ボディ */
#dialogStitchB .body {
  background-color: transparent;
  padding: 0.5em 2em;
}
/* フッタ */
#dialogStitchB .footer {
  display: flex;           /* ボタンのセンタリング */
  justify-content: center; /* ボタンのセンタリング */
  align-items: center;     /* ボタンのセンタリング */
  background-color: #eee7e0;
  padding: 1em 2em;
  position: sticky;
  bottom: 0;
}
/* ボタン */
#dialogStitchB .button {
  border: none;
  margin: 0 0.5em;
  padding: 1em 2em;
  border-radius: 6px;
  cursor: pointer;
}
#dialogStitchB .button:hover {
  opacity: 0.8;
}
#dialogStitchB .button.cancel {
  background-color: #e9dacb;
  color: #000;
}
#dialogStitchB .button.ok {
  background-color: #be8f68;
  color: #fff;
}

すりガラス

ウインドウを半透明にして、さらに背景をぼかすという最新技術を駆使したデザインです。

すりガラスAのコード

HTML
<dialog id="dialogBlurA">
  <div class="inner">
    <div class="body">
      <p>一度入信したら、もう後戻りはできません。</p>
    </div>
    <div class="footer">
      <button class="button ok">OK</button>
    </div>
  </div>
</dialog>
CSS
/* ダイアログボックスのスタイリング */
#dialogBlurA {
  width: 26em;
  max-height: 50%;
  background-color: rgba(255, 255, 255, 0.4); /* 背景色は白の半透明 */
  backdrop-filter: blur(12px);                /* ぼかし */
  border: solid 1px rgba(255, 255, 255, 0.4);
  border-radius: 4px;
  box-shadow: 0 0 24px 4px rgba(0, 0, 0, 0.4);
  padding: 0;
}
/* 背景 */
#dialogBlurA::backdrop {
  background-color: rgba(0, 0, 0, 0.2);
}
/* ボディ */
#dialogBlurA .body {
  background-color: transparent; /* 背景色は透明 */
  padding: 1em 2em;
}
/* フッタ */
#dialogBlurA .footer {
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: transparent; /* 背景色は透明 */
  padding: 1em 2em;
  position: sticky;
  bottom: 0;
}
/* ボタン */
#dialogBlurA .button {
  border: outset 2px rgba(255, 255, 255, 0.4);
  padding: 0.5em 4em;
  border-radius: 6px;
  cursor: pointer;
}
#dialogBlurA .button:hover {
  backdrop-filter: blur(48px);
}
#dialogBlurA .button.ok {
  background-color: transparent;
}

すりガラスBのコード

HTML
<dialog id="dialogBlurB">
  <div class="inner">
    <div class="header">入信の確認</div>
    <div class="body">
      <p>一度入信したら、もう後戻りはできません。本当に入信しますか?</p>
    </div>
    <div class="footer">
      <button class="button cancel">キャンセル</button>
      <button class="button ok">入信</button>
    </div>
  </div>
</dialog>
CSS
/* ダイアログボックスのスタイリング */
#dialogBlurB {
  width: 26em;
  max-height: 50%;
  background-color: rgba(255, 255, 255, 0.4); /* 背景色は白の半透明 */
  backdrop-filter: blur(12px);                /* ぼかし */
  border: solid 1px rgba(255, 255, 255, 0.4);
  border-radius: 4px;
  box-shadow: 0 0 24px 4px rgba(0, 0, 0, 0.4);
  padding: 0;
}
/* 背景 */
#dialogBlurB::backdrop {
  background-color: rgba(0, 0, 0, 0.2);
}
/* ヘッダ */
#dialogBlurB .header {
  background-color: transparent; /* 背景色は透明 */
  font-weight: bold;
  padding: 2em 2em 0;
  position: sticky;
  top: 0;
}
/* ボディ */
#dialogBlurB .body {
  background-color: transparent; /* 背景色は透明 */
  padding: 1em 2em;
}
/* フッタ */
#dialogBlurB .footer {
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: transparent; /* 背景色は透明 */
  padding: 1em 2em;
  position: sticky;
  bottom: 0;
}
/* ボタン */
#dialogBlurB .button {
  border: outset 2px rgba(255, 255, 255, 0.4);
  margin: 0 1em;
  padding: 0.5em 2em;
  border-radius: 6px;
  cursor: pointer;
}
#dialogBlurB .button:hover {
  backdrop-filter: blur(12px);
}
#dialogBlurB .button.cancel {
  border: none;
  background-color: transparent;
}
#dialogBlurB .button.ok {
  background-color: transparent;
}

トラテープ

デンジャー感あふれる黄色と黒のしましまデザインです。色を変えれば可愛い感じのストライプにもなりますね。

トラテープAのコード

HTML
<dialog id="dialogStripeA">
  <div class="inner">
    <div class="body">
      <p>一度入信したら、もう後戻りはできません。</p>
    </div>
    <div class="footer">
      <button class="button ok">OK</button>
    </div>
  </div>
</dialog>
CSS
/* ダイアログボックスのスタイリング */
#dialogStripeA {
  width: 26em;
  max-height: 50%;
  border: solid 10px; /* ボーダーの種類(solid)と幅を指定 */
  border-image: repeating-linear-gradient(
      -45deg,       /* ストライプの傾き */
      #ffdc00,      /* 色1 */
      #ffdc00 10px, /* 色1 終了地点(太さ) */
      #24140e 10px, /* 色2 開始地点(色1の終了地点) */
      #24140e 20px  /* 色2 終了地点(色1の終了地点+太さ) */
    )
    10; /* ボーダーの幅と同じにする */
  box-shadow: 0 0 24px 4px rgba(0, 0, 0, 0.4);
  padding: 0;
}
/* 背景 */
#dialogStripeA::backdrop {
  background-color: rgba(0, 0, 0, 0.4);
}
/* ボディ */
#dialogStripeA .body {
  background-color: #fff;
  padding: 1em;
}
/* フッタ */
#dialogStripeA .footer {
  background-color: #fff;
  text-align: right;
  padding: 1em;
  position: sticky;
  bottom: 0;
}
/* ボタン */
#dialogStripeA .button {
  width: 8em;
  height: 2.4em;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
#dialogStripeA .button:hover {
  opacity: 0.8;
}
#dialogStripeA .button.ok {
  background-color: #ffdc00;
  color: #24140e;
}

トラテープBのコード

HTML
<dialog id="dialogStripeB">
  <div class="inner">
    <div class="header">入信の確認</div>
    <div class="body">
      <p>一度入信したら、もう後戻りはできません。本当に入信しますか?</p>
    </div>
    <div class="footer">
      <button class="button cancel">キャンセル</button>
      <button class="button ok">入信</button>
    </div>
  </div>
</dialog>
CSS
/* ダイアログボックスのスタイリング */
#dialogStripeB {
  width: 26em;
  max-height: 50%;
  border: none;
  box-shadow: 0 0 24px 4px rgba(0, 0, 0, 0.4);
  padding: 0;
}
/* 背景 */
#dialogStripeB::backdrop {
  background-color: rgba(0, 0, 0, 0.4);
}
/* ヘッダ */
#dialogStripeB .header {
  background-image: linear-gradient( /* 半透明の白を被せてしましまの色を薄くする */
      rgba(255, 255, 255, 0.8),
      rgba(255, 255, 255, 0.8)
    ),
    repeating-linear-gradient(
      -45deg,       /* ストライプの傾き */
      #ffdc00,      /* 色1 */
      #ffdc00 20px, /* 色1 終了地点(太さ) */
      #24140e 20px, /* 色2 開始地点(色1の終了地点) */
      #24140e 40px  /* 色2 終了地点(色1の終了地点+太さ) */
    );
  color: #000;
  font-weight: bold;
  padding: 1em;
  position: sticky;
  top: 0;
}
/* ボディ */
#dialogStripeB .body {
  background-color: #fff;
  padding: 1em;
}
/* フッタ */
#dialogStripeB .footer {
  background-color: #fff;
  border-top: solid 1px #ddd;
  text-align: right;
  padding: 1em;
  position: sticky;
  bottom: 0;
}
/* ボタン */
#dialogStripeB .button {
  width: 8em;
  height: 2.4em;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
#dialogStripeB .button:hover {
  opacity: 0.8;
}
#dialogStripeB .button.cancel {
  background-color: #24140e;
  color: #ffdc00;
}
#dialogStripeB .button.ok {
  background-color: #ffdc00;
  color: #24140e;
}

アイコン

アイコンを表示したダイアログの例です。

WebアイコンフォントのFont Awesome 6を使っているので、読み込んでおく必要があります。

アイコン インフォのコード

HTML
<dialog id="dialogIconInfo">
  <div class="inner">
    <div class="body">
      <p>一度入信したら、もう後戻りはできません。</p>
    </div>
    <div class="footer">
      <button class="button ok">OK</button>
    </div>
  </div>
</dialog>
CSS
/* ダイアログボックスのスタイリング */
#dialogIconInfo {
  width: 30em;
  max-height: 50%;
  background-color: #f7f6fb;
  border: none;
  border-radius: 8px;
  box-shadow: 0 0 24px 4px rgba(0, 0, 0, 0.4);
  padding: 0;
}
/* 背景 */
#dialogIconInfo::backdrop {
  background-color: rgba(0, 0, 0, 0.4);
}
/* アイコン */
#dialogIconInfo .inner:before {
  position: sticky;      /* スクロール時も位置を固定 */
  top: calc(50% - 2rem); /* アイコンの位置 */
  left: 2rem;            /* アイコンの位置 */
  font-family: 'Font Awesome 6 Free'; /* フォントの指定 */
  font-weight: 900;
  content: '\f05a'; /* アイコンの種類 */
  font-size: 4em;   /* アイコンの大きさ */
  color: #0075c2;   /* アイコンの色 */
}
/* ボディ */
#dialogIconInfo .body {
  background-color: #f7f6fb;
  padding: 1em 2em 1em 8em;
  margin-top: -4em;
  min-height: 4em;
}
/* フッタ */
#dialogIconInfo .footer {
  background-color: #f7f6fb;
  width: 19em;
  text-align: right;
  margin-left: 7em;
  padding: 1em 2em 2em 1em;
  position: sticky;
  bottom: 0;
}
/* ボタン */
#dialogIconInfo .button {
  width: 8em;
  height: 3em;
  border: none;
  border-radius: 1.5em;
  cursor: pointer;
}
#dialogIconInfo .button:hover {
  opacity: 0.8;
}
#dialogIconInfo .button.ok {
  background-color: #0075c2;
  color: #fff;
}

アイコン アラートのコード

HTML
<dialog id="dialogIconAlert">
  <div class="inner">
    <div class="body">
      <p>一度入信したら、もう後戻りはできません。</p>
    </div>
    <div class="footer">
      <button class="button ok">OK</button>
    </div>
  </div>
</dialog>
CSS
/* ダイアログボックスのスタイリング */
#dialogIconAlert {
  width: 30em;
  max-height: 50%;
  background-color: #fef9fb;
  border: none;
  border-radius: 8px;
  box-shadow: 0 0 24px 4px rgba(0, 0, 0, 0.4);
  padding: 0;
}
/* 背景 */
#dialogIconAlert::backdrop {
  background-color: rgba(0, 0, 0, 0.4);
}
/* アイコン */
#dialogIconAlert .inner:before {
  position: sticky;      /* スクロール時も位置を固定 */
  top: calc(50% - 2rem); /* アイコンの位置 */
  left: 2rem;            /* アイコンの位置 */
  font-family: 'Font Awesome 6 Free'; /* フォントの指定 */
  font-weight: 900;
  content: '\f071'; /* アイコンの種類 */
  font-size: 4em;   /* アイコンの大きさ */
  color: #ea5550;   /* アイコンの色 */
}
/* ボディ */
#dialogIconAlert .body {
  background-color: #fef9fb;
  padding: 1em 2em 1em 8em;
  margin-top: -4em;
  min-height: 4em;
}
/* フッタ */
#dialogIconAlert .footer {
  background-color: #fef9fb;
  width: 19em;
  text-align: right;
  margin-left: 7em;
  padding: 1em 2em 2em 1em;
  position: sticky;
  bottom: 0;
}
/* ボタン */
#dialogIconAlert .button {
  width: 8em;
  height: 3em;
  border: none;
  border-radius: 1.5em;
  cursor: pointer;
}
#dialogIconAlert .button:hover {
  opacity: 0.8;
}
#dialogIconAlert .button.ok {
  background-color: #ea5550;
  color: #fff;
}

表示位置

デフォルトでは、モーダルダイアログボックスはウインドウのど真ん中に表示されます。これはmargin: auto;で設定されています。したがって、表示位置を変更するには次のいずれかの方法をとります。

  • marginを上書き設定する。
  • margin: 0;にしてpositionで設定する。

下記の動作サンプルは、ウインドウの中央上部にダイアログを表示する例です。次のセクションで解説する上からスライドするアニメーションと組み合わせるといい感じになります。

中央上のコード

HTML
<dialog id="dialogTop">
  <div class="inner">
    <div class="header">入信の確認</div>
    <div class="body">
      <p>一度入信したら、もう後戻りはできません。本当に入信しますか?</p>
    </div>
    <div class="footer">
      <button class="button cancel">キャンセル</button
      ><button class="button ok">入信</button>
    </div>
  </div>
</dialog>
CSS
/* ダイアログボックスのスタイリング */
#dialogTop {
  width: 36em;
  max-height: 50%;
  border: none;
  border-radius: 0 0 8px 8px;
  box-shadow: 0 0 24px 4px rgba(0, 0, 0, 0.4);
  margin: 0 auto; /* 上下のマージンを0、左右をautoにする */
  padding: 0;
}
/* 背景 */
#dialogTop::backdrop {
  background-color: rgba(0, 0, 0, 0.4);
}
/* ヘッダ */
#dialogTop .header {
  background-color: #4e454a;
  color: #fff;
  font-weight: bold;
  padding: 1em;
  position: sticky;
  top: 0;
}
/* ボディ */
#dialogTop .body {
  background-color: #fff;
  padding: 1em;
}
/* フッタ */
#dialogTop .footer {
  background-color: #fff;
  text-align: right;
  padding: 1em;
  position: sticky;
  bottom: 0;
  display: flex;
  justify-content: center;
  gap: 1em;
}
/* ボタン */
#dialogTop .button {
  width: 8em;
  height: 2.4em;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
#dialogTop .button:hover {
  opacity: 0.4;
}
#dialogTop .button.cancel {
  background-color: transparent;
}
#dialogTop .button.ok {
  background-color: #fff;
  border: solid 2px #4e454a;
}

開閉時のアニメーション

ダイアログボックスの開閉時にアニメーションを追加すると非常にそれっぽくなるので、ぜひ実装したいところです。

いろいろな方法がありますが、ここではCSSのanimationプロパティを使います。で、開くときのアニメーションは比較的簡単に実装できるのですが、閉じるときのそれはなかなか厄介です。なぜかというと、開くときは

  1. 開くための操作をする
  2. ダイアログが開く
  3. アニメーション実行

という順序でコトが進むのですが、閉じるときは

  1. 閉じるための操作をする
  2. ダイアログが閉じる
  3. アニメーション実行

となるわけです。ダイアログが閉じてからアニメーションが始まっても私たちはそれを見ることができません。なので、

  1. 閉じるための操作をする
  2. ダイアログが閉じるのを待ってもらう
  3. アニメーション実行
  4. アニメーションが終わったらダイアログを閉じる

というふうにします。そのためにJavaScript様の力を借ります。ちょっと難しくなっちゃうけど堪忍やで。

スライドのコード

HTML
<dialog id="dialogSlide">
  <div class="inner">
    <div class="body">
      <p>一度入信したら、もう後戻りはできません。</p>
    </div>
    <div class="footer">
      <button class="button ok">OK</button>
    </div>
  </div>
</dialog>
CSS
/* 開くときのアニメーション */
#dialogSlide[open] {                      /* ダイアログにopen属性が付いたら */
  animation: slideDown 200ms ease normal; /* アニメーションを実行 */
}
@keyframes slideDown {            /* アニメーションの動きの定義 */
  from {                          /* アニメーションの開始 */
    transform: translateY(-110%); /* 上から */
  }
  to {                            /* アニメーションの終了 */
    transform: translateY(0%);    /* 本来の位置へ */
  }
}
#dialogSlide[open]::backdrop {         /* ダイアログにopen属性が付いた背景 */
  animation: fadeIn 200ms ease normal; /* アニメーションを実行 */
}
@keyframes fadeIn { /* アニメーションの動きの定義 */
  from {            /* アニメーションの開始 */
    opacity: 0;     /* 透明から */
  }
  to {              /* アニメーションの終了 */
    opacity: 1;     /* 色付きへ */
  }
}

/* 閉じるときのアニメーション */
#dialogSlide.hide {                     /* ダイアログにhideクラスが付いたら(JavaScriptで付ける) */
  animation: slideUp 200ms ease normal; /* アニメーションを実行 */
}
@keyframes slideUp {              /* アニメーションの動きの定義 */
  to {                            /* アニメーションの終了 */
    transform: translateY(-110%); /* (本来の位置から)上へ */
  }
}
#dialogSlide.hide::backdrop {           /* ダイアログにhideクラスが付いた背景 */
  animation: fadeOut 200ms ease normal; /* アニメーションを実行 */
}
@keyframes fadeOut { /* アニメーションの動きの定義 */
  to {               /* アニメーションの終了 */
    opacity: 0;      /* (本来の色から)透明へ */
  }
}
JavaScript
//各要素を変数に代入
const dialogSlide = document.querySelector('#dialogSlide');
const okButtonSlide = document.querySelector('#dialogSlide .button.ok');

//「OK」ボタンがクリックされたとき
okButtonSlide.addEventListener('click', function () {
  dialogSlide.classList.add('hide'); //ダイアログにhideクラスを追加
  dialogSlide.addEventListener('animationend', function closeDialog() { //アニメーションが終わったら
    this.classList.remove('hide'); //hideクラスを削除
    this.close(); //ダイアログを閉じる
    this.removeEventListener('animationend', closeDialog); //イベントリスナーを取り外す
  });
});

フェードのコード

HTML
<dialog id="dialogFade">
  <div class="inner">
    <div class="body">
      <p>一度入信したら、もう後戻りはできません。</p>
    </div>
    <div class="footer">
      <button class="button ok">OK</button>
    </div>
  </div>
</dialog>
CSS
/* 開くときのアニメーション */
#dialogFade[open],                     /* ダイアログにopen属性が付いたら */
#dialogFade[open]::backdrop {          /* 背景も */
  animation: fadeIn 200ms ease normal; /* アニメーションを実行 */
}
@keyframes fadeIn { /* アニメーションの動きの定義 */
  from {            /* アニメーションの開始 */
    opacity: 0;     /* 透明から */
  }
  to {              /* アニメーションの終了 */
    opacity: 1;     /* 色付きへ */
  }
}

/* 閉じるときのアニメーション */
#dialogFade.hide,                       /* ダイアログにhideクラスが付いたら */
#dialogFade.hide::backdrop {            /* 背景も */
  animation: fadeOut 200ms ease normal; /* アニメーションを実行 */
}
@keyframes fadeOut { /* アニメーションの動きの定義 */
  to {               /* アニメーションの終了 */
    opacity: 0;      /* (本来の色から)透明へ */
  }
}
JavaScript
//各要素を変数に代入
const dialogFade = document.querySelector('#dialogFade');
const okButtonFade = document.querySelector('#dialogFade .button.ok');

//「OK」ボタンがクリックされたとき
okButtonFade.addEventListener('click', function () {
  dialogFade.classList.add('hide'); //ダイアログにhideクラスを追加
  dialogFade.addEventListener('animationend', function closeDialog() { //アニメーションが終わったら
    this.classList.remove('hide'); //hideクラスを削除
    this.close(); //ダイアログを閉じる
    this.removeEventListener('animationend', closeDialog); //イベントリスナーを取り外す
  });
});

さいごに

最後まで読んでくださりありがとうございます。あなたにダイアログマスターの称号を授けます。←なんの権限があって。

でわでわ

CSSでモーダルダイアログをデザインする

この記事が気に入ったら
いいね または フォローしてね!

シェアしてね

コメント

コメントする

目次