Как создать пользовательский ползунок диапазона с помощью CSS

Как создать пользовательский ползунок диапазона с помощью CSS
Как создать пользовательский ползунок диапазона с помощью CSS

В этой статье мы покажем, как использовать современные методы CSS для создания привлекательного пользовательского слайдера диапазона, используя только собственный HTML <input> элемент.

Ползунки диапазона (<input type="range">) позволяют пользователям выбирать значение в пределах заданного диапазона, предоставляя альтернативные типы ввода, такие как <input type="number">.

Стили слайдера диапазона по умолчанию выглядят не очень. Изображение ниже дает представление о том, какой диапазон ползунков, которые мы будем стилизовать, отображаются по умолчанию в Chrome, Firefox и Safari.

Но <input> элементы сложно стилизовать. Большинство онлайн-решений для их оформления основаны на JavaScript и некотором загроможденном коде. Что еще хуже, некоторые из этих методов также нарушают доступность элемента.

Структура элемента ввода диапазона

Давайте начнем с анализа структуры элемента ввода диапазона. Это собственный элемент, и каждый браузер имеет свою собственную реализацию таких элементов. В основном у нас есть две разные реализации.

Есть один для браузеров Webkit и Blink, таких как Chrome, Edge, Safari и Opera:

<input type="range" min="0" max="100" step="1" value="20">
  <div>
    <div pseudo="-webkit-slider-runnable-track" id="track">
      <div id="thumb">
    </div>
   </div>
  </div>
</input>

Обзор входных данных Chrome

И это для Firefox:

<input type="range" min="0" max="100" step="1" value="20">
  <div></div>
  <div></div>
  <div></div>
</input>

Обзор входных данных Firefox

Существует третья реализация для IE, но, к счастью, этот браузер практически мертв и его больше нет!

Такое несоответствие между браузерами - это то, что усложняет задачу, поскольку нам нужно предоставить различный стиль для каждой реализации. Не будем углубляться в это, поскольку статья тогда никогда не закончится.

Единственное, что вам нужно иметь в виду, это то, что, независимо от реализации, у нас всегда есть “большой палец” в качестве общего компонента.

Мы собираемся только оформить этот элемент, что упростит настройку пользовательского слайдера диапазона. Давайте сразу перейдем к коду, чтобы увидеть магию в действии.

Настройка входных данных

Первым шагом является сброс и отключение всех стилей браузера по умолчанию с помощью appearance: none и некоторых других общих свойств:

input {
  appearance :none;
  background: none;
  cursor: pointer;
}

В более сложном сценарии нам может потребоваться добавить больше кода на случай, если к нашему элементу будут применены другие стили по умолчанию. Просто нужно убедиться, что у нас есть “голый” элемент без какого-либо визуального оформления.

Давайте также определим несколько переменных CSS, чтобы мы могли легко создавать различные варианты для ползунка диапазона:

input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/

  width: 400px; /* input width */
  height: var(--s); 
  appearance :none;
  background: none;
  cursor: pointer;
}

На этом шаге виден только большой палец со стилями по умолчанию.

Стилизация элемента Thumb

Давайте оформим элемент thumb. Мы начнем с базовой настройки:

<thumb selector> {
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  appearance: none;
}

Код должен быть понятным. Пока ничего особенного.

Обратите внимание на использование двух разных селекторов, как мы объяснили в первом разделе:

/* Chrome, Edge, Safari, Opera */
input[type="range" i]::-webkit-slider-thumb { }
/* Firefox */
input[type="range"]::-moz-range-thumb { }

Но откуда вы знаете, какой селектор использовать?

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

Добавляем немного магии с помощью border-image

Теперь мы собираемся использовать волшебный CSS-трюк для завершения нашего слайдера. Это предполагает использование border-image:

border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g));

Да, это выглядит пугающе, но давайте проанализируем эту линию, и вы увидите, что это не так уж сложно. Приведенное выше является сокращением для следующего:

