В даний час я працюю над своїм першим оплачуваних проектом. Крім усього іншого в цьому проекті від мене вимагається стилізація і написання скриптів для повзунків. Є кілька цікавих моментів, на які мені б хотілося звернути вашу увагу, такі як проблеми відображення в IE, Android WebKit і правильне використання подій вводу і зміни. А також короткий огляд синтаксису.

Ось мій приклад. В цьому конкретному випадку користувачів з Голландії з допомогою повзунків просять розділити 100 мільйонів євро бюджетних коштів між кількома відомствами. При цьому загальне значення всіх повзунків не повинно перевищувати 100 (мільйонів), що вимагає написання невеликого скрипта.

Повзунок, доріжка і бігунок

Ось повзунок. Технічно він відомий як , і він не підтримується IE9 і нижче.

Тут код HTML:

Повзунок складається з доріжки, по якій користувач перетягує бігунок. До доріжці і бегунку можна застосовувати стилі, але не скрипти.

Основи стилів

Стилізація повзунків не так вже важка. Для бігунка і доріжки можна налаштувати стилі, хоча необхідні псевдоелементи залежать від браузера:

Для бігунка використовується -webkit-slider-thumb, -moz-range-thumb або -ms-thumb.

До доріжці можна «звернутися» за допомогою -webkit-slider-runnable-track, -moz-range-track або -ms-track.

Не можна комбінувати ці селектори в одному правилі, навіть незважаючи на те, що правильніше використовувати для всіх браузерів одні і ті ж стилі (крім відступів для бігунка). Якщо браузер знаходить один селектор, який він не розпізнає, то ігнорує всі інші. Тому вам доведеться повторюватися або використовувати генератор CSS на серверній стороні.

IE і MS Edge вимагають прозорий color і border-color на доріжці, або вони відобразять стилі доріжки за замовчуванням. Крім того, для повзунка їм потрібні інші відступи, ніж в інших браузерах.

В моєму прикладі висота повзунка приблизно 40 пікселів. Виявляється, в основних стилях повзунка встановлено властивість overflow: hidden, яке займає більшу частину повзунка в Edge і IE. Щоб виправити це, мені довелося явно задати висоту повзунка.

В IE, але не Edge, повзунок має відступ. Тому задайте відступ padding: 0 і врятуйте себе від головного болю.

Я читав кілька разів, що MS Edge повинен підтримувати властивості -webkit-. Але на практиці виявилося, що неможливо працювати з одним набором стилів і для Edge, і для WebKit/Blink. Я раджу використовувати окремі -ms- стилі хоча б тому, що вони потрібні для IE10 і IE11. Краще всього визначити стилі -ms- після -webkit-: таким чином -ms- стилі будуть точно виконуватися Edge.

У браузерах, побудованих на основі движка WebKit і Blink, бігунок має за замовчуванням box-sizing: border-box, в той час як у всіх інших браузерах, значення цієї властивості одно content-box. Краще поставити box-sizing для бігунка в явному вигляді.

WebKit і Blink також вимагають -webkit-appearance: none, але з одним винятком. Дивіться нижче.

CSS шаблон

Всі ці несуттєві проблеми приводять до наступного шаблону CSS:

input[type=range] {
-webkit-appearance: none;
height: 35px; /* встановіть свою висоту*/
padding: 0;
/* стилі вашого повзунка */
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
box-sizing: content-box;
/* стилі вашого бігунка */
}
input[type=range]::-moz-range-thumb {
/* знову стилі вашого бігунка */
}
input[type=range]::-ms-thumb { /* повинен слідувати після -webkit- */
/* знову стилі вашого бігунка */
/* можуть знадобитися різні відступи */
}
input[type=range]::-webkit-slider-runnable-track {
/* стилі вашої доріжки*/
}
input[type=range]::-moz-range-track {
/* знову стилі вашої доріжки */
}
input[type=range]::-ms-track { /* повинен слідувати після -webkit- */
border-color: transparent;
color: transparent;
/* знову стилі вашої доріжки */
}

Властивість appearance і помилка Android WebKit

Ще один недолік в браузерах на основі WebKit і Blink полягає в тому, що ви повинні встановити властивість -webkit-appearance: none для повзунка і для бігунка (але не для доріжки). Це показано в шаблоні CSS, наведеному вище.

Справжня проблема в тому, що Android WebKit вимагає від вас не використовувати це оголошення. Якщо ви додасте -webkit-appearance: none, Android WebKit буде неправильно відображати ваші стилі. Видалення цього коду виправляє помилку, але тоді стилі повзунка не будуть відображатися в Safari, Chrome і деяких інших браузерах. Вирішимо цю проблему разом.

