【コピペOK】メールテンプレート デザイン9選 — ウェルカムから通知まで
メールテンプレート デザインは、ニュースレターを一枚きれいに作ることではなく、ウェルカム・領収書・パスワード再設定のようにサービスが自動送信する「取引型」メールを種類ごとに用意することです。9個のうち1つには、請求金額が0円から実際に12,900円まで上がるカウンターが入っています。
自動再生 · タイルを押すとその項目へ · すべて1つのzip
- 01 ウェルカムメール
- 02 領収書・注文確認メール
- 03 パスワード再設定メール
- 04 通知メール
- 05 配送状況メール
- 06 メールアドレス認証コード
- 07 請求書・サブスク決済メール
- 08 予約確認メール
- 09 セキュリティ通知メール
9個は人気順ではなく、一人のユーザーがサービスを体験する順番で並べました。登録直後のウェルカムメール、初回決済の領収書、アカウントを忘れたときのパスワード再設定と認証コード、ふだん届く通知、購入後の配送案内、毎月の請求書、予約を入れたときの確認メール、最後にセキュリティが心配なときのログイン警告です。9個とも<table role="presentation">のテーブルレイアウトとmax-width:400pxの可変カードで組まれているため、実際のメール配信サービス(ESP)にそのまま貼り付けられます。
01ウェルカムメール
登録直後に自動送信される最初のメールです。バッジが2秒ごとに軽く弾み、ボタンを押すとその場で「開始しました ✓」に変わります。
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" class="ema__card" style="max-width:400px">
<tr><td class="ema__brand">◆ Acme</td></tr>
<tr><td align="center" class="ema__hero"><span class="ema__badge">👋</span></td></tr>
<tr><td align="center" class="ema__title">환영합니다, 지훈님!</td></tr>
<tr><td align="center" class="ema__ctawrap">
<a href="#" role="button" class="ema__cta" id="cta">시작하기</a>
</td></tr>
</table>
02領収書・注文確認メール
決済直後に自動送信される注文確認メールです。「領収書を見る」を押すとgrid-template-rowsが0frから1frに変わり、注文内訳2件が実際に開きます。
.ema__detail {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows $dur-base $ease-spring;
}
.ema.is-open .ema__detail { grid-template-rows: 1fr; }
.ema__detailin { overflow: hidden; }
03パスワード再設定メール
リンクの有効期限が10分から0まで実際に減っていくカウントダウンが入っています。setIntervalが1秒ごとに残り秒数を減らし、mm:ss形式で再描画します。
var left = 600;
setInterval(function () {
if (left <= 0) return;
left -= 1;
var m = Math.floor(left / 60), s = left % 60;
cd.textContent = (m < 10 ? '0' : '') + m + ':' + (s < 10 ? '0' : '') + s;
}, 1000);
04通知メール
コメントやメンションなど、もっとも頻繁に届く汎用通知メールです。「コメントを見る」を押すと未読ドットが実際に消え、ボタンラベルが「既読」に変わります。
cta.addEventListener('click', function (e) {
e.preventDefault();
ema.classList.remove('is-demo');
ema.classList.add('is-read');
cta.textContent = '읽음';
});
05配送状況メール
プログレスバーが2秒周期で自動的に埋まり、「配送を確認」を押すと実際の配送3段階が開きます。widthではなくtransform: scaleX()で埋めるため、レイアウトの再計算が起きません。
.ema__fill { transform-origin: left; }
.ema.is-demo .ema__fill { animation: ema-progress 2s ease-in-out infinite; }
@keyframes ema-progress {
0%, 15% { transform: scaleX(.18); }
55%, 70% { transform: scaleX(.86); }
100% { transform: scaleX(.18); }
}
06メールアドレス認証コード
認証コードの文字間隔が呼吸するように広がって狭まり、「コピー」ボタンは実際にクリップボードへコードを送ります。navigator.clipboardがない環境(古いWebViewなど)では、隠し<textarea>とdocument.execCommand('copy')で本当にコピーを試み、それも失敗したら「コピー済み」ではなく正直に「コピー失敗」を表示します。
function copyCode(code) {
var ok = false;
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(code); ok = true;
} else {
var ta = document.createElement('textarea');
ta.value = code; ta.style.position = 'fixed'; ta.style.opacity = '0';
document.body.appendChild(ta); ta.select();
try { ok = document.execCommand('copy'); } catch (e) { ok = false; }
document.body.removeChild(ta);
}
copystate.textContent = ok ? '복사됨' : '복사 실패 — 직접 선택하세요';
}
07請求書・サブスク決済メール
0円から始まった請求金額がrequestAnimationFrameで実際に12,900円まで上がり、押すと内訳が開きます。
var target = 12900, t0 = null;
function step(ts) {
if (!t0) t0 = ts;
var p = Math.min(1, (ts - t0) / 1200);
amt.textContent = Math.round(target * p).toLocaleString('ko-KR') + '원';
if (p < 1) requestAnimationFrame(step);
}
requestAnimationFrame(step);
08予約確認メール
日付バッジが2秒ごとにrotateYで回転し、「カレンダーに追加」を押すと実際にラベルが「追加済み ✓」に変わります。
.ema__badge { transform-style: preserve-3d; }
.ema.is-demo .ema__badge { animation: ema-flip 2s ease-in-out infinite; }
@keyframes ema-flip {
0%, 20% { transform: rotateY(0); }
50%, 65% { transform: rotateY(180deg); }
100% { transform: rotateY(360deg); }
}
09セキュリティ通知メール
新規ログインバッジが$errorトークンの警告色でじんわり光り、押すと実際にボタンが「保護完了 ✓」に変わります。他の8個のブランドブルーではなくエラー色を使うのは、安心させる通知と警戒すべき通知は色から違うべきだと考えたからです。
.ema.is-demo .ema__badge { animation: ema-glow 2s ease-in-out infinite; }
@keyframes ema-glow {
0%, 100% { box-shadow: 0 0 0 0 rgba(194, 54, 26, .4); }
50% { box-shadow: 0 0 0 12px rgba(194, 54, 26, 0); }
}
どこで壊れるか — 落とし穴
最大の落とし穴は、Outlook(デスクトップ)のレンダリングエンジンが@keyframesもflexboxも最新CSSの多くも対応していないことです。そのため9個ともレイアウトは<table role="presentation">で組み、width="100%"とstyle="max-width:400px"を併用して、テーブル幅が固定されるクライアントでも崩れないようにしました。<!--[if mso]>〜<![endif]-->の条件付きコメントでOutlookだけ別のテーブルラッパーを被せているのも同じ理由です。2つ目の落とし穴は実際にコードで踏みました — 見出しやボタンの文字にfont: 700 12px/1 inherit;のような省略形を使うと、inheritがfont-familyの位置で無効な値になり宣言全体が無効化され、ブラウザの既定フォント(13px前後)に静かに戻ってしまいます。font-familyだけを別の行に出してfont: 700 12px/1;を残しても、フォント名の欠けた省略形はやはり無効のままで復活しないため、省略形をやめてfont-weight: 700; font-size: 12px; line-height: 1;と個別のプロパティで書きフォントは継承に任せるか、省略形の中に実際のフォント名まで書いて、はじめて正しいフォントが当たります。3つ目はサイズです — 最初は9個とも480×300のステージでスクロールバーが出るほど溢れており、セルの内側余白を8pxから4pxに減らし、ダークモードボタンをカードのレイアウト外(絶対配置)に出してこれは解決しましたが、トグルボタン・カウントダウン・進行状況トラックのような「追加の行」を持つ6個は、320×200のスマホ画面ではまだ10〜46px溢れたままでした。その行の内側要素(ボタン・リスト行・進行バーの余白)まで同じように削ってようやく320×200にも収まりました。4つ目は02番・領収書のきらめきアニメーションです — 最初は2秒のうち0.7秒しか動かず、23フレーム中4フレームしか「動いたフレーム」と判定されず(下限6)、動く区間を1.8秒に広げてから16フレームまで上がりました。この4つは実際に測定して見つかったもので、感覚で直したものは一つもありません。圧縮パスワード4m43f23gで開くzip内のvanilla版は、この4つをすべて反映した最新版です。
アクセシビリティ
9個ともprefers-reduced-motion: reduceではバッジ・プログレスバーの繰り返しアニメーション(回転・パルス・グロー・バーの塗りつぶし全てanimation: none !important)を止めますが、クリックで変わる実際の状態(既読処理・展開・完了表示)はそのまま残します。ボタンはすべて実際の<button>またはrole="button"のリンクなのでキーボードフォーカスとEnter・スペースで操作でき、展開する要素にはaria-expandedを、切り替え型ボタンにはaria-pressedを付けています。認証コードのコピー(06)の状態表示はaria-live="polite"のため、画面を移動しなくてもスクリーンリーダーが「コピーしました」を読み上げます。ダークモードは手動トグルボタンと<meta name="color-scheme" content="light dark">+@media (prefers-color-scheme: dark)の両方を入れており、システムのダークモードに対応するクライアントではボタンなしでも自動的に切り替わります。
他のメール関連の記事はテンプレートカテゴリーに、このサイト全体については概要ページにあります。クライアントごとのCSS対応状況はCan I emailで確認できます。
FAQ
このテンプレートをそのままメール配信サービス(ESP)で使えますか?
はい、そのために作りました。zip内のvanilla版はテーブルベースのレイアウト + インラインに近いスタイル + max-width:400pxの可変カードで組まれているため、Mailchimp・SendGrid・Resendなどの貼り付け欄にそのまま入れられます。400pxはニュースレターより狭い、取引型カード向けの幅です。もっと広くしたい場合はmax-widthの値を変えるだけで済みます。送信前には必ずCan I emailでお使いのサービスが使うクライアントの対応状況を確認してください。
なぜ9個中8個が青色で、09番だけ赤色なのですか?
8個はブランドブルー($subject-blue)をCTA・バッジの色として共有し、1社が送るメールのような統一感を出しています。セキュリティ通知(09)だけはエラートークン($error)を使いました。安心させるメールと警戒させるメールは、色から違うべきだと判断したためです。
ダークモードのプレビューボタンは、実際のダークモードと同じ動作ですか?
はい、同じCSSルールを使っています。ボタンは.is-darkクラスを切り替えて、@media (prefers-color-scheme: dark)と同じ背景・文字色のルールを強制的に適用するだけなので、ボタンを押して見える画面は実際のダークモード対応クライアント(Apple Mail・Outlook.comなど)で表示される画面と同じです。