ハンバーガー→×モーフ
3本線がtransformで滑らかに×へ変形するメニュートグル。aria-expandedも同期し、モバイルナビの開閉ボタンにそのまま使えます。
ライブデモ
使用例(お題: アイドルグループ Sakura)
この技法を「アイドルグループ Sakura」というテーマのダミーサイトで実際に使った例です。
HTML
<!-- Sakura: モバイルサイト風。ハンバーガー→×でメニュー開閉 -->
<div class="sk">
<header class="sk__bar">
<span class="sk__logo">🌸 Sakura</span>
<button class="burger" type="button" aria-expanded="false" aria-label="メニューを開く" aria-controls="sk-menu">
<span class="burger__box" aria-hidden="true">
<span class="burger__line"></span>
<span class="burger__line"></span>
<span class="burger__line"></span>
</span>
</button>
</header>
<nav class="sk__menu" id="sk-menu" aria-hidden="true">
<a href="#">ホーム</a>
<a href="#">メンバー</a>
<a href="#">ライブ・イベント</a>
<a href="#">楽曲 / MV</a>
<a href="#">ニュース</a>
</nav>
<section class="sk__hero">
<p class="sk__eyebrow">2nd SINGLE</p>
<h1 class="sk__title">「春風セレナーデ」<br>配信中</h1>
<p class="sk__lead">右上のメニューを押すとナビが開きます。</p>
</section>
</div>
CSS
/* Sakura アイドル テーマ: 桜ピンク/白/淡グレー */
* { box-sizing: border-box; }
body {
margin: 0;
font-family: "Hiragino Kaku Gothic ProN", "Segoe UI", system-ui, sans-serif;
background:
radial-gradient(circle at 85% 0%, #ffe3ee 0%, transparent 55%),
#fff7fb;
color: #6b4a58;
}
.sk {
position: relative;
height: 400px;
overflow: hidden;
}
.sk__bar {
position: relative;
z-index: 3;
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 24px;
background: rgba(255,247,251,.85);
backdrop-filter: blur(4px);
border-bottom: 1px solid #ffe0ec;
}
.sk__logo {
font-size: 18px;
font-weight: 800;
color: #e85a92;
}
/* 主役: ハンバーガー→×トグル */
.burger {
width: 44px;
height: 44px;
display: grid;
place-items: center;
background: none;
border: none;
cursor: pointer;
padding: 0;
}
.burger__box {
position: relative;
width: 26px;
height: 18px;
}
.burger__line {
position: absolute;
left: 0;
width: 100%;
height: 3px;
border-radius: 3px;
background: #e85a92;
transition: transform .35s cubic-bezier(.65,0,.35,1), opacity .2s ease;
}
.burger__line:nth-child(1) { top: 0; }
.burger__line:nth-child(2) { top: 50%; transform: translateY(-50%); }
.burger__line:nth-child(3) { bottom: 0; }
/* open状態: 上下を中央へ寄せて×に、中央は消す */
.burger.is-open .burger__line:nth-child(1) {
top: 50%;
transform: translateY(-50%) rotate(45deg);
}
.burger.is-open .burger__line:nth-child(2) { opacity: 0; }
.burger.is-open .burger__line:nth-child(3) {
bottom: 50%;
transform: translateY(50%) rotate(-45deg);
}
/* スライドインするメニュー */
.sk__menu {
position: absolute;
z-index: 2;
top: 77px;
left: 0;
right: 0;
display: flex;
flex-direction: column;
background: #fff;
box-shadow: 0 16px 30px rgba(232,90,146,.18);
transform: translateY(-12px);
opacity: 0;
pointer-events: none;
transition: transform .3s ease, opacity .3s ease;
}
.sk__menu.is-open {
transform: translateY(0);
opacity: 1;
pointer-events: auto;
}
.sk__menu a {
padding: 14px 24px;
font-size: 14px;
font-weight: 600;
color: #6b4a58;
text-decoration: none;
border-bottom: 1px solid #ffeef5;
}
.sk__menu a:hover { background: #fff0f6; color: #e85a92; }
.sk__hero {
height: 100%;
display: grid;
align-content: center;
text-align: center;
gap: 12px;
padding: 0 24px;
}
.sk__eyebrow {
margin: 0;
font-size: 12px;
letter-spacing: .2em;
color: #e85a92;
font-weight: 700;
}
.sk__title {
margin: 0;
font-size: 30px;
font-weight: 800;
line-height: 1.35;
color: #4a3340;
}
.sk__lead {
margin: 0;
font-size: 13px;
color: #b08a9b;
}
@media (prefers-reduced-motion: reduce) {
.burger__line, .sk__menu { transition: none; }
}
JavaScript
// Sakuraモバイルナビ: クラスのトグルで×へモーフし、メニュー開閉とARIAを同期
(() => {
const btn = document.querySelector('.burger');
const menu = document.querySelector('.sk__menu');
if (!btn) return; // null安全
btn.addEventListener('click', () => {
const open = btn.classList.toggle('is-open');
btn.setAttribute('aria-expanded', String(open));
btn.setAttribute('aria-label', open ? 'メニューを閉じる' : 'メニューを開く');
// メニュー本体の表示と支援技術向け属性も同期
if (menu) {
menu.classList.toggle('is-open', open);
menu.setAttribute('aria-hidden', String(!open));
}
});
// メニュー内リンクのクリックでデモ遷移を防ぎつつ閉じる
if (menu) menu.addEventListener('click', (e) => {
if (!e.target.closest('a')) return;
e.preventDefault();
btn.classList.remove('is-open');
btn.setAttribute('aria-expanded', 'false');
btn.setAttribute('aria-label', 'メニューを開く');
menu.classList.remove('is-open');
menu.setAttribute('aria-hidden', 'true');
});
})();
コード
HTML
<!-- ハンバーガー→×モーフ: 3本線が滑らかに×へ変形 -->
<div class="stage">
<button class="burger" type="button" aria-label="メニューを開く" aria-expanded="false">
<span class="burger__box" aria-hidden="true">
<span class="burger__line burger__line--top"></span>
<span class="burger__line burger__line--mid"></span>
<span class="burger__line burger__line--bot"></span>
</span>
</button>
<p class="hint"><span class="state">closed</span> — クリックで切り替え</p>
</div>
CSS
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
font-family: "Segoe UI", system-ui, sans-serif;
background: radial-gradient(circle at 50% 40%, #232946 0%, #0e1020 75%);
color: #fffffe;
}
.stage {
display: grid;
place-items: center;
gap: 24px;
}
/* ボタン枠 */
.burger {
--size: 56px;
width: 80px;
height: 80px;
display: grid;
place-items: center;
border: none;
border-radius: 20px;
cursor: pointer;
background: linear-gradient(145deg, #2b3157, #1a1d36);
box-shadow: 0 10px 30px rgba(0, 0, 0, .4), inset 0 1px 0 rgba(255,255,255,.06);
transition: transform .2s ease;
}
.burger:active { transform: scale(.94); }
.burger__box {
position: relative;
width: 34px;
height: 22px;
}
/* 3本の線。中央基準で transform して × へ */
.burger__line {
position: absolute;
left: 0;
width: 100%;
height: 3px;
border-radius: 3px;
background: linear-gradient(90deg, #eebbc3, #b8c1ff);
transition: transform .4s cubic-bezier(.68,-0.6,.32,1.6), opacity .25s ease;
}
.burger__line--top { top: 0; transform-origin: center; }
.burger__line--mid { top: 50%; transform: translateY(-50%); }
.burger__line--bot { bottom: 0; transform-origin: center; }
/* 開いた状態(is-open)で×に変形 */
.burger.is-open .burger__line--top {
transform: translateY(9.5px) rotate(45deg);
}
.burger.is-open .burger__line--mid {
opacity: 0;
transform: translateY(-50%) scaleX(0);
}
.burger.is-open .burger__line--bot {
transform: translateY(-9.5px) rotate(-45deg);
}
.hint {
margin: 0;
font-size: 13px;
color: rgba(255, 255, 254, .55);
}
.state {
font-weight: 700;
color: #eebbc3;
}
@media (prefers-reduced-motion: reduce) {
.burger__line { transition: opacity .2s ease; }
}
JavaScript
// ハンバーガー→×: クラスのトグルでCSSアニメを駆動し、ARIA属性も同期
(() => {
const btn = document.querySelector('.burger');
const state = document.querySelector('.state');
if (!btn) return; // null安全
btn.addEventListener('click', () => {
const open = btn.classList.toggle('is-open');
btn.setAttribute('aria-expanded', String(open));
btn.setAttribute('aria-label', open ? 'メニューを閉じる' : 'メニューを開く');
if (state) state.textContent = open ? 'open' : 'closed';
});
})();
🤖 AIエージェント用プロンプト
このままコピーしてAIに貼り付け「追加する場所」だけ書き換えればOK
あなたは熟練のフロントエンドエンジニアです。私のWebサイトに「ハンバーガー→×モーフ」の効果を追加してください。
# 追加してほしい効果
ハンバーガー→×モーフ(マイクロインタラクション)
3本線がtransformで滑らかに×へ変形するメニュートグル。aria-expandedも同期し、モバイルナビの開閉ボタンにそのまま使えます。
# 追加する場所
👉【ここに対象箇所を記入:例「トップのヒーローセクション」「お問い合わせボタン」「記事カードの一覧」など】
# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- ハンバーガー→×モーフ: 3本線が滑らかに×へ変形 -->
<div class="stage">
<button class="burger" type="button" aria-label="メニューを開く" aria-expanded="false">
<span class="burger__box" aria-hidden="true">
<span class="burger__line burger__line--top"></span>
<span class="burger__line burger__line--mid"></span>
<span class="burger__line burger__line--bot"></span>
</span>
</button>
<p class="hint"><span class="state">closed</span> — クリックで切り替え</p>
</div>
【CSS】
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
font-family: "Segoe UI", system-ui, sans-serif;
background: radial-gradient(circle at 50% 40%, #232946 0%, #0e1020 75%);
color: #fffffe;
}
.stage {
display: grid;
place-items: center;
gap: 24px;
}
/* ボタン枠 */
.burger {
--size: 56px;
width: 80px;
height: 80px;
display: grid;
place-items: center;
border: none;
border-radius: 20px;
cursor: pointer;
background: linear-gradient(145deg, #2b3157, #1a1d36);
box-shadow: 0 10px 30px rgba(0, 0, 0, .4), inset 0 1px 0 rgba(255,255,255,.06);
transition: transform .2s ease;
}
.burger:active { transform: scale(.94); }
.burger__box {
position: relative;
width: 34px;
height: 22px;
}
/* 3本の線。中央基準で transform して × へ */
.burger__line {
position: absolute;
left: 0;
width: 100%;
height: 3px;
border-radius: 3px;
background: linear-gradient(90deg, #eebbc3, #b8c1ff);
transition: transform .4s cubic-bezier(.68,-0.6,.32,1.6), opacity .25s ease;
}
.burger__line--top { top: 0; transform-origin: center; }
.burger__line--mid { top: 50%; transform: translateY(-50%); }
.burger__line--bot { bottom: 0; transform-origin: center; }
/* 開いた状態(is-open)で×に変形 */
.burger.is-open .burger__line--top {
transform: translateY(9.5px) rotate(45deg);
}
.burger.is-open .burger__line--mid {
opacity: 0;
transform: translateY(-50%) scaleX(0);
}
.burger.is-open .burger__line--bot {
transform: translateY(-9.5px) rotate(-45deg);
}
.hint {
margin: 0;
font-size: 13px;
color: rgba(255, 255, 254, .55);
}
.state {
font-weight: 700;
color: #eebbc3;
}
@media (prefers-reduced-motion: reduce) {
.burger__line { transition: opacity .2s ease; }
}
【JavaScript】
// ハンバーガー→×: クラスのトグルでCSSアニメを駆動し、ARIA属性も同期
(() => {
const btn = document.querySelector('.burger');
const state = document.querySelector('.state');
if (!btn) return; // null安全
btn.addEventListener('click', () => {
const open = btn.classList.toggle('is-open');
btn.setAttribute('aria-expanded', String(open));
btn.setAttribute('aria-label', open ? 'メニューを閉じる' : 'メニューを開く');
if (state) state.textContent = open ? 'open' : 'closed';
});
})();
# 外部ライブラリ
なし(追加ライブラリ不要)
# 守ってほしいこと
- 既存のHTML構造・レイアウト・デザインを壊さないこと。必要に応じてクラス名・色・サイズを私のサイトに合わせて調整してよい。
- クラス名やidが既存と衝突しないよう、必要なら接頭辞で名前空間を分けること。
- レスポンシブ対応と prefers-reduced-motion への配慮を入れること。
- 私のサイトのフレームワーク(React / Vue / 素のHTML など)に合わせて実装すること。不明な場合は素のHTML/CSS/JSで提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。