Ми задали в CSS -webkit-appearance: none, це єдине рішення, у якого є майбутнє. В Android WebKit ми хочемо змінити значення на slider-horizontal. Але як ми дізнаємося, що ми в Android WebKit?

Розпізнавання браузера? Так не прийнято в наших колах – що і до кращого: це не спрацювало б у Xiaomi Chromium 34 (35), який базується на Chromium і, отже, вимагає значення none, але при цьому «маскується» під Android.

Моїм початковим планом було отримати доступ до стилів бігунка і подивитися, чи відповідають вони моїм. Якщо вони не підходять, то ми застосовуємо slider-horizontal:

window.getComputedStyle(slider,’::-webkit-slider-thumb’).height;

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

Потім я побачив, що це застосування getComputedStyle() не підтримується в Android WebKit. Жоден стиль не повертається, навіть стилі за замовчуванням.

Тому я написав класичний трюк, який використовує одну помилку, щоб позбутися від іншої, незв’язаної з нею. На щастя, це безпечний прийом, так як обидві помилки можуть з’явитися тільки в Android WebKit, і цей браузер вже не розробляється:

var testAndWK = window.getComputedStyle(slider,’::-webkit-slider-thumb’).height;
if (!testAndWK) {
slider.style.WebkitAppearance = ‘slider-horizontal’;
}

Ви можете виконати тест один раз і використовувати результати для кожного повзунка. Неважливо, яке властивість CSS ви тестуєте, перевірте, чи дійсно він існує. Якщо значення не повертається, то встановлюємо -webkit-appearance: slider-horizontal для кожного повзунка. Проблема вирішена. Навіть краще, інші браузери ігнорує нас, поки ми використовуємо —webkit-.

Заповнення смуги прогресу

В моєму прикладі доріжка зліва від бігунка повинна мати колір фону відмінний від доріжки праворуч. IE/Edge і Firefox пропонують для цього використовувати псевдоелементи, WebKit і Blink – ні. Цей код вирішує проблему у всіх версіях IE, Firefox і Edge:

input[type=range]::-ms-fill-lower {
background-color: #5082e0;
}
input[type=range]::-moz-range-progress {
background-color: #5082e0;
}

Що стосується браузерів на основі WebKit — і Blink, то тут потрібно рішення з JavaScript. Я позичив своє з прикладів Ana Tudor. У цьому рішенні використовується лінійний градієнт зі стоп-кольором, який обчислюється від поточного значення повзунка. Подивіться скрипт, особливо код функції handleSlider().

Спливаючі підказки

Ana Tudor також показала, як можна використовувати псевдоэлемент :before як стилізованої підказки, що містить поточне значення. На жаль, з’ясувалося, що в цьому випадку IE/Edge і Firefox не підтримують :before або :after. В IE/Edge є передбачення (дивіться нижче), але в Firefox неможливо відобразити спливаючі підказки.

Я пробував рухомий елемент, що реагує на переміщення бігунка, але написання скриптів не спрацьовує, і отримати поточні координати бігунка неможливо. Також намагався використовувати поточне значення повзунка замість координат, але спроба завершилася провалом. У кінцевому рахунку, ми вирішили використовувати статичну підказку (яка насправді не виглядає як підказка).

В IE/Edge є вбудована підказка, яка здебільшого не може бути стилізована. На щастя, ви можете приховати її:

input[type=range]::-ms-tooltip {
display: none;
}

Події вводу і зміни

Коли користувач переміщує повзунок по доріжці, повзунок може викликати події вводу або зміни. Одні браузери безперервно «породжують» події під час переміщення, інші – тільки після зупинки переміщення.

При відстеженні дій користувача з повзунком перехватывайте події вводу і зміни. Потім викликайте обробник події, коли користувач припинить переміщення бігунка. Це дає стабільний результат у всіх браузерах:

slider.addEventListener. (‘input’,startTimer,false);
slider.addEventListener. (‘change’,startTimer,false);
var timeout;
function startTimer() {
var that = this;
clearTimeout(timeout);
timeout = setTimeout(function () {
handleEvent(that);
},100);
}
function handleEvent(slider) {
/* Спрацьовує, коли користувач переміщує повзунок протягом 100 мс*/

}

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

Переклад статті «Styling and scripting sliders» був підготовлений дружною командою проекту Сайтостроение від А до Я.