border-image-source: linear-gradient(90deg,var(--c) 50%,#ababab 0); 
border-image-slice: 1;
border-image-width: 0 100vw;
border-image-outset: 0 calc(100vw + var(--g));

На странице MDN мы читаем:

border-image Свойство CSS рисует изображение вокруг заданного элемента. Он заменяет обычную границу элемента.

Наше изображение будет представлять собой градиент, имеющий два цвета — основной (определяется --c) и серый. Нам нужно, чтобы изображение границы охватывало все пространство входных данных по горизонтали, поэтому мы используем большое значение для ширины слева и справа (100vw), в то время как мы оставляем верх и низ равными (0).

Но border-image-width это ограничено размером элемента. Чтобы преодолеть это, нам также нужно использовать большое значение для border-image-outset, чтобы увеличить пространство, доступное для изображения границы. Снова из MDN:

border-image-outset Свойство CSS задает расстояние, на которое изображение границы элемента выделяется из его рамки.

Части изображения границы, которые отображаются за пределами рамки элемента с помощью border-image-outset, не вызывают переполнения полос прокрутки и не фиксируют события мыши.

Когда мы впервые видите ползунок, кажется, что мы увеличиваем основной цвет слева, но на самом деле мы перемещаем фиксированный градиент, который перекрывает наш элемент.

Следующая демонстрация предоставляет обзор того, что происходит под капотом.

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

Также обратите внимание, что начало должно быть больше ширины, чтобы был зазор. По этой причине он определен равным ширине плюс значение разрыва.

Добавляя overflow: hidden к элементу ввода и используя большое значение, иллюзия получается идеальной.

Что насчет border-image-slice? Почему значение 1?

Это свойство немного сложное, но обязательное при использовании border-image. В нашем случае это значение не очень актуально, и небольшое положительное значение выполнит свою работу.

Последний шаг - уменьшить размер полосы, чтобы он соответствовал размеру, который мы определили с помощью переменной --l. Для этого мы собираемся использовать clip-path:

clip-path:
    polygon(
       0     calc(50% + var(--l)/2),
      -100vw calc(50% + var(--l)/2),
      -100vw calc(50% - var(--l)/2),
       0     calc(50% - var(--l)/2),
       0 0,100% 0,
       100%  calc(50% - var(--l)/2),
       100vw calc(50% - var(--l)/2),
       100vw calc(50% + var(--l)/2),
       100%  calc(50% + var(--l)/2),
       100% 100%,0 100%);

На изображении ниже представлен обзор различных точек, чтобы понять форму многоугольника.

Обзор входных данных Firefox

Вот и все! У нас есть пользовательский ползунок диапазона с несколькими строками кода, которым вы можете легко управлять, настраивая несколько переменных.

Добавление некоторой анимации

Как насчет какой-нибудь тонкой анимации при взаимодействии со слайдером? Для этого не нужно много кода, и это улучшит пользовательский интерфейс слайдера.

Во-первых, мы собираемся преобразовать большой палец из окружности только для границ в полный круг, когда мы нажимаем на него. Для этого мы увеличиваем значение разброса box-shadow. Помните, что мы использовали box-shadow для определения границы большого пальца:

box-shadow: 0 0 0 var(--l) inset var(--c);

Мы обновляем var(--l) до var(--s), используя :active селектор и :focus-visible. Последний связан с навигацией с клавиатуры и позволяет нам добиться одинакового эффекта независимо от того, используем ли мы мышь или клавиатуру.

Код выглядит следующим образом:

input[type="range" i]::-webkit-slider-thumb {
  box-shadow: 0 0 0 var(--l) inset var(--c);
  transition: .3s;
}

input[type="range" i]::-moz-range-thumb {
  box-shadow: 0 0 0 var(--l) inset var(--c);
  transition: .3s;
}

input:active::-webkit-slider-thumb,
input:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 var(--s) inset var(--c);
}

input:active::-moz-range-thumb,
input:focus-visible::-moz-range-thumb {
  box-shadow: 0 0 0 var(--s) inset var(--c);
}

Это немного длинновато для box-shadow перехода, не так ли? Мы можем оптимизировать его с помощью переменной CSS:

input[type="range" i]::-webkit-slider-thumb {
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--c);
  transition: .3s;
}

