60 FPS? Легко! pointer-events:none!

в 20:31, , рубрики: css, javascript, Веб-разработка, производительность

60 FPS? Легко! pointer events:none!

Вы, наверное, уже читали интересную статью о том, как можно отключать эффекты :hover при скроле – это позволяет здорово сохранить отзывчивость сайта, но имеет один недостаток – вам приходится опираться на один общий класс, и это плохо.

.hover .element:hover {
  box-shadow: 1px 1px 1px #000;
}


Плохо, потому что данный подход ограничивает вашу расширяемость, и вносит лишнюю спецификацию в, и без того нелегкие, селекторы CSS.

Фишка тут в том, что при скроле вы просто удаляете класс .hover с тега body, тем самым отключая все ваши селекторы с :hover-ом. После окончания события, класс возвращается, и эффекты :hover опять в деле.

Круто. Но не очень – привычное переключение глобального класса запускает немалый пересчет стилей, и это не есть гуд. Гениальное решение предложил Christian Schaefer:

60 FPS? Легко! pointer events:none!

О да, pointer-events – наше все!

Свойство pointer-events позволяет управлять условиями, при которых элементы вашей страницы будут реагировать на события мыши. Смотрите сами:

Ошеломительная разница, не так ли? И все это без лишней сложности селекторов:

.disable-hover {
  pointer-events: none;
}

Просто добавляем этот класс к нашему body по началу скрола, и все – мышь «пролетает»!

var body = document.body,
    timer;

window.addEventListener('scroll', function() {
  clearTimeout(timer);
  if(!body.classList.contains('disable-hover')) {
    body.classList.add('disable-hover')
  }
  
  timer = setTimeout(function(){
    body.classList.remove('disable-hover')
  },500);
}, false);

Код, как видите, довольно простой. Вешаем обработчик на событие скрола, в котором сперва сбрасываем предыдущий таймер, проверяем наличие класса на нашем body, и, если его нет – добавляем. Затем просто добавляем новый таймер, который, через пол секунды после окончания скрола, сбросит наш класс. Все!

Почти

Если где-то в странице будут элементы со стилем pointer-events: auto, они перетрут глобальный класс, и будут все еще тормозить. Мы же не хотим этого, верно?

.disable-hover,
.disable-hover * {
  pointer-events: none !important;
}

Как вы догадались, решение, так же, простое. Супер-селектором * с флагом !important мы научим наши элементы вести себя хорошо.

Можете убедиться в работе данного подхода. Попробуйте замерить производительность с hover-ом, и без. Результат впечатляет!

Автор: creage

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js