transitionのショートハンドを乱用してたらついにそのツケを支払う時が来た話

情報・技術
情報・技術

transitionプロパティって秒数を設定するだけでなんにでもアニメーションCSS化することができるから便利だよね、ってことで文字通りなんにでも「transition: ◯s;」を設置してたら想定してない現象が起きて痛い目を見ました。

それはどういった現象かというと、親要素にhoverをトリガーにしたopacityとvisibility用transitionを設置して、子要素にhoverをトリガーにしたbackground-color用transitionを設置したときに、visibilityがhiddenのはずなのにしばらくのあいだ要素がある扱いされてしまうというものです。

<ul id="hoge">
  <li>hoge1
    <ul>
      <li>hoge1-1</li>
      <li>hoge1-2</li>
    </ul>
  </li>
  <li>hoge2</li>
</ul>


<style>
#hoge ul {
  visibility: hidden;
  opacity: 0;
  transition: 0.3s;
}
#hoge > li:hover ul {
  visibility: visible;
  opacity: 1;
  transition: 0.3s;
}
#hoge ul li {
  background-color: #aaa;
  transition: 0.3s;
}
#hoge ul li:hover {
  background-color: #ff0;
  transition: 0.3s;
}
</style>

見ての通り、子要素からマウスカーソルが完全に離れているにも関わらず、表示はされていないけど存在はしているという謎の現象です。

これ、ユーザーからすると地味にストレスなので要修正案件です。

どうやら子要素に指定したtransition-duration値が親要素に伝播して加算されているっぽい。いやいや、んなことあるかいな!なんのためのカスケーディングやねん!と思いましたが、こちらのサイトでドンピシャの現象と解決策が提示されていました。

CSSアニメーション(transition)で起こるバブリングの原因と対策 | UNORTHODOX WORKBOOK | Blog
...

webkit系に見られるバグらしく、実際にFirefoxやEdgeで開くと問題なく動きました。欠陥だからしょうがないねって気もしますが、とはいえ、なんでもかんでもtransition-property値を初期値のallで運用しまくってるのがそもそもの間違いで、どう考えてもどのプロパティに適用させるかはキチンと指定したほうがいいに決まってます。(管理面でもどういう意図で設置したのかわかるしね)

ちなみにちゃんと指定すると下のように残像(?)がなくなります。

<ul id="hoge">
  <li>hoge1
    <ul>
      <li>hoge1-1</li>
      <li>hoge1-2</li>
    </ul>
  </li>
  <li>hoge2</li>
</ul>


<style>
#hoge ul {
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.3s, visibility 0.3s;
}
#hoge > li:hover ul {
  visibility: visible;
  opacity: 1;
  transition: opacity 0.3s, visibility 0.3s;
}
#hoge ul li {
  background-color: #aaa;
  transition:  background 0.3s;
}
#hoge ul li:hover {
  background-color: #ff0;
  transition:  background 0.3s;
}
</style>

ということで、全ページに実装しているtransitionを全て修正することになりました。トホホ。
これに限らず、プロパティを指定すべきところはちゃんと指定しましょうね、という話でした。

おしまい。

コメント

タイトルとURLをコピーしました