input[type="range" i]::-moz-range-thumb {
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--c);
  transition: .3s;
}

input:active,
input:focus-visible {
  --_b:  var(--s);
}

Выражаем значение разброса с помощью переменной, и просто обновляем эту переменную с помощью :active и :focus-visible.

Мы также собираемся добавить немного анимации к цвету. Сделаем его немного темнее на :hover. Для этого не будем обновлять цвет, а скорее смешаем его с чёрным, используя новую color-mix() функцию. Этот трюк позволяет нам использовать основной цвет, определенный --c, а не определять новый темный цвет для каждого ползунка вручную:

--_c: color-mix(in srgb, var(--c), #000 var(--p,0%));

Определяем новую переменную, которая заменит --c в коде. Затем, регулируя процент черного цвета (#000) с помощью переменной --p, контролируем “темноту” цвета:

input:focus-visible,
input:hover{
  --p: 25%;
}

Эта функция пока поддерживается не во всех браузерах, поэтому настоятельно рекомендуется использовать запасной вариант:

@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c); /* if no support we keep the color as defined */
  }
}

Наш слайдер диапазона теперь идеален!

Заключение

Мы дошли до конца, и нам не пришлось иметь дело с какой-либо сложной реализацией, связанной с браузером! Мы определили селектор элемента thumb и, используя несколько приемов CSS, оформили им весь слайдер диапазона. Давайте не будем забывать, что мы сделали это, используя только <input> элемент, поэтому нам не нужно беспокоиться о каких-либо проблемах с доступом, поскольку мы сохранили встроенную функциональность. Слайдер без проблем поддерживает навигацию с клавиатуры.

Понравилась статья?
Будем признательны, если поделитесь в соцсетях или мессенджерах, а также присоединитесь к нашей группе Вконтакте. Будет интересно!

Вас может заинтересовать:

Анимация для текста на CSS
Анимация для текста на CSS
В наше время без анимационных эффектов на сайте просто не обойтись. Это и слайдеры и скроллеры, различного рода реагирования элементов дизайна при наведении на них мышкой, это анимация при прокрутке страниц и различные выезжающие, выплывающие, выползающие и т.д. блоки контента. Дизайнеры используют свою фантазию на 100%, чтобы их дсайт выделился из общей массы и запомнился Пользователям...

CSS анимация обводки блоков
CSS анимация обводки блоков
Интересные эффекты для границ блоков контента с анимацией, которые вам могут пригодиться при оформлении страниц сайта.

Как использовать свойства CSS object-fit и object-position
Как использовать свойства CSS object-fit и object-position
Существует множество вариантов для определения размера и расположения фоновых изображений с помощью CSS. В этой статье мы рассмотрим, как использовать object-fit для размещения изображений на определенном пространстве и как использовать object-position для правильного позиционирования в этом пространстве.

Анимационные указатели прокрутки страницы
Анимационные указатели прокрутки страницы
Такие указатели чаще всего применяют на первом экране Главной страницы сайта, когда на ней размещена полноэкранная картинка, видео или слайдер. Чтобы показать Пользователю, что основной контент расположен ниже, в нижней части экрана размещают стрелку, направленную вниз. Чтобы привлечь к ней дополнительное внимание, её делаю анимационный...

Градиентная обводка блока на CSS
Градиентная обводка блока на CSS

Как сделать красивую градиентную обводку блока на одном только CSS? Для этого мы сделаем следующее:

1. Создадим div.linear-gradient с градиентным фоном;

2. Создадим внутренний блок div с небольшим отступом.


Бесплатный ФРОНТЭНД
Бесплатный ФРОНТЭНД
Представляю вашему вниманию бесплатные неоновые эффекты для текста на CSS...

QRcode

2010-2024 © Веб студия iNikSite.ru (г. Подольск). Все права сохранены.

Цены на сайте носят ознакомительный характер и не являются публичной офертой! Просим уточнять цены при отправке заявки в нашу компанию. У нас действуют специальные предложения и скидки на различные варианты исполнения заказа и 100% предоплату!

Мы используем файлы cookie. Они помогают улучшить ваше взаимодействие с сайтом.