Анна Селезнёва, Evil Martians
The Rolling Scopes Conference, 10 – 11 февраля 2018, Минск
Меня зовут Аня, и я марсианка
Я разносторонний человек
15px
В Windows:
17px
16px
15px
* – в последних версиях
const outer = document.createElement('div');
const inner = document.createElement('div');
outer.style.overflow = 'scroll';
document.body.appendChild(outer);
outer.appendChild(inner);
const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;
document.body.removeChild(outer);
html {
overflow-y: scroll;
}
scrollbar-button
scrollbar-track
scrollbar-thumb
scrollbar-track-piece
scrollbar-corner + resizer
::-webkit-scrollbar
::-webkit-scrollbar-track (-piece)
::-webkit-scrollbar-thumb
::-webkit-scrollbar-button
::-webkit-scrollbar-corner
::-webkit-resizer
+ :horizontal :vertical :start :end :increment :decrement
Поддерживается:
Не поддерживается:
Запрос в Microsoft Edge был отправлен 2,5 года назад.
Задача добавлена в backlog.
Приоритет средний.
Запрос в Mozilla Firefox был отправлен 17 лет назад.
Черновики спецификации: drafts.csswg.org/css-scrollbars-1
(GitHub: github.com/w3c/csswg-drafts/labels/css-scrollbars-1)
<a href="#element">Перейти</a>
<div id="element">
...
</div>
elem.scrollIntoView(options)
Параметры:
{
block: 'start' | 'end',
behavior: 'auto' | 'instant' | 'smooth',
}
html {
scroll-behavior: smooth;
}
Пример: codepen.io/askd/full/WdXOYW
Поддерживается:
Полифил:
Слайдер из коробки
Пример: codepen.io/askd/full/aEVyZy
.container {
scroll-snap-type: mandatory;
scroll-snap-points-x: repeat(100%);
}
.slide {
scroll-snap-align: start;
}
Поддерживается:
Поддерживается частично:
В процессе:
chromestatus.com/feature/5721832506261504
Полифил:
window.addEventListener('scroll', () => {
const scrollTop = window.scrollY;
/* doSomething with scrollTop */
});
window.addEventListener('scroll', throttle(() => {
const scrollTop = window.scrollY;
/* doSomething with scrollTop */
}));
function throttle(action, wait = 1000) {
let time = Date.now();
return function() {
if ((time + wait - Date.now()) < 0) {
action();
time = Date.now();
}
}
}
function throttle(action) {
let isRunning = false;
return function() {
if (isRunning) return;
isRunning = true;
window.requestAnimationFrame(() => {
action();
isRunning = false;
});
}
}
$ npm i --save lodash.throttle
import throttle from 'lodash/throttle';
Сравнение requestAnimationFrame и lodash.throttle:
codepen.io/askd/full/RxEYOv
.water {
width: 100%;
height: calc(100% - var(--scroll));
background-color: aqua;
}
Пример: codepen.io/askd/full/PEBZJW
window.addEventListener('scroll', () => {
const scroll = window.pageYOffset /
(document.body.scrollHeight - window.innerHeight) * 100;
element.style.setProperty('--scroll', `${scroll}%`);
});
Когда доскроллили до определенного места страницы
Пример: codepen.io/askd/full/ppGQya
.element {
position: sticky;
top: 50px;
}
Место прилипания задаётся с помощью:
top, right, bottom, left
Поддерживается:
Пример от Реми Шарпа: css-smooth-sticky-demo.now.sh
window.addEventListener('scroll', () => {
const scrollTop = window.scrollY;
const offset = Math.round(scrollTop * 0.533);
wrapper.style.transform = `translateX(${offset}px)`;
/* 0.533 = tan(28deg) */
});
.parallax {
background-attachment: fixed;
background-size: cover;
}
@media (max-device-width: 1024px) {
.parallax { background-attachment: scroll; }
}
Подробнее на w3schools.com
.element {
-webkit-overflow-scrolling: touch;
}
Только для мобильных устройств
elem.addEventListener('wheel', onScroll);
Пример: codepen.io/askd/full/BJMLmM
function onScroll(event) {
const delta = -event.deltaY;
if (delta < 0 && elemHeight - delta > elem.scrollHeight - elem.scrollTop) {
elem.scrollTop = elem.scrollHeight;
return prevent(event);
}
if (delta > elem.scrollTop) {
elem.scrollTop = 0;
return prevent(event);
}
return true;
}
const prevent = (event) => {
event.preventDefault();
return false;
};
Обработчики touch и wheel событий ухудшают производительность скролла:
element.addEventListener('touchstart', e => {
/* doSomething */
});
Пассивный обработчик:
element.addEventListener('touchstart', e => {
/* doSomething */
}, { passive: true });
Подробнее (+полифил): github.com/WICG/EventListenerOptions
.element {
overscroll-behavior: contain;
}
Пример: codepen.io/askd/full/NXobXR
Поддерживается:
Подробнее: developers.google.com/.../overscroll-behavior
Аналог:
-ms-scroll-chaining: none
@keyframes progress { to { width: 100%; } }
#progress {
animation: progress 1s linear;
animation-timeline: scroll(element(#body));
}
Черновик: wicg.github.io/scroll-animations
Презентация: askd.rocks/pres/scroll