「癒し」を表現する
ゆらぎ・呼吸・浮遊。見ている人の緊張をほどく、ゆっくりと繊細な動きの表現テクニック。
このページについて
- 「癒しの表現」とは:長い周期・小さな振幅・低彩度を組み合わせ、生体リズム(呼吸・ゆらぎ)に寄り添う動きで安心感を作る表現。「動いていることに気づかないほど穏やか」が品質の目安。
- こんな時に使う:スパ・サロン・ヨガ/瞑想アプリ・ヘルスケア・カウンセリング・寝具/アロマ系EC・お寺/神社サイト。
- 関連タグ:🌊 海🌺 温かみ🌳 木漏れ日🏥 ヘルスケア・医療
- AIへの伝え方のコツ:「癒し系で」では伝わらない。「周期7秒以上」「振幅±5px」「ease-in-out」「パステル低彩度」のように、ゆっくり・小さく・淡くを数値で指定すると意図通りになる。
表現の引き出し
🎨 呼吸するグラデーション
📝 表現の語彙
💬 AIへの指示テンプレ
🎯 似合うシーン
瞑想/マインドフルネスアプリ・スパ・ヨガスタジオ・カウンセリング・睡眠系サービス
🔧 実装手法
非対称な呼吸リズムの@keyframes(吸う4s/キープ2s/吐く6s)+ 異周期の色レイヤー重ね(12s/19s/23s/29s)+ 低彩度パステル
📄 コード例を見る
<div class="breath-stage">
<div class="breath-layer"></div>
<div class="hue-layer"></div>
<div class="soft-orb orb-a"></div>
<div class="soft-orb orb-b"></div>
<div class="soft-orb orb-c"></div>
</div>.breath-stage {
position: relative;
height: 180px;
border-radius: 8px;
overflow: hidden;
/* 低彩度パステル(薄ラベンダー→薄青→薄緑) */
background: linear-gradient(160deg, #e8e3f4 0%, #dce9f0 50%, #e5efe4 100%);
}
/* 呼吸レイヤー:中央やや上が明るい光が12秒周期で明滅 */
.breath-layer {
position: absolute;
inset: 0;
background: radial-gradient(circle at 50% 35%,
rgba(255, 253, 245, 0.5) 0%, rgba(255, 253, 245, 0) 70%);
animation: breathe 12s ease-in-out infinite;
}
/* 対称のsin波にしない:吸う4秒→止める2秒→吐く6秒(4-7-8呼吸法に近い非対称リズム) */
@keyframes breathe {
0% { opacity: 0; } /* 吐き切った状態 */
33% { opacity: 1; } /* 4秒かけて吸う */
50% { opacity: 1; } /* 2秒キープ */
100% { opacity: 0; } /* 6秒かけて吐く */
}
/* 色相の移ろい:周期19秒の薄桃レイヤー。12秒とのズレで重なりが毎回変わり、単調にならない */
.hue-layer {
position: absolute;
inset: 0;
background: radial-gradient(circle at 72% 78%,
rgba(244, 219, 231, 0.3) 0%, rgba(244, 219, 231, 0) 65%);
animation: hueDrift 19s ease-in-out infinite;
}
@keyframes hueDrift {
0%, 100% { opacity: 0.15; }
50% { opacity: 1; }
}
/* 微かな光の玉:ほぼ気づかない動きが「生きている」気配を作る */
.soft-orb {
position: absolute;
border-radius: 9999px;
background: #fffdf5;
filter: blur(25px);
}
.orb-a { top: 28px; left: 16%; width: 64px; height: 64px; opacity: .22;
animation: orbDrift 23s ease-in-out infinite alternate; }
.orb-b { top: 92px; left: 64%; width: 46px; height: 46px; opacity: .18;
animation: orbDrift 29s ease-in-out infinite alternate-reverse; }
.orb-c { top: 58px; left: 42%; width: 70px; height: 70px; opacity: .15;
animation: orbDrift 26s ease-in-out infinite alternate; animation-delay: -9s; }
@keyframes orbDrift {
from { transform: translate(0, 0); }
to { transform: translate(14px, -10px); }
}
@media (prefers-reduced-motion: reduce) {
.breath-layer, .hue-layer, .soft-orb { animation: none; }
}🎨 浮遊する光の玉
📝 表現の語彙
💬 AIへの指示テンプレ
🎯 似合うシーン
ナイトイベント・ウェディング・アロマ/キャンドル系EC・ホテル・記念日サービス
🔧 実装手法
radial-gradientの無輪郭光球 + blur/opacityによる被写界深度 + 縦・横・明滅の3軸独立周期の合成
📄 コード例を見る
// 光の玉7個。擬似乱数((i * 7919) % 100 方式)で個体差をつける
const FIREFLY_COLORS = [
[255, 251, 235], [254, 243, 199], [253, 246, 227], [255, 255, 255],
];
const orbs = Array.from({ length: 7 }, (_, i) => {
const j1 = ((i * 7919) % 100) / 100;
const j2 = ((i * 104729) % 100) / 100;
const size = 8 + j1 * 48; // 8〜56px
const [r, g, b] = FIREFLY_COLORS[i % 4];
return {
size,
left: 8 + ((i * 37) % 78), // % 不等間隔
top: 14 + ((i * 53) % 58), // %
blur: 2 + (size / 56) * 14, // 大きいほどボケる(手前のボケ)
base: 0.9 - (size / 56) * 0.55, // 大きいほど薄い(被写界深度)
bg: `radial-gradient(circle, rgba(${r},${g},${b},0.9) 0%,
rgba(${r},${g},${b},0.4) 40%, rgba(${r},${g},${b},0) 70%)`,
driftY: 11 + j1 * 12, // 縦の漂い 11〜23s
driftX: 7 + j2 * 12, // 横の漂い 7〜19s(縦と必ず違う周期)
twinkle: 5 + j1 * 8, // 明滅 5〜13s
delay: -(j2 * 20),
};
});
<div className="firefly-stage">
{orbs.map((o, i) => (
// 縦・横・明滅を別レイヤーに分けて3軸を独立合成(機械感の排除)
<div key={i} className="orb-y"
style={{ left: `${o.left}%`, top: `${o.top}%`,
animationDuration: `${o.driftY}s`, animationDelay: `${o.delay}s` }}>
<div className="orb-x"
style={{ animationDuration: `${o.driftX}s`, animationDelay: `${o.delay / 2}s` }}>
<div className="orb"
style={{ width: o.size, height: o.size, background: o.bg,
filter: `blur(${o.blur}px)`, "--base": o.base,
animationDuration: `${o.twinkle}s` }} />
</div>
</div>
))}
</div>.firefly-stage {
position: relative;
height: 180px;
border-radius: 8px;
overflow: hidden;
/* 夜の青灰。真っ黒にしない柔らかい夜 */
background: linear-gradient(180deg, #1e2a3a 0%, #2d3e50 60%, #3a4a5c 100%);
}
.orb-y { position: absolute; animation: floatY 15s ease-in-out infinite; }
.orb-x { animation: floatX 11s ease-in-out infinite; }
/* 輪郭のない、中心から溶けるような光(radial-gradientで作る) */
.orb {
border-radius: 9999px;
animation: orbTwinkle 7s ease-in-out infinite;
}
@keyframes floatY {
0%, 100% { transform: translateY(-12px); }
50% { transform: translateY(12px); }
}
@keyframes floatX {
0%, 100% { transform: translateX(-18px); }
50% { transform: translateX(18px); }
}
/* 明滅は基準値の±30%でゆっくり */
@keyframes orbTwinkle {
0%, 100% { opacity: calc(var(--base) * 0.7); }
50% { opacity: var(--base); }
}
@media (prefers-reduced-motion: reduce) {
.orb-y, .orb-x, .orb { animation: none; }
}🎨 ゆれる植物
📝 表現の語彙
💬 AIへの指示テンプレ
🎯 似合うシーン
オーガニック系EC・ハーブ/茶葉ブランド・ナチュラル系サロン・園芸・環境系NPO
🔧 実装手法
SVG pathの2段rotate(茎全体+上半分の位相差)によるしなり + animation-delayの順次ズラしで風の波 + 茎の反り・葉の数/向き/大きさを個体ごとに変えて不揃いな群生に
📄 コード例を見る
// 草6本。高さ・色・周期に加え、茎の反り(bend)と葉の数/位置/向き/大きさ(leaves)を
// 個体ごとにバラして不揃いな群生にする。delayは左→右へ順にズラす(風の波)
const plants = [
{ x: 56, h: 104, color: "#8fa882", sw: 2.6, dur: 7, delay: 0, bend: 1, bud: false,
leaves: [{ t: 0.42, side: 1, size: 1 }, { t: 0.7, side: -1, size: 0.75 }] },
{ x: 116, h: 142, color: "#7d9471", sw: 3, dur: 8.5, delay: -0.6, bend: -0.7, bud: true,
leaves: [{ t: 0.55, side: -1, size: 0.9 }] },
{ x: 172, h: 88, color: "#a4b594", sw: 2.2, dur: 6, delay: -1.1, bend: 1.3, bud: false,
leaves: [{ t: 0.35, side: -1, size: 0.85 }, { t: 0.6, side: 1, size: 1.05 }, { t: 0.82, side: -1, size: 0.55 }] },
// ...(草ごとに葉の数1〜3枚・左右の向き・大きさ・茎の反り方を変える)
];
// 茎上の点(始点を原点とした2次ベジェ)と、その点から左右に開く葉のパス
const stemPoint = (p1, p2, u) => {
const m = 1 - u;
return { x: 2 * m * u * p1.x + u * u * p2.x, y: 2 * m * u * p1.y + u * u * p2.y };
};
const leafPath = (o, side, s) =>
`M${o.x},${o.y} Q${o.x + side*9*s},${o.y-7*s} ${o.x + side*13*s},${o.y-17*s}` +
` Q${o.x + side*4*s},${o.y-10*s} ${o.x},${o.y} Z`;
<svg viewBox="0 0 420 180" width={420} height={180}>
{plants.map((p) => {
const half = p.h * 0.5;
// 茎の反り(bend)で制御点を左右に振る → 草ごとにS字の曲がり方が変わる
const lP1 = { x: 4 * p.bend, y: -half * 0.6 }, lTip = { x: p.bend, y: -half };
const uP1 = { x: -4 * p.bend, y: -half * 0.5 }, uTip = { x: -1.5 * p.bend, y: -half };
return (
<g key={p.x} transform={`translate(${p.x},174)`}>
{/* 茎全体:根元支点の rotate ±2.5deg */}
<g className="stem" style={{ "--dur": `${p.dur}s`, "--delay": `${p.delay}s` }}>
<path d={`M0,0 Q${lP1.x},${lP1.y} ${lTip.x},${lTip.y}`}
stroke={p.color} strokeWidth={p.sw} fill="none" strokeLinecap="round" />
{/* 下半分の葉:根元側の茎と一緒に揺れる */}
{p.leaves.filter((l) => l.t < 0.5).map((l, i) => (
<path key={i} d={leafPath(stemPoint(lP1, lTip, l.t / 0.5), l.side, l.size)}
fill={p.color} opacity={0.85} />
))}
<g transform={`translate(${lTip.x},${lTip.y})`}>
{/* 茎の上半分:わずかに遅れた位相で追加のrotate(しなり) */}
<g className="stem-upper">
<path d={`M0,0 Q${uP1.x},${uP1.y} ${uTip.x},${uTip.y}`}
stroke={p.color} strokeWidth={p.sw * 0.6} fill="none" strokeLinecap="round" />
{/* 上半分の葉:先端のしなりに遅れてついてくる */}
{p.leaves.filter((l) => l.t >= 0.5).map((l, i) => (
<path key={i} d={leafPath(stemPoint(uP1, uTip, (l.t - 0.5) / 0.5), l.side, l.size)}
fill={p.color} opacity={0.85} />
))}
{p.bud && <circle cx={uTip.x} cy={uTip.y - 2.5} r={3.5} fill="#d9c2cc" />}
</g>
</g>
</g>
</g>
);
})}
</svg>.meadow-stage {
position: relative;
height: 180px;
border-radius: 8px;
overflow: hidden;
/* 生成り→薄抹茶。和の余白感 */
background: linear-gradient(180deg, #f7f4ed 0%, #eef0e4 100%);
}
.meadow-ground {
position: absolute;
bottom: 0; left: 0; right: 0;
height: 8px;
background: #e3e6d6;
}
/* 茎全体:根元固定で ±2.5deg */
.stem {
transform-box: fill-box;
transform-origin: bottom center;
animation: sway var(--dur) ease-in-out infinite;
animation-delay: var(--delay);
}
/* 上半分:-0.4s 遅れた位相で ±1.5deg を重ねる → 根元が動いてから先端が遅れてついてくる */
.stem-upper {
transform-box: fill-box;
transform-origin: bottom center;
animation: swayUpper var(--dur) ease-in-out infinite;
animation-delay: calc(var(--delay) - 0.4s);
}
@keyframes sway {
0%, 100% { transform: rotate(-2.5deg); }
50% { transform: rotate(2.5deg); }
}
@keyframes swayUpper {
0%, 100% { transform: rotate(-1.5deg); }
50% { transform: rotate(1.5deg); }
}
/* 花粉・胞子の気配(小さな光の粒がごくゆっくり漂う) */
.pollen {
position: absolute;
border-radius: 9999px;
background: #fffdf0;
filter: blur(1px);
animation: pollenDrift 21s ease-in-out infinite alternate;
}
@keyframes pollenDrift {
from { transform: translate(0, 0); }
to { transform: translate(12px, -14px); }
}
@media (prefers-reduced-motion: reduce) {
.stem, .stem-upper, .pollen { animation: none; }
}🎨 水面の波紋
📝 表現の語彙
💬 AIへの指示テンプレ
🎯 似合うシーン
温泉/旅館・茶道/和文化・スパ・瞑想・サウンドセラピー・日本酒ブランド
🔧 実装手法
同心円3本組のease-out拡大 + 多地点・異周期のランダム発生 + 背景の微細な明度ゆらぎ(周期17s)
📄 コード例を見る
// 波紋の発生点5箇所。周期6〜14sでバラし「いつどこに落ちるか分からない」リズム
const ripples = [
{ left: "22%", top: "38%", cycle: 6, delay: -2 },
{ left: "68%", top: "26%", cycle: 8.5, delay: -5 },
{ left: "45%", top: "64%", cycle: 11, delay: -1 },
{ left: "84%", top: "70%", cycle: 14, delay: -8 },
{ left: "12%", top: "76%", cycle: 9.5, delay: -6.5 },
];
<div className="pond-stage">
<div className="light-band" /> {/* 静止した光の帯(水面の質感) */}
<div className="pond-shimmer" /> {/* 水面の微動(周期17sの明度ゆらぎ) */}
{ripples.map((r, i) => (
<div key={i} className="ripple-point" style={{ left: r.left, top: r.top }}>
{/* 雫の気配:波紋の直前に小さな白い点が一瞬現れる */}
<div className="drop"
style={{ animationDuration: `${r.cycle}s`, animationDelay: `${r.delay}s` }} />
{/* 1本の輪ではなく、0.25秒差で広がる同心円3本組 */}
{[0, 1, 2].map((n) => (
<div key={n} className="ripple-ring"
style={{ animationDuration: `${r.cycle}s`,
animationDelay: `${r.delay + 0.3 + n * 0.25}s` }} />
))}
</div>
))}
</div>.pond-stage {
position: relative;
height: 180px;
border-radius: 8px;
overflow: hidden;
/* 青磁色の静かな水面 */
background: linear-gradient(165deg, #dce8e8 0%, #c5d8d4 50%, #b2c9c4 100%);
}
.light-band {
position: absolute;
inset: 0;
background: linear-gradient(115deg,
rgba(255,255,255,0) 30%, rgba(255,255,255,0.2) 46%, rgba(255,255,255,0) 60%);
}
/* 完全静止だと「画像」に見えるため、ごくわずかな明度のゆらぎを入れる */
.pond-shimmer {
position: absolute;
inset: 0;
background: radial-gradient(circle at 60% 40%,
rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 70%);
animation: shimmer 17s ease-in-out infinite;
}
@keyframes shimmer {
0%, 100% { opacity: 0.02; }
50% { opacity: 0.07; }
}
.ripple-point { position: absolute; }
.ripple-ring {
position: absolute;
top: 0; left: 0;
border: 1.5px solid rgba(255, 255, 255, 0.55);
border-radius: 9999px;
transform: translate(-50%, -50%);
opacity: 0;
/* ease-out が重要:波紋は最初速く、徐々に減速して消える(物理的に正しい) */
animation: rippleExpand 9s ease-out infinite;
}
/* 拡大は周期の先頭35%で完了し、残りは静寂。線は広がるほど細く・薄く */
@keyframes rippleExpand {
0% { width: 0; height: 0; opacity: 0; border-width: 2.5px; }
2% { opacity: 0.8; }
35% { width: 130px; height: 130px; opacity: 0; border-width: 0.5px; }
100% { width: 130px; height: 130px; opacity: 0; border-width: 0.5px; }
}
.drop {
position: absolute;
width: 3px; height: 3px;
border-radius: 9999px;
background: #ffffff;
transform: translate(-50%, -50%);
opacity: 0;
animation: dropHint 9s linear infinite;
}
@keyframes dropHint {
0% { opacity: 0; }
1% { opacity: 0.9; }
3% { opacity: 0; }
100% { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
.pond-shimmer, .ripple-ring, .drop { animation: none; }
}よくある質問
癒し系の動きで一番やりがちな失敗は?
「速すぎる・大きすぎる」こと。一般的なUIアニメーション(0.3s〜1s)の感覚で作ると、癒しではなく「賑やか」になります。周期は最低4秒以上、移動は±10px以内、と意識的に1桁遅く・小さくするのがコツです。「動いていることに気づかれないくらい」がちょうどいい目安です。
ゆっくりした動きはユーザーを待たせない?
待たせません。本ページの表現はすべて「環境装飾」であり、コンテンツの表示やインタラクションをブロックしません。読み込み完了を待つスピナーとは役割が違うので、ゆっくりでも問題ありません。むしろ操作の邪魔をしない控えめさが大切です。
癒し表現とパフォーマンスの両立は?
transform と opacity のみを使えば、長周期アニメーションの負荷はごく小さいです。blurは要素数が多いと重くなるため、blur要素は5〜8個程度に抑えます。また「画面外では停止」(Intersection Observer)を入れると、長いページでも安心です。
AIに「癒し系のサイト」を頼むと派手になってしまう
「癒し」という言葉はAIにとって解釈の幅が広すぎます。本ページの各カードにある数値(周期12秒・振幅±10px・低彩度パステル・ease-in-out)をそのまま指示に含めると、意図の精度が大きく上がります。表現名(呼吸するグラデーション・波紋)で指定するのも有効です。
同じカテゴリの他のページ
「疾走感」をWebで表現する - 演出パターンとAIプロンプト | UI Memo
車・スポーツ・配達などのWebサイトで疾走感を演出する具体的な表現テクニック4選。左右に動く・流れる風景・スピードライン・タイヤ回転の実装デモとAIへの指示プロンプト付き。
「温かみ」をWebで表現する - 灯り・木質・陽だまりの演出パターンとAIプロンプト | UI Memo
温かみのある雰囲気をWebサイトで演出する表現テクニック4選。揺れる灯火・木のぬくもり・陽だまり・湯気と湯のみの実装デモとコード、AIへの指示プロンプト付き。カフェ・ぬくもり系ブランドに。
「清涼感」をWebで表現する - 結露・水面・氷・涼風の演出パターンとAIプロンプト | UI Memo
清涼感のある涼しげな雰囲気をWebサイトで演出する表現テクニック4選。結露のグラス・水面のコースティクス・氷のきらめき・涼風の実装デモとコード、AIへの指示プロンプト付き。夏・飲料・空調・清涼系ブランドに。