昼夜トグル
クリックすると太陽と月が弧を描いて移動し、空の背景色が昼と夜のあいだをなめらかに遷移するトグル。雲の漂いや星の瞬きも添えました。
ライブデモ
コード
HTML
<!-- 昼夜トグル: 太陽と月が弧を描いて移動し、空の背景色が昼と夜のあいだを遷移するトグル -->
<div class="stage">
<button class="day-night" type="button" role="switch" aria-checked="false" aria-label="昼と夜を切り替える">
<span class="day-night__sky day-night__sky--day" aria-hidden="true"></span>
<span class="day-night__sky day-night__sky--night" aria-hidden="true"></span>
<span class="day-night__stars" aria-hidden="true">
<span></span><span></span><span></span><span></span><span></span><span></span>
</span>
<span class="day-night__clouds" aria-hidden="true">
<span class="day-night__cloud day-night__cloud--a"></span>
<span class="day-night__cloud day-night__cloud--b"></span>
</span>
<span class="day-night__ground" aria-hidden="true"></span>
<span class="day-night__celestial" aria-hidden="true">
<span class="day-night__sun"></span>
<span class="day-night__moon"></span>
</span>
</button>
<p class="day-night__status" aria-hidden="true">☀️ 昼</p>
<p class="hint">クリックすると昼と夜が入れ替わります</p>
</div>
CSS
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
overflow: hidden;
display: grid;
place-items: center;
font-family: "Segoe UI", system-ui, sans-serif;
background: radial-gradient(circle at 50% 30%, #161329 0%, #0d0e1a 72%);
color: #f4f5fb;
}
.stage { display: grid; place-items: center; gap: 14px; padding: 20px; }
.day-night {
position: relative;
width: min(78vw, 240px);
height: 130px;
border: none;
border-radius: 26px;
cursor: pointer;
overflow: hidden;
padding: 0;
-webkit-tap-highlight-color: transparent;
box-shadow: 0 16px 32px rgba(0, 0, 0, .5);
}
.day-night:focus-visible { outline: 2px solid #ffd166; outline-offset: 4px; }
/* 空(昼/夜)はopacityのクロスフェードで色を遷移させる */
.day-night__sky {
position: absolute;
inset: 0;
transition: opacity .9s ease;
}
.day-night__sky--day {
background: linear-gradient(180deg, #7ec8f2 0%, #bfe4ff 65%, #eaf6ff 100%);
opacity: 1;
}
.day-night__sky--night {
background: linear-gradient(180deg, #0b1026 0%, #1b2560 65%, #232d6e 100%);
opacity: 0;
}
.day-night[aria-checked="true"] .day-night__sky--day { opacity: 0; }
.day-night[aria-checked="true"] .day-night__sky--night { opacity: 1; }
/* 星: 夜のみ表示。個々にまたたきの時間差をつける */
.day-night__stars {
position: absolute;
inset: 0;
opacity: 0;
transition: opacity .9s ease;
}
.day-night[aria-checked="true"] .day-night__stars { opacity: 1; }
.day-night__stars span {
position: absolute;
width: 3px;
height: 3px;
border-radius: 50%;
background: #fff;
animation: star-twinkle 2.4s ease-in-out infinite;
}
.day-night__stars span:nth-child(1) { top: 18%; left: 14%; animation-delay: 0s; }
.day-night__stars span:nth-child(2) { top: 32%; left: 32%; animation-delay: .3s; }
.day-night__stars span:nth-child(3) { top: 14%; left: 52%; animation-delay: .9s; }
.day-night__stars span:nth-child(4) { top: 28%; left: 74%; animation-delay: .5s; }
.day-night__stars span:nth-child(5) { top: 44%; left: 60%; animation-delay: 1.2s; }
.day-night__stars span:nth-child(6) { top: 12%; left: 88%; animation-delay: 1.6s; }
@keyframes star-twinkle {
0%, 100% { opacity: .25; transform: scale(.8); }
50% { opacity: 1; transform: scale(1.15); }
}
/* 雲: 昼のみ表示し、常にゆっくり漂う(一覧カードでも生きて見えるアイドル演出) */
.day-night__clouds {
position: absolute;
inset: 0;
opacity: 1;
transition: opacity .9s ease;
}
.day-night[aria-checked="true"] .day-night__clouds { opacity: 0; }
.day-night__cloud {
position: absolute;
height: 14px;
border-radius: 999px;
background: rgba(255, 255, 255, .85);
box-shadow:
12px -6px 0 -1px rgba(255, 255, 255, .85),
-10px -3px 0 -2px rgba(255, 255, 255, .7);
}
.day-night__cloud--a { top: 24%; left: -30%; width: 44px; animation: cloud-drift 13s linear infinite; }
.day-night__cloud--b { top: 46%; left: -46%; width: 34px; animation: cloud-drift 18s linear infinite 3s; }
@keyframes cloud-drift {
0% { transform: translateX(0); }
100% { transform: translateX(340px); }
}
.day-night__ground {
position: absolute;
left: -12%;
right: -12%;
bottom: -30px;
height: 58px;
background: #142036;
border-radius: 50%;
opacity: .92;
}
/* 太陽/月の本体。leftの移動+is-arcing時の弧を描くtranslateYで昇降させる */
.day-night__celestial {
position: absolute;
left: 12%;
bottom: 26px;
width: 34px;
height: 34px;
transition: left 1.05s cubic-bezier(.34, 1.56, .64, 1);
}
.day-night[aria-checked="true"] .day-night__celestial { left: calc(88% - 34px); }
.day-night__celestial.is-arcing { animation: celestial-arc 1.05s cubic-bezier(.34, 1.56, .64, 1); }
@keyframes celestial-arc {
0% { transform: translateY(0); }
50% { transform: translateY(-46px); }
100% { transform: translateY(0); }
}
.day-night__sun,
.day-night__moon {
position: absolute;
inset: 0;
border-radius: 50%;
transition: opacity .9s ease, transform .9s ease;
}
.day-night__sun {
background: radial-gradient(circle at 32% 30%, #fff6da, #ffd166 55%, #ffb347 100%);
box-shadow: 0 0 22px rgba(255, 209, 102, .65);
opacity: 1;
transform: scale(1);
}
.day-night__moon {
background: radial-gradient(circle at 35% 32%, #f4f6ff, #cbd5f5 60%, #8892b0 100%);
box-shadow:
inset -4px -3px 0 1px rgba(120, 130, 170, .3),
inset 5px 6px 0 0 rgba(120, 130, 170, .22),
0 0 16px rgba(180, 190, 230, .5);
opacity: 0;
transform: scale(.6);
}
.day-night[aria-checked="true"] .day-night__sun { opacity: 0; transform: scale(.6); }
.day-night[aria-checked="true"] .day-night__moon { opacity: 1; transform: scale(1); }
.day-night__status {
margin: 0;
font-size: 14px;
font-weight: 700;
}
.hint { margin: 0; font-size: 13px; color: rgba(244, 245, 251, .5); text-align: center; }
@media (prefers-reduced-motion: reduce) {
.day-night__celestial { transition-duration: .15s; }
.day-night__celestial.is-arcing { animation: none; }
.day-night__cloud { animation: none; }
.day-night__stars span { animation: none; opacity: .8; transform: none; }
}
JavaScript
// 昼夜トグル: クリックで太陽/月が弧を描いて移動し、空の色を昼夜で入れ替える
(() => {
const btn = document.querySelector('.day-night');
const celestial = document.querySelector('.day-night__celestial');
const status = document.querySelector('.day-night__status');
if (!btn || !celestial) return; // null安全
let isNight = btn.getAttribute('aria-checked') === 'true';
const setStatus = () => {
if (status) status.textContent = isNight ? '🌙 夜' : '☀️ 昼';
};
setStatus();
btn.addEventListener('click', () => {
isNight = !isNight;
btn.setAttribute('aria-checked', String(isNight));
setStatus();
celestial.classList.remove('is-arcing');
void celestial.offsetWidth; // reflow: 連続クリックでも毎回弧を描かせる
celestial.classList.add('is-arcing');
});
celestial.addEventListener('animationend', () => {
celestial.classList.remove('is-arcing');
});
})();
🤖 AIエージェント用プロンプト
このままコピーしてAIに貼り付け「追加する場所」だけ書き換えればOK
あなたは熟練のフロントエンドエンジニアです。私のWebサイトに「昼夜トグル」の効果を追加してください。
# 追加してほしい効果
昼夜トグル(遊べるUI)
クリックすると太陽と月が弧を描いて移動し、空の背景色が昼と夜のあいだをなめらかに遷移するトグル。雲の漂いや星の瞬きも添えました。
# 追加する場所
👉【ここに対象箇所を記入:例「トップのヒーローセクション」「お問い合わせボタン」「記事カードの一覧」など】
# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- 昼夜トグル: 太陽と月が弧を描いて移動し、空の背景色が昼と夜のあいだを遷移するトグル -->
<div class="stage">
<button class="day-night" type="button" role="switch" aria-checked="false" aria-label="昼と夜を切り替える">
<span class="day-night__sky day-night__sky--day" aria-hidden="true"></span>
<span class="day-night__sky day-night__sky--night" aria-hidden="true"></span>
<span class="day-night__stars" aria-hidden="true">
<span></span><span></span><span></span><span></span><span></span><span></span>
</span>
<span class="day-night__clouds" aria-hidden="true">
<span class="day-night__cloud day-night__cloud--a"></span>
<span class="day-night__cloud day-night__cloud--b"></span>
</span>
<span class="day-night__ground" aria-hidden="true"></span>
<span class="day-night__celestial" aria-hidden="true">
<span class="day-night__sun"></span>
<span class="day-night__moon"></span>
</span>
</button>
<p class="day-night__status" aria-hidden="true">☀️ 昼</p>
<p class="hint">クリックすると昼と夜が入れ替わります</p>
</div>
【CSS】
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
overflow: hidden;
display: grid;
place-items: center;
font-family: "Segoe UI", system-ui, sans-serif;
background: radial-gradient(circle at 50% 30%, #161329 0%, #0d0e1a 72%);
color: #f4f5fb;
}
.stage { display: grid; place-items: center; gap: 14px; padding: 20px; }
.day-night {
position: relative;
width: min(78vw, 240px);
height: 130px;
border: none;
border-radius: 26px;
cursor: pointer;
overflow: hidden;
padding: 0;
-webkit-tap-highlight-color: transparent;
box-shadow: 0 16px 32px rgba(0, 0, 0, .5);
}
.day-night:focus-visible { outline: 2px solid #ffd166; outline-offset: 4px; }
/* 空(昼/夜)はopacityのクロスフェードで色を遷移させる */
.day-night__sky {
position: absolute;
inset: 0;
transition: opacity .9s ease;
}
.day-night__sky--day {
background: linear-gradient(180deg, #7ec8f2 0%, #bfe4ff 65%, #eaf6ff 100%);
opacity: 1;
}
.day-night__sky--night {
background: linear-gradient(180deg, #0b1026 0%, #1b2560 65%, #232d6e 100%);
opacity: 0;
}
.day-night[aria-checked="true"] .day-night__sky--day { opacity: 0; }
.day-night[aria-checked="true"] .day-night__sky--night { opacity: 1; }
/* 星: 夜のみ表示。個々にまたたきの時間差をつける */
.day-night__stars {
position: absolute;
inset: 0;
opacity: 0;
transition: opacity .9s ease;
}
.day-night[aria-checked="true"] .day-night__stars { opacity: 1; }
.day-night__stars span {
position: absolute;
width: 3px;
height: 3px;
border-radius: 50%;
background: #fff;
animation: star-twinkle 2.4s ease-in-out infinite;
}
.day-night__stars span:nth-child(1) { top: 18%; left: 14%; animation-delay: 0s; }
.day-night__stars span:nth-child(2) { top: 32%; left: 32%; animation-delay: .3s; }
.day-night__stars span:nth-child(3) { top: 14%; left: 52%; animation-delay: .9s; }
.day-night__stars span:nth-child(4) { top: 28%; left: 74%; animation-delay: .5s; }
.day-night__stars span:nth-child(5) { top: 44%; left: 60%; animation-delay: 1.2s; }
.day-night__stars span:nth-child(6) { top: 12%; left: 88%; animation-delay: 1.6s; }
@keyframes star-twinkle {
0%, 100% { opacity: .25; transform: scale(.8); }
50% { opacity: 1; transform: scale(1.15); }
}
/* 雲: 昼のみ表示し、常にゆっくり漂う(一覧カードでも生きて見えるアイドル演出) */
.day-night__clouds {
position: absolute;
inset: 0;
opacity: 1;
transition: opacity .9s ease;
}
.day-night[aria-checked="true"] .day-night__clouds { opacity: 0; }
.day-night__cloud {
position: absolute;
height: 14px;
border-radius: 999px;
background: rgba(255, 255, 255, .85);
box-shadow:
12px -6px 0 -1px rgba(255, 255, 255, .85),
-10px -3px 0 -2px rgba(255, 255, 255, .7);
}
.day-night__cloud--a { top: 24%; left: -30%; width: 44px; animation: cloud-drift 13s linear infinite; }
.day-night__cloud--b { top: 46%; left: -46%; width: 34px; animation: cloud-drift 18s linear infinite 3s; }
@keyframes cloud-drift {
0% { transform: translateX(0); }
100% { transform: translateX(340px); }
}
.day-night__ground {
position: absolute;
left: -12%;
right: -12%;
bottom: -30px;
height: 58px;
background: #142036;
border-radius: 50%;
opacity: .92;
}
/* 太陽/月の本体。leftの移動+is-arcing時の弧を描くtranslateYで昇降させる */
.day-night__celestial {
position: absolute;
left: 12%;
bottom: 26px;
width: 34px;
height: 34px;
transition: left 1.05s cubic-bezier(.34, 1.56, .64, 1);
}
.day-night[aria-checked="true"] .day-night__celestial { left: calc(88% - 34px); }
.day-night__celestial.is-arcing { animation: celestial-arc 1.05s cubic-bezier(.34, 1.56, .64, 1); }
@keyframes celestial-arc {
0% { transform: translateY(0); }
50% { transform: translateY(-46px); }
100% { transform: translateY(0); }
}
.day-night__sun,
.day-night__moon {
position: absolute;
inset: 0;
border-radius: 50%;
transition: opacity .9s ease, transform .9s ease;
}
.day-night__sun {
background: radial-gradient(circle at 32% 30%, #fff6da, #ffd166 55%, #ffb347 100%);
box-shadow: 0 0 22px rgba(255, 209, 102, .65);
opacity: 1;
transform: scale(1);
}
.day-night__moon {
background: radial-gradient(circle at 35% 32%, #f4f6ff, #cbd5f5 60%, #8892b0 100%);
box-shadow:
inset -4px -3px 0 1px rgba(120, 130, 170, .3),
inset 5px 6px 0 0 rgba(120, 130, 170, .22),
0 0 16px rgba(180, 190, 230, .5);
opacity: 0;
transform: scale(.6);
}
.day-night[aria-checked="true"] .day-night__sun { opacity: 0; transform: scale(.6); }
.day-night[aria-checked="true"] .day-night__moon { opacity: 1; transform: scale(1); }
.day-night__status {
margin: 0;
font-size: 14px;
font-weight: 700;
}
.hint { margin: 0; font-size: 13px; color: rgba(244, 245, 251, .5); text-align: center; }
@media (prefers-reduced-motion: reduce) {
.day-night__celestial { transition-duration: .15s; }
.day-night__celestial.is-arcing { animation: none; }
.day-night__cloud { animation: none; }
.day-night__stars span { animation: none; opacity: .8; transform: none; }
}
【JavaScript】
// 昼夜トグル: クリックで太陽/月が弧を描いて移動し、空の色を昼夜で入れ替える
(() => {
const btn = document.querySelector('.day-night');
const celestial = document.querySelector('.day-night__celestial');
const status = document.querySelector('.day-night__status');
if (!btn || !celestial) return; // null安全
let isNight = btn.getAttribute('aria-checked') === 'true';
const setStatus = () => {
if (status) status.textContent = isNight ? '🌙 夜' : '☀️ 昼';
};
setStatus();
btn.addEventListener('click', () => {
isNight = !isNight;
btn.setAttribute('aria-checked', String(isNight));
setStatus();
celestial.classList.remove('is-arcing');
void celestial.offsetWidth; // reflow: 連続クリックでも毎回弧を描かせる
celestial.classList.add('is-arcing');
});
celestial.addEventListener('animationend', () => {
celestial.classList.remove('is-arcing');
});
})();
# 外部ライブラリ
なし(追加ライブラリ不要)
# 守ってほしいこと
- 既存のHTML構造・レイアウト・デザインを壊さないこと。必要に応じてクラス名・色・サイズを私のサイトに合わせて調整してよい。
- クラス名やidが既存と衝突しないよう、必要なら接頭辞で名前空間を分けること。
- レスポンシブ対応と prefers-reduced-motion への配慮を入れること。
- 私のサイトのフレームワーク(React / Vue / 素のHTML など)に合わせて実装すること。不明な場合は素のHTML/CSS/JSで提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。