JINMUSOFTWARE

transitionの説明【CSS】

transitionしている図形

transitionとは

transitionプロパティは、CSSプロパティが変更されて反映されるその過渡期に対して、時間や変化速度などを設定してアニメーションを表現することができます。

本来、CSSプロパティが変更されると画面には一瞬で反映されます。

よくある例は、Twitterアイコンの上にマウスカーソルがHoverしたら、ふんわり大きくなったり、MenuButtonの上にマウスカーソルがHoverしたら色がゆっくり変わるなど、要素をアトラクティブに変化させることができます。

とても簡単でお手軽です。

ちなみに、Transitionの意味は変遷、過渡期です。

Warning!

このページは、アニメーションする表現が含まれています。拡大、縮小、回転、色の変化などです。

このページはデバイスのモーション低減の要求に対応していません。

このような表現が苦手な方はご注意頂きますようお願い致します。

関連のプロパティ

最初は1つづ理解して、そこそこ覚えたら、一括指定プロパティを使用したほうが混乱しないかなと思います。

transition関連のプロパティ

  • transition-delay: 開始待ち時間
  • transition-duration: 変化にかかる所要時間
  • transition-property: 変化させるプロパティの指定
  • transition-timing-function: 変化速度
  • transition: 一括指定

補足

変化対象のプロパティの状態がauto等の指定は相性が悪いようです。例えば、初期状態が「width: fit-content;」から「width: 100%」への変化は正常に動作しませんでした。「fit-content」では使用できないようです。数値は明確なほうが良いようです。

一括指定の「transition」からみて、それ以外のプロパティををサブプロパティと呼ぶこともあるようです。

開始から終了までの過渡期の中間状態をブラウザが勝手に計算します。このことから暗黙的トランジションと呼ばれることもあるらしいです。

transition-delay

transition-delayプロパティは、アニメーションを開始する待ち時間を設定します。

時間の指定の単位は、[s]、[ms]を使用できます。

transition-delay: 1s;

以下は、マウスカーソルがHoverすると、1秒間待機した後にアニメーションが開始されます。

≪デザインなど余計なコードは省いています≫

<div class="tdy12-1">Delay</div>
.tdy12-1 {
    height: 100px;
    width: 100px;
    background-color: skyblue;
}
.tdy12-1:hover {
    transition-delay: 1s;
    transition-duration: 1s;
    background-color: gold;
    transform: rotate(360deg);
}

Delay

どうでしょうか?1秒待機後に回転しながら金色に変わったと思います。

テキストが右にシフトしてしまう現象?

マウスポインターをHoverした瞬間、テキストが少し右にシフトする現象が発生しました。その時は、ブラウザの横幅を微調整すると収まりました。また、transform: rotate(360deg);を外したら発生しなくなりました。transformの仕様かな?

ちなみにFirefoxの場合は、下に3px位ずれました。仕様なのかな?

transition-duration

transition-durationプロパティは、アニメーションする時間を設定します。

時間の指定は、1s、1000ms、などが使用できます。

transition-duration: 1s;

さて、マウスカーソルのHoverで変化するSampleをいくつか作ってみました。

Hoverしたら配色を変更する

まずは参考に、transition-durationが設定されていない要素です。マウスをHoverするとすぐさま変化しますね。

:hover擬似クラスを使用します。

.td5:hover {
    background-color: blue;
}

backgorund-color / transition: 1s;

transition-durationを設定する

それでは、transition-durationを設定してみましょう。timeは1秒にしてみました。

.td1:hover {
    background-color: blue;
    transition: 1s;
}

backgorund-color / transition: 1s;

transition-durationを変化が戻るときにも作用させる

おっと、マウスを外した時にパッと戻ってしまいますね。戻るときにもゆっくり変化してもらいましょう。

通常時(hoverしていなとき)のプロパティにもtransition-durationを追加すれば良きですね。

.td3 {
    transition: 1s;
}
.td3:hover {
    background-color: blue;
    transition: 1s;
}

backgorund-color / transition: 1s;

どうでしょうか、hover状態が解除されるときもアニメーションされたと思います。

JavaScriptの利用

mdnのJavaScriptを使用したSampleも魅力的ですね。我々は結局、HTML、CSSときたらJavaScriptも勉強したくなってしまいますよね。

では、取り入れてみましょう。

Buttonを押すと変化します。もう一回押すと戻ります。

JavaScriptの中身は、Buttonを押すと、CSSのclassを付けたり外したりしています。

