Горизонтальна прокрутка на чистому CSS

1

Від автора: стаття нашого гостя, Пітера Бизменса. Пітер – front-end розробник на сайті Audience, де він любить писати стилі на SCSS. Сьогодні він нам покаже те, що я називаю чесним CSS трюком. Весь веб має вертикальне будова. Ви читаєте сайт, як звичайну книгу: зліва направо, зверху вниз. Але іноді хочеться піти від вертикальності і зробити щось божевільне: зробити горизонтальний список. Або ще безумніше, горизонтальний сайт!

Було б непогано, якщо б ми могли робити ось так:

/* несправжній код */
div {
scroll-direction: horizontal;
}

На жаль, такого не буде. Такого навіть в планах немає в CSS.

Це дуже погано, тому що в компанії, в якій я працюю, це б дуже в нагоді. Ми робимо дуже багато презентацій, а презентація – це досить горизонтальна штука. Зазвичай співвідношення сторін у слайдів складає 4:3 або 16:9. З-за цього у нас виникає постійна проблема з горизонтальними слайдами і вертикальними веб-технологіями. Під «ми» я маю на увазі себе. Але що я люблю, так це труднощі.

Інший варіант використання

Мені в голову прийшов конкретний спосіб застосування. Ідея в тому, що покупцям було б зручно переглядати всі товари на одному слайді. Природно, каталог товарів не вмістився б в одному виді. Тому ми вирішили розбити каталог на три категорії, кожна з горизонтальною прокруткою. Таким чином, три найпопулярніших товару відображаються в кожній категорії, а до менш важливих товарів відкритий легкий доступ.

Спосіб без JavaScript

Всі ми знаємо, що на JS існує маса спосіб зробити горизонтальну прокрутку. Деякі приклади є на CSS-Tricks. Мені стало цікаво, чи можна втілити цю ідею на чистому CSS. Рішення виявилося дуже простим:

створюємо контейнер з елементами;

повертаємо контейнер на 90 градусів проти годинникової стрілки, щоб нижня грань опинилася праворуч;

повертаємо елементи всередині контейнера назад на своє місце.

Крок 1) створюємо контейнер

Створіть блок div з безліччю дочірніх елементів.

У нашому прикладі прокручується контейнер буде 300px шириною, в ньому буде 8 елементів 100х100рх. Розміри довільні, можна задати будь-які.

item 1
item 2
item 3
item 4
item 5
item 6
item 7
item 8

Висота контейнера стане шириною і навпаки. Нижче ширина контейнера буде становити 300px:

.horizontal-scroll-wrapper {
width: 100px;
height: 300px;
overflow-y: auto;
overflow-x: hidden;
}

Та дочірні елементи:

.horizontal-scroll-wrapper > div {
width: 100px;
height: 100px;
}

Крок 2) контейнер повертаємо

Тепер потрібно повернути контейнер на -90 градусів за допомогою CSS властивості transform. Ми отримали горизонтальний скроллер.

.horizontal-scroll-wrapper {

transform: rotate(-90deg);
transform-origin: top right;
}

Тільки є одна маленька проблема: дочірні елементи повернулися разом з контейнером.

Крок 3) повертаємо дочірні елементи назад на своє місце

Так як же повернути елементи на своє місце? Поверніть його назад за допомогою CSS властивості transform.

.horizontal-scroll-wrapper > div {

transform: rotate(90deg);
transform-origin: top right;
}

Крок 4) фіксоване позиціонування

Виглядає все непогано, але є кілька проблем.

Ми повернули контейнер, а в якості якоря поставили правий верхній кут, з-за цього ліва сторона змістилася на ширину контейнера. Якщо вам складно уявити, просто додайте палець до правому верхньому кутку сторінки і поверніть її. Вихід: потрібно повернути її назад за допомогою властивості translate.

Вже краще. Але першого елемента все ще не видно, так як та ж проблема спостерігається і з дочірніми елементами. Це можна поправити, задавши першому дочірньому елементу верхній margin зі значенням його ширини або трансформувавши всі елементи, як контейнер. Найпростіший спосіб, який я знайшов, це додати верхній padding до контейнера, рівний ширині дочірніх елементів, тим самим створивши буферну зону для елементів.

.horizontal-scroll-wrapper {

transform:rotate(-90deg) translateY(-100px);

}

Ще одне демо з прямокутними дочірніми елементами:

Сумісність

Я перевірив сумісність на доступних мені пристроях.

Горизонтальная прокрутка на чистом CSS

Десктоп

Так як стилізація скроллбаров поки що працює тільки в Webkit/Blink браузерах Firefox і IE показується звичайний сірий скроллбар. Це можна поправити за допомогою JS і ховати їх взагалі, але це тема для іншого уроку.

Прокрутка за допомогою колеса миші відмінно працює на десктопі. Але у мого ноутбука свою думку на цей рахунок. На пристроях з тач скрінами і тач падами демо веде себе так, ніби div взагалі не повертали.

Мобільні пристрої

Я був приємно здивований, коли дізнався, що Android розуміє, що контейнер був повернутий, і дозволяє вам скролити з допомогою свайпов вправо і вліво.

З iOS ж навпаки, все не так гладко. Браузер веде себе так, ніби контейнер не повертали зовсім. Тому для прокрутки потрібно використовувати свайпи вгору і вниз, що досить дивно. Overflow: hidden не вирішує проблему.

Висновок

За даними сайту Can I Use трансформації в CSS зараз підтримуються у 93%+ користувачів (на момент написання статті, листопад 2016). Тут проблем виникнути не повинно.

Хоча краще не використовувати цей метод в продуктиве. Я протестував його на деяких пристроях, але далеко не на всіх і не так ретельно.

Найбільша проблема – сенсорні инпуты, в яких для переходу наліво і направо потрібно робити свайпи вгору і вниз. В якості рішення можна було б прописати повідомлення на сайті з поясненням, але тоді вам доведеться покластися на те, що користувачі прочитають його. І навіть тоді це буде суперечити здоровому глузду. Інший спосіб рішення – захоплювати сенсорні инпуты з допомогою JS на пристроях, але тоді краще взагалі все писати на JS і повністю відмовитися від нашого CSS хака.