



WithCodeMedia-1-pc
WithCodeMedia-2-pc
WithCodeMedia-3-pc
WithCodeMedia-4-pc




WithCodeMedia-1-sp
WithCodeMedia-2-sp
WithCodeMedia-3-sp
WithCodeMedia-4-sp









Webサイトのボタンやメニューをホバーしたとき、色がパッと瞬間的に切り替わるのではなく、なめらかに変化するサイトを見たことはないでしょうか。あの「ふわっと動く」感覚を実現しているのが、CSSの transition プロパティです。
transition はJavaScriptを一切使わず、CSSだけで要素の変化をアニメーション化できる非常に強力なプロパティです。2026年現在、モバイルファーストのWeb制作においてtransitionはもはや必須知識であり、ユーザー体験を大きく左右する要素となっています。
この記事では、transition の基本的な書き方から、ホバーエフェクト・ボタンアニメーション・カードのふわっと浮く演出など実用的なサンプルコードまで、コピペですぐ動くコードとともに徹底解説します。「なんとなく動いているけど仕組みがわかっていない」という方から、「timing-functionを使いこなしたい」上級者まで対応しています。
先に、この記事の結論をまとめます。
transition は property / duration / timing-function / delay の4値で構成され、変化前後に値が必要:hover などの状態変化と組み合わせることで、色・大きさ・位置などをなめらかにアニメーションできるtransition: all は手軽だが、パフォーマンスに注意が必要(個別指定が推奨)timing-function の使い分けとボタン・カードの実用パーツコードを記事内でコピペ提供transition は、CSSプロパティの値が変化するときにアニメーションを付与するプロパティです。たとえば、通常時は背景色が白いボタンが、ホバー時に青くなる場合、transition がなければ瞬間的にパッと切り替わります。transition を指定すると、その変化が指定した時間をかけてなめらかに進行します。
重要なのは、transitionはCSSプロパティの値が変わる「前の状態」と「後の状態」の両方が必要だという点です。このポイントが、あとで紹介する「効かない原因」の筆頭となります。
transition プロパティは次の4つの値で構成されます。
/* 書式 */
transition: property duration timing-function delay;
/* 例 */
transition: background-color 0.3s ease 0s;| 値 | 役割 | 省略時のデフォルト |
|---|---|---|
property | 変化させるCSSプロパティ名(all で全て) | all |
duration | 変化にかかる時間(秒/ミリ秒) | 0s |
timing-function | 変化の速度カーブ | ease |
delay | 変化が始まるまでの待機時間 | 0s |
各サブプロパティとして個別に書くこともできます。
/* 個別サブプロパティで書く方法 */
.button {
transition-property: background-color;
transition-duration: 0.3s;
transition-timing-function: ease;
transition-delay: 0s;
}最もよく使われるパターンが、:hover と組み合わせた色変化です。transition は変化の起点となる要素(通常状態)に記述します。
<!-- HTML -->
<button class="btn-color">ホバーしてね</button>/* CSS */
.btn-color {
background-color: #d16176;
color: #fff;
border: none;
padding: 12px 32px;
font-size: 16px;
border-radius: 4px;
cursor: pointer;
/* transitionは通常状態に記述 */
transition: background-color 0.3s ease;
}
.btn-color:hover {
background-color: #51322b;
}このコードをブラウザで開き、ボタンをホバーすると0.3秒かけてピンクからダークブラウンへと背景色がなめらかに変化します。
.link-animated {
color: #d16176;
text-decoration: none;
transition: color 0.2s ease;
}
.link-animated:hover {
color: #51322b;
}transform: scale() と組み合わせると、要素をなめらかに拡大縮小できます。
<!-- HTML -->
<img class="img-zoom" src="sample.jpg" alt="サンプル画像" width="300" height="200">/* CSS */
.img-zoom {
display: block;
transition: transform 0.3s ease;
}
.img-zoom:hover {
transform: scale(1.05);
}transform を使う場合、GPUレンダリングが適用されるためパフォーマンスが高く、実務で推奨されるアプローチです。
transition: all を指定すると、変化するすべてのCSSプロパティに対してアニメーションが適用されます。記述量が少なくて済みますが、意図しないプロパティにもアニメーションが付いてしまうことがあります。
/* transition: all の例 */
.card {
background-color: #fff;
color: #333;
padding: 16px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
}
.card:hover {
background-color: #EFBDB7;
color: #51322b;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
}注意点:
width や height など、アニメーションが不要なプロパティにも適用されてしまう場合があるtiming-function は、変化の「加速・減速のカーブ」を指定する値です。同じ0.3秒でも、カーブが違うと動きの印象がまったく変わります。
| 値 | 動き | 用途例 |
|---|---|---|
ease(デフォルト) | 最初ゆっくり→中間速い→最後ゆっくり | 汎用。大半のホバーエフェクトに適する |
ease-in | 最初ゆっくり→だんだん速くなる | 要素が消えていく・フェードアウト系 |
ease-out | 最初速い→だんだんゆっくりになる | 要素が飛び込んでくる・フェードイン系 |
ease-in-out | 最初と最後ゆっくり・中間速い | スライダー・モーダル開閉など滑らかな動き |
linear | 一定速度で変化 | ローディングバー・回転アニメーション |
cubic-bezier() | 自由にカーブを定義 | バウンス・オーバーシュートなど独自の動き |
steps() | パラパラ漫画のように段階的に変化 | スプライトアニメーション |
cubic-bezier(x1, y1, x2, y2) を使うと、4つのコントロールポイントで独自の速度カーブを定義できます。cubic-bezier.com というビジュアルツールで視覚的に調整できます。
/* バウンス感のある動き */
.bounce-btn {
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.bounce-btn:hover {
transform: scale(1.1);
}
/* スパッと素早く終わる動き */
.snappy-btn {
transition: background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}複数のプロパティに対して、それぞれ異なる時間やカーブを指定したい場合は、カンマ区切りで複数のtransitionを指定します。
/* 複数プロパティに個別のtransitionを指定 */
.multi-transition {
background-color: #d16176;
color: #fff;
transform: translateY(0);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
/* カンマで区切って複数指定 */
transition:
background-color 0.2s ease,
transform 0.3s ease-out,
box-shadow 0.3s ease;
}
.multi-transition:hover {
background-color: #51322b;
transform: translateY(-4px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.2);
}この例では、背景色は0.2秒・transformは0.3秒・box-shadowは0.3秒と、それぞれ異なる時間でアニメーションさせています。細かい時間差を付けることで、動きに深みが生まれます。
<!-- HTML -->
<a href="#" class="cta-button">詳しく見る</a>/* CSS */
.cta-button {
display: inline-block;
background-color: #d16176;
color: #fff;
text-decoration: none;
padding: 14px 40px;
border-radius: 30px;
font-size: 16px;
font-weight: bold;
letter-spacing: 0.05em;
transition:
background-color 0.25s ease,
transform 0.25s ease,
box-shadow 0.25s ease;
}
.cta-button:hover {
background-color: #51322b;
transform: translateY(-3px);
box-shadow: 0 8px 20px rgba(81, 50, 43, 0.3);
}<!-- HTML -->
<div class="hover-card">
<h3>カードタイトル</h3>
<p>カードの説明テキストが入ります。</p>
</div>/* CSS */
.hover-card {
background: #fff;
border-radius: 12px;
padding: 24px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
transition:
transform 0.3s ease,
box-shadow 0.3s ease;
cursor: pointer;
}
.hover-card:hover {
transform: translateY(-8px);
box-shadow: 0 16px 32px rgba(0, 0, 0, 0.15);
}下線が左から右にスライドするエフェクトです。::after 擬似要素と組み合わせます。
<!-- HTML -->
<a href="#" class="underline-link">アニメーションリンク</a>/* CSS */
.underline-link {
position: relative;
color: #d16176;
text-decoration: none;
display: inline-block;
}
.underline-link::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
width: 0;
height: 2px;
background-color: #d16176;
transition: width 0.3s ease;
}
.underline-link:hover::after {
width: 100%;
}<!-- HTML -->
<nav>
<ul class="nav-list">
<li><a href="#" class="nav-item">ホーム</a></li>
<li><a href="#" class="nav-item">サービス</a></li>
<li><a href="#" class="nav-item">会社概要</a></li>
<li><a href="#" class="nav-item">お問い合わせ</a></li>
</ul>
</nav>/* CSS */
.nav-list {
display: flex;
list-style: none;
gap: 8px;
margin: 0;
padding: 0;
}
.nav-item {
display: block;
padding: 10px 20px;
color: #51322b;
text-decoration: none;
border-radius: 4px;
background-color: transparent;
transition:
background-color 0.2s ease,
color 0.2s ease;
}
.nav-item:hover {
background-color: #EFBDB7;
color: #51322b;
}<!-- HTML -->
<input type="text" class="animated-input" placeholder="お名前を入力">/* CSS */
.animated-input {
width: 100%;
padding: 12px 16px;
border: 2px solid #ddd;
border-radius: 6px;
font-size: 16px;
outline: none;
box-sizing: border-box;
transition:
border-color 0.2s ease,
box-shadow 0.2s ease;
}
.animated-input:focus {
border-color: #d16176;
box-shadow: 0 0 0 3px rgba(209, 97, 118, 0.2);
}<!-- HTML -->
<button class="hamburger" id="hamburger">
<span class="bar"></span>
<span class="bar"></span>
<span class="bar"></span>
</button>/* CSS */
.hamburger {
background: none;
border: none;
cursor: pointer;
padding: 8px;
display: flex;
flex-direction: column;
gap: 6px;
}
.bar {
display: block;
width: 28px;
height: 3px;
background-color: #51322b;
border-radius: 2px;
transition:
transform 0.3s ease,
opacity 0.3s ease;
}
/* .open クラスが付いたときにバツ印に変化 */
.hamburger.open .bar:nth-child(1) {
transform: translateY(9px) rotate(45deg);
}
.hamburger.open .bar:nth-child(2) {
opacity: 0;
transform: scaleX(0);
}
.hamburger.open .bar:nth-child(3) {
transform: translateY(-9px) rotate(-45deg);
}transition と animation(@keyframes)はどちらもCSSアニメーションの手段ですが、用途が異なります。適切に使い分けることで、メンテナンス性の高いコードが書けます。
| 比較項目 | transition | animation(@keyframes) |
|---|---|---|
| 発火のタイミング | 状態変化(:hover, :focusなど)が必要 | ページロード時など自動再生が可能 |
| 繰り返し | 基本的に1回のみ | 無限ループ(infinite)が可能 |
| 中間点の設定 | 開始と終了の2点のみ | 0%〜100%で複数の中間点を設定可能 |
| 記述の簡便さ | シンプル(1行〜2行) | @keyframesとanimationの両方が必要 |
| 適した用途 | ホバー・フォーカス・クリック時の変化 | ローディング・常時アニメーション・複雑な動き |
まとめると、ユーザーの操作に連動した変化には transition、それ以外の自動再生・繰り返しアニメーションには animation が適しています。
/* transition が向いている例:ホバーで色が変わるボタン */
.btn {
background-color: #d16176;
transition: background-color 0.3s ease;
}
.btn:hover {
background-color: #51322b;
}
/* animation が向いている例:常にくるくる回るローディングアイコン */
.spinner {
width: 40px;
height: 40px;
border: 4px solid #EFBDB7;
border-top-color: #d16176;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}初心者がつまずきやすいポイントをまとめます。transitionが動かないときは、まずこれらを確認してください。
transitionは「A(変化前)からB(変化後)」への移行をアニメーションします。どちらかの値がなければアニメーションしません。
/* NG例:通常状態にbackground-colorがない */
.btn {
transition: background-color 0.3s ease;
/* background-colorの初期値がないため動かない場合がある */
}
.btn:hover {
background-color: #d16176;
}
/* OK例:通常状態にも値を明示する */
.btn {
background-color: transparent; /* または具体的な色 */
transition: background-color 0.3s ease;
}
.btn:hover {
background-color: #d16176;
}display: none から display: block への変化はtransitionでアニメーションできません。要素の表示・非表示のアニメーションには opacity と visibility の組み合わせを使います。
/* NG例:display:none/blockのtransitionは動かない */
.menu {
display: none;
transition: display 0.3s ease; /* 効かない */
}
.menu.open {
display: block;
}
/* OK例:opacity + visibility で代替する */
.menu {
opacity: 0;
visibility: hidden;
transition:
opacity 0.3s ease,
visibility 0.3s ease;
}
.menu.open {
opacity: 1;
visibility: visible;
}height: 0 から height: auto への変化はtransitionできません。max-height を代わりに使うか、JavaScriptでpx値を動的に取得する方法を使います。
/* NG例 */
.accordion-content {
height: 0;
overflow: hidden;
transition: height 0.3s ease; /* height:autoには効かない */
}
.accordion-content.open {
height: auto; /* 動かない */
}
/* OK例:max-heightを使う(余裕のある値を設定する) */
.accordion-content {
max-height: 0;
overflow: hidden;
transition: max-height 0.5s ease;
}
.accordion-content.open {
max-height: 500px; /* コンテンツの最大高さより大きい値 */
}transitionは通常状態の要素に書くのが基本です。:hover側に書くと、「ホバーしたとき」のアニメーションは動いても「ホバーを外したとき」はアニメーションなしで瞬間的に戻ります。
/* △ 片方向だけアニメーションする(戻りは瞬間) */
.btn {
background-color: #d16176;
}
.btn:hover {
background-color: #51322b;
transition: background-color 0.3s ease; /* ホバー時のみ効く */
}
/* OK:両方向ともなめらかにアニメーションする */
.btn {
background-color: #d16176;
transition: background-color 0.3s ease; /* 通常状態に書く */
}
.btn:hover {
background-color: #51322b;
}/* NG例:transitionなしではパッと移動するだけ */
.card {
/* transitionがない */
}
.card:hover {
transform: translateY(-8px);
}
/* OK例 */
.card {
transition: transform 0.3s ease;
}
.card:hover {
transform: translateY(-8px);
}transitionはブラウザのレンダリングパイプラインに影響します。パフォーマンスが高い順に、以下のプロパティのアニメーションが推奨されます。
| パフォーマンス | プロパティ | 理由 |
|---|---|---|
| 高い(推奨) | transform, opacity | GPUコンポジットレイヤーで処理される |
| 中程度 | color, background-color, box-shadow | ペイントが発生するが影響は小さい |
| 低い(注意) | width, height, margin, padding, top, left | レイアウト再計算(リフロー)が発生する |
要素を動かしたいときは margin や top/left ではなく transform: translate() を使いましょう。視覚的な結果は同じでも、パフォーマンスに大きな差が出ます。
/* NG例:marginのアニメーション(リフロー発生) */
.card {
margin-top: 0;
transition: margin-top 0.3s ease;
}
.card:hover {
margin-top: -8px;
}
/* OK例:transformのアニメーション(GPUで処理) */
.card {
transform: translateY(0);
transition: transform 0.3s ease;
}
.card:hover {
transform: translateY(-8px);
}will-change プロパティを使うと、ブラウザに「このプロパティがアニメーションされる予定」という事前情報を与え、処理を最適化できます。ただし、乱用するとメモリ使用量が増えるため、アニメーションが多い要素に限定して使用します。
/* transformとopacityのアニメーションを最適化 */
.animated-card {
will-change: transform, opacity;
transition: transform 0.3s ease, opacity 0.3s ease;
}
.animated-card:hover {
transform: translateY(-8px);
opacity: 0.9;
}モバイル端末ではホバー状態が発生しない(タップ)ため、ホバーエフェクトがスマホで意図せず残留する問題があります。@media (hover: hover) を使うことで、ホバーが有効な端末にだけエフェクトを適用できます。
/* ホバーが有効な環境でのみエフェクトを適用 */
@media (hover: hover) {
.btn:hover {
background-color: #51322b;
transform: translateY(-3px);
}
.card:hover {
transform: translateY(-8px);
box-shadow: 0 16px 32px rgba(0, 0, 0, 0.15);
}
}
/* transitionは常に記述(フォーカス時にも効くため) */
.btn {
background-color: #d16176;
transition: background-color 0.25s ease, transform 0.25s ease;
}
.card {
transition: transform 0.3s ease, box-shadow 0.3s ease;
}IE 10・11ではベンダープレフィックスなしで transition が使えます。ただし、IE 9以下はtransitionに対応していません。2026年現在、Microsoftは2022年にIEのサポートを終了しており、IE対応は実務上ほぼ不要になっています。主要ブラウザ(Chrome・Firefox・Safari・Edge)では完全に動作します。
transition は「変化をなめらかにする仕組み」で、transform は「要素の移動・回転・拡大縮小を指定するプロパティ」です。別々の役割を持ちます。「transformをtransitionでアニメーションする」という形で組み合わせて使います。transition単体では何も変化せず、変化させるプロパティ(colorやtransformなど)が別途必要です。
durationのデフォルト値は 0s(0秒)です。省略した場合は0秒で変化が完了するため、アニメーションなし(瞬間的な切り替わり)と同じ見た目になります。アニメーションを確認したい場合は必ずdurationを指定してください(例:0.3s)。
はい、作れます。ただし、display: none → display: block の切り替えではtransitionが効かないため、opacity と visibility の組み合わせを使います。モーダルを非表示にするとき opacity: 0; visibility: hidden;、表示するとき opacity: 1; visibility: visible; とし、両方にtransitionを設定します。表示・非表示の切り替え自体はJavaScriptでクラスの付け外しを行います。
delayは「変化が始まるまでの待機時間」です。主な活用例は、複数要素を少しずつ時間差で表示するスタガーアニメーションや、ドロップダウンメニューをホバー後0.2秒待ってから開く(誤ホバー防止)用途などです。以下の例は、リストの各アイテムを時間差で表示するパターンです。
/* 各リストアイテムに時間差でアニメーション */
.list-item {
opacity: 0;
transform: translateY(20px);
transition: opacity 0.4s ease, transform 0.4s ease;
}
.list-item.visible {
opacity: 1;
transform: translateY(0);
}
.list-item:nth-child(1) { transition-delay: 0s; }
.list-item:nth-child(2) { transition-delay: 0.1s; }
.list-item:nth-child(3) { transition-delay: 0.2s; }
.list-item:nth-child(4) { transition-delay: 0.3s; }
.list-item:nth-child(5) { transition-delay: 0.4s; }CSSの実装テクニックを「レイアウト・装飾・アニメーション・基礎・トラブル解決」の目的別に探せる総まとめページを用意しています。実装で迷ったときの索引としてどうぞ。
あわせて読みたい:CSS @keyframesの使い方|アニメーションの作り方 / CSSフェードインの実装方法|スクロールでふわっと表示

副業・フリーランスが主流になっている今こそ、自らのスキルで稼げる人材を目指してみませんか?
未経験でも心配することはありません。初級コースを受講される方の大多数はプログラミング未経験です。まずは無料カウンセリングで、悩みや不安をお聞かせください!
WithCodeでWeb制作を習得後、フリーランスエンジニアとして活動。HTML/CSS・JavaScript・WordPress案件を中心に年間20件以上の制作実績を持つ。「難しい技術をわかりやすく」をモットーに、初心者〜中級者向けの技術記事を執筆。副業・フリーランス独立を目指す方に向けた情報発信に注力している。
公式サイト より
今すぐ
無料カウンセリング
を予約!