Hello!
const changeButton = document.getElementById("change23");
changeButton.addEventListener("click", () => {
    const element = document.getElementById("hello");
    element.classList.toggle("td71");
});
.td7 {
    transition-duration: 0.3s;
}
.td71 {
    background-color: coral;
    transition-duration: 1s;
}

1秒かけてアニメーションします。戻るときは少し早く、0.3秒で戻ります。進むときと戻るときで同じ秒数にする必要はありません。

classの付け外しでも、transitionが作動することを学びました。

transition-property

変化させるプロパティを指定(限定)します。そのほかのプロパティは即座に変化します。

transition-property: <target property>;

以下の例は、配色の変化は即座に変更されますが、回転だけトランジションします。

Rotate!
.tpy44-1:hover {
    transition-property: transform;
    transition-duration: 3s;
    transition-delay: 0.3s;
    background-color: gold;
    color: tan;
    border-color: orange;
    transform: rotate(360deg);
}

使用できるkeywordがあります。

  • none : すべてのプロパティでトランジションしません。
  • all : すべてのプロパティでトランジションします。(transition可能なプロパティであれば)

transition-timing-function

トラジション中の変化する加速方法を指定します。

transition-timing-function: linear;
transition-timing-function: ease-in;
transition-timing-function: steps(5, jump-start);
transition-timing-function: cubic-bezier(0.74, -0.38, 0.36, 1.38);

Ease系

linear: 線形

ease: 開始終了が遅い。中間早い

ease-in: 開始遅い。終了早い

ease-out: 開始早い。終了遅い

ease-in-out: 開始終了が遅い。中間早い

cubic-bezier: cubic-bezier(0.74, -0.38, 0.36, 1.38)

Step系

step-start

step-end

steps(5, jump-start)

steps(5, jump-end)

steps(5, jump-none)

steps(5, jump-both)

ちなみに、各要素の初期の横幅をfit-contentにするとうまく動作しません。

cubic-beizer 三次ベジェ曲線の便利なサイト

Easing Functions Cheat Sheet Easingカーブ集

transition

一括指定できるプロパティです。

一括指定 / A shorthand property

transitionプロパティを使用すると、transition-propertytransition-timing-functiontransition-durationtransition-delay、を一括で設定できます。

transition: <property> <duration> <timing-function> <delay>;

それでは、transitionプロパティを使用してみましょう。

transition: transform 1.6s cubic-bezier(0.95, 0.05, 0.795, 0.035) 1s;
ts1-1

1秒待機して回転だけ1.6秒間アニメーションします。色の変化は即座に反映。変化速度は三次ベジェ曲線を使用。

同じ秒数の設定がありますが、duration、delayの順番です。

なれてきたら一括指定が便利ですね。

複数のアニメーションを同時に設定する方法

次に複数のtransitionを設定してみましょう。

対象をカンマで区切ると複数設定できます。

次のSampleは、transformの変化を、0.5秒待機して、ease-outで2秒間変化します。と同時に、background-colorの変化を、2.5秒待機して、ease-inで1秒間変化します。

簡単に言うと、「回転後に背景色が変わる」という設定です。

各プロパティで設定する場合と、一括指定で設定する場合の、同じ動作をする2つのSampleです。

.ts1-2:hover {
    transition-property: transform, background-color;
    transition-timing-function: ease-out, ease-in;
    transition-duration: 2s, 1s;
    transition-delay: 0.5s, 2.5s;
    background-color: gold;
    transform: rotate(360deg);
}
.ts1-3:hover {
    transition: transform ease-out 2s 0.5s, background-color ease-in 1s 2.5s;
    background-color: gold;
    transform: rotate(360deg);
}
ts1-2
ts1-3

なれてきたら一括指定が便利ですね。

transition完了の検出

JavaScriptを使用して、transitionの終了を検出できます。

transition完了時に、”transitionend”イベントが発行されるので、それを捕えます。

transitionの完了を検出したタイミングでspan要素を追加する

Sampleとして、transitionの完了時に、span要素を1つ追加するコードを書いてみました。

.ted88-2:hover {
    transition: 1s;
    background-color: darksalmon;
}
const tsnElement = document.getElementById("ted88");
tsnElement.addEventListener("transitionend", () => {
    tsnElement.insertAdjacentHTML("beforeend", "<span>yah! <span>");
});
End

どうですか?

transition完了後にCSSのclassを追加する

