2017/05/23

Sortable.jsでD&Dしたときに:hoverのスタイルが残るバグの対処法

jQuery不要でドラッグ&ドロップで要素の並べ替えができるSortable.jsを使っていたのだが、Chromeで不可解なバグを見つけてしまったのでその対処法をまとめる。(※詳しくは後述するがSortable.jsのバグではない)

要素をD&Dしたときに:hoverのスタイルが残るバグ


言葉で説明してもわかりにくいと思うので、下のGifアニメーションを見てほしい。
「要素2」をドラッグし、「要素1」にドロップしたときに、本来hoverスタイルが適用されないはずの「要素1」に対してスタイルが適用されてしまうバグだ。


これはChromeのバグだ。そのため、Sortable.jsを使っていなくても再現する
詳しくは、以下のIssueを確認してほしい。
Native drag & drop triggering :hover pseudo-class on surrounding elements



解決策: :hoverを使わない


当バグの解決策は単純で、バグの原因である:hoverを使わなければいい。
<ul id="bug">
  <li class="item">1</li>
  <li class="item">2</li>
  <li class="item">3</li>
</ul>

<ul id="solution">
  <li class="item">1'</li>
  <li class="item">2'</li>
  <li class="item">3'</li>
</ul>

ul { float: left; }
.item {
  width: 100px;
  height: 100px;
  color: white;
  background-color: black;
  text-align: center;
  line-height: 100px;
  border: 1px solid white;
}
/* :hoverのスタイルが残る */
#bug > .item {
  background-color: red;
}
#bug > .item:hover {
  opacity: .5;
}

/* :hoverを使わない */
#solution > .item {
  background-color: blue;
}
#solution > .item.-hover {
  opacity: .5;
}

const bug = document.getElementById('bug');
Sortable.create(bug);

const solution = document.getElementById('solution');
Sortable.create(solution);

// hoverの代わりにmouseenter, mouseleaveイベントでスタイルを適用する
[...solution.children].forEach(child => {
  child.addEventListener('mouseenter', event => {
    event.target.classList.add('-hover');
  });
  child.addEventListener('mouseleave', event => {
    event.target.classList.remove('-hover');
  });
});

このようにmouseenter、mouseleaveイベントをつかってhover用のクラスを追加/削除することで、バグを回避しつつ、hoverエフェクトを表現することができる。




以上

written by @bc_rikko

0 件のコメント :

コメントを投稿