次のSampleは、transition完了時に、色を変更する内容のclassを追加します。

transition完了時にテキスト色がWhiteに変更されます。

.ted88-2:hover {
    transition: 1s;
    background-color: darksalmon;
}
.addClass {
    transition: none !important;
    color: whitesmoke;
}
const tsnTarget1 = document.getElementById("ted89-1");
tsnTarget1.addEventListener("transitionend", () => {
    var judge = tsnTarget1.classList.contains("addClass");
    if (!judge) {
        tsnTarget1.classList.add("addClass");
    }
});
tsnTarget1.addEventListener("mouseleave", () => {
    tsnTarget1.classList.remove("addClass");
});
End

説明と言い訳

  • transitionが完了(transitionend発行)すると、”addClass”が無い場合にのみ”addClass”を追加します。
  • マウスがleaveしたら、”addClass”を削除します。
  • “addClass” は、colorプロパティで文字色を変更します。このときtransitionは”none”を強制して瞬時に変更します。
  • importantを使用した理由は、.ted88-2:hoverのほうが優勢でtransition:1sを上書きできなかったためです。
  • contains(“addClass”)のチェックはいらなかったかなと思います。後から見直すと、やっぱり、う~ん、ってことありますよね。
  • 当初、このclassを単純にtoggle()で付け替えしようとしたところ、色が変わる度にtransitionが開始され、そして”transitionend”イベントが発行されて、toggle()でまた色が変わるという、無限ループになってしまいました。
  • Loopしたい場合はそれでもいいのかもしれませんが、それはAnimationで”animation-iteration-count: infinite”を指定するのがセオリーなのかなと想像しています。
  • transition:none; のおかげでtransitionendイベントの発行が止まったと思っています。
  • 最終的に、マウスのenter(hover)でclassをaddして、マウスのleaveでclassをremoveする方法に落ち着きました。

transitionのEventとProperty

transitionの最中は、いくつかのeventとpropertyをJavaScriptで参照できます。

こちらのSmplaeは1.1秒待機後、3.4秒間回転します。

Event.

※カッコの数値はelapsedTimeです

Event名と発行タイミング

  • transitionrun: delayより前に発行。最初の最初。
  • transitionstart: delayの後に発行。アニメーションの開始の時。
  • transitionend: アニメーション終了時。
  • transitioncancel: 今回の場合は、途中でHoverが解除されたとき。

すべてTrigger的なEventのみですね。

transition実行中のEventは無いようです。ちょっと残念ですね。transition実行中のEventがあれば経過秒数の表示などできるかなと思いました。

Property関連

  • propertyName: transition対象のCSSプロパティ名。
  • elapsedTime: transition経過時間。delayは含まれない。
  • pseudoElement: 擬似要素名

transition対象のプロパティが複数あればその分だけEventが発行され、プロパティも参照できます。

Transition完了の演出

完了の検出ではないですが、transitionを2つ設定しタイミングをずらせば完了の演出ができます。

マウスをHoverしてから、3秒後にBarが緑色になります。

ttf32-1

.ttf32-1 {
    transition: width 1s;
}
.box32:hover .ttf32-1 {
    width: 100%;
    background-color: chartreuse;
    transition: width 3s ease 0s, background-color 0s linear 3s;
}

1つ目の設定は、3秒かけて横幅を100%にする設定です。

2つ目の設定は、3秒待機してから背景色を0秒で変更する設定です。

ちなみに、アニメーションが完了した状態から、マウスを素早く、leave、Enterすると、transitionは途中状態のまま順方向に進みます。ただし、所要時間は0秒から始まります。

グラデーションがtransitionしない件

グラデーションがtransitionしないとの噂を聞いたので確認してみましょう。

どうやら、background-image: linear-gradient() 等が駄目のようです。

linear-gradient()の結果は、<gradient>データ型のオブジェクトです。

ちなみに、background-color、background-image:url()などはtransition可能です。

linear-gradient()のtransitionを確認

.gra12-1{
    border: blue 3px solid;
    background-image: linear-gradient(90deg, lightblue, 80%, blue);
}
.gra12-1:hover {
    transition: 1s 0.3s;
    border: orangered 3px solid;
    background-image: linear-gradient(90deg, mistyrose, 80%, orangered);
}
gra12

あら。だめですね。

borderの色はtransitionしてくれますが、linear-gradient()のグラデーションは瞬時に変更されてしまいました。

linear-gradient()の透過率に着目

私は、ピンときました。

linear-gradient()で使用する色の透過度がtransitionされるか試してみます。

.gra14-1 {
  border: blue 3px solid;
  background-image:
   linear-gradient(90deg, rgba(173, 216, 230, 1), 80%, rgba(0, 0, 255, 1)),
   linear-gradient(90deg, rgba(255, 228, 225, 0), 80%, rgba(255, 68, 0, 0));
}
.gra14-1:hover {
  border: orangered 3px solid;
  background-image:
   linear-gradient(90deg, rgba(173, 216, 230, 0), 80%, rgba(0, 0, 255, 0)),
   linear-gradient(90deg, rgba(255, 228, 225, 1), 80%, rgba(255, 68, 0, 1));
}
gra14-1

あら、全然ダメでした。

擬似要素::beforeを重ねる

さて、他の要素を重ねて、それをtransitionして透かすことにしましょう。

擬似要素::beforeを使用してみます。

もとのdiv要素に、::beforeを重ねて透かします。

.gra13-1 {
    position: relative;
    border: gold 3px solid;
    background-image: linear-gradient(90deg, rgb(255, 247, 208), 80%, gold);
}
.gra13-1:hover::before {
    opacity: 0;
    transition: 1s 0.3s;
}
.gra13-1::before {
    transition: 0.7s;
    content: "gra13-1 before";
    position: absolute;
    left: -3px;
    top: -3px;
    border: blue 3px solid;
    background-image: linear-gradient(90deg, aliceblue, 80%, blue);
    }
gra13-1

成功しましたね。

blue➡goldに変わりました。被せていた擬似要素::beforeがtransitionしながら透明になりました。

ここでの擬似要素::beforeの注意事項がいくつかあります

  • z-indexの扱いには注意。今回はz-indexでの調整はしませんでした。
  • 擬似クラス:hoverと同時に指定するときの順番に注意。
  • 親要素(元の要素)にborder幅があると、::beforeの位置がずれる。topとleftで位置調整しました。

今回は、親要素(元要素)と::beforeの組み合わせでしたが、::afterとの組み合わせでも実現できそうですね。

div要素を被せてからtransitionしてみる

今度は、div要素を被せてみようかな。

<div class="gra15">
    <div class="gra15-1">gra15-1</div>
    <div class="gra15-2">gra15-2</div>
</div>
.gra15 {
    position: relative;
}
.gra15-1 {
    z-index: 0;
    border: gold 3px solid;
    background-image: linear-gradient(90deg, rgb(255, 247, 208), 80%, gold);
}
.gra15-2 {
    position: absolute;
    z-index: 1;
    top: 0;
    border: blue 3px solid;
    background-image: linear-gradient(90deg, aliceblue, 80%, blue);
}
.gra15-2:hover {
    opacity: 0;
    transition: 1s;
}
gra15-1
gra15-2

成功しましたね。

テキストがある場合は、同じテキストにして違和感なく背景が変わったように見せる工夫が必要ですね。

被せる用のhtmlが余計に増えてしまいますので、::beforeで実装したほうがスマートに感じますね。

要素サイズより大きい背景をグライドしてグラデーションのtransitionを実現する

情報の海を探してみると、大きい背景を用意して、表示位置を変更することで、グラデーションのtransitionを実装する方法が見つかります。

そのほか、::beforeと::afterの擬似要素で先ほどの様に、opacityをtransitionする方法も見つかりました。

では、背景の表示位置の移動でtransitionしてみましょう。

<div class="gra16">
    <div class="gra16-1">gra16-1</div>
</div>
.gra16-1 {
    transition: 0.5s;
    z-index: 0;
    padding-left: 3px;
    border-radius: 5px;
    border: gold 3px solid;
    /* background-image: linear-gradient(110deg, lightyellow, gold 50%, aquamarine 50%, lime); */
    background-image: linear-gradient(110deg, lightyellow, gold, aquamarine, lime);
    background-size: 300% 100%;
}
.gra16-1:hover {
    transition: 1.2s;
    border: lime 3px solid;
    background-position: 100% 0;
}
gra16-1

あら。なんかいい感じ。

Reference

Accessibility Concerns

  • prefers-reduced-motionユーザ設定でtransitionなどのアニメーションを最小化する設定をしているかを検出する

transform関連のCSSプロパティなど

transition関連のCSSプロパティなど

transition Event

Links

CSS Transition Guide

CSS Animation Guide

css animationのほうがより細かい動作を定義できる

Gradation

関連記事