От автора: элемент progress HTML уже много лет реализован в браузерах. (Лея Веру работала над полифиллом еще в 2011 году!) Можно было бы ожидать, что после всех этих лет все станет стабильным. Оказывается, за эти годы изменилось не так много. Порядка по-прежнему не наблюдается, а процесс анимирования элемента progress … не совсем гладкий.
Какие браузеры
Цель с самого начала заключалась в том, чтобы получить результат в последних версиях Chrome, Safari, Firefox, Edge и, возможно, Internet Explorer.
HTML
Элемент progress имеет атрибут max и атрибут value. Атрибут max должен быть значением больше 0. Если вы не установите значение max, оно по умолчанию равно 1. Значение представляет собой число от 0 до максимального значения. В этой статье я не буду рассматривать неопределенные индикаторы, для которых значение не задано.
Стили
Все браузеры предоставляют собственные стили элемента progress, но их легко переопределить. Просто начните устанавливать свои стили!
progress { background-color: white; border: 1px solid blue; /* и т.д. и т.п. */ }
(Во многих руководствах пишут, что вам нужно задать для appearance — и всех его вендорных эквивалентов — none, но сейчас это не обязательно).
Вам может стать интересно, почему в Blink и Webkit цвет фона индикатора прогресса фактически не изменился. Для этого вам нужно настроить таргетинг на псевдо-элемент.
::-webkit-progress-value { background-colour: white; }
Отлично. Теперь нам нужно настроить панель, которая отображает прогресс — индикатор прогресса. В каждом браузере имена отличаются.
::-webkit-progress-value { background-color: blue; } ::-moz-progress-bar { background-color: blue; } ::-ms-fill { background-color: blue; }
Теперь у нас есть что-то, что выглядит разумно согласованным в разных браузерах.
Изменение Value
Чтобы анимировать индикатор прогресса, нам нужно изменить value для элемента progress. Для этого нам нужен JavaScript.
// предположим, у нас на странице есть только 1 элемент progress. var p = document.querySelector('progress'); // здесь val - это наше новое значение value p.setAttribute('value', val);
Давайте анимируем элемент!
Edge и Internet Explorer анимируют индикатор прогрессу сразу из коробки. Отлично! Для Chrome и Safari мы можем просто установить переход по ширине индикатора прогресса.
::-webkit-progress-value { transition: width 1s; }
Сложности в Firefox
Хотелось бы желать / надеяться / ожидать, чтобы простой переход также работал на Firefox, но вы ошибаетесь. У каждого браузера есть определенные вещи, которые вы не можете делать для каждого из элементов.
В Firefox вы не можете установить переход по ширине. Вы также не можете изменять ширину. Но вы можете использовать преобразование. И вы можете использовать переход для других свойств.
Я подозреваю, что есть более простой способ сделать это, но это то, до чего я додумался: давайте анимируем padding-bottom!
Анимирование padding-bottom означает, что я могу получить высоту индикатора прогресса, которая будет соответствовать ширине индикатора прогресса. Проблема в том, что это происходит в неправильном направлении. поэтому я преобразую индикатор прогресса, чтобы повернуть на 90 градусов, и задать анимацию в право, так, как мы этого хотим!
::-moz-progress-bar { transition: padding-bottom 1s; padding-bottom: var(--value); transform-origin: 0 0; transform: rotate(-90deg) translateX(-15px); padding-left: 15px; }
Мы устанавливаем для transform-origin — 0 0, чтобы указать верхний левый угол. (Вы также можете указать top left, но 0 0 на несколько байтов короче).
Индикатор теперь будет увеличиваться справа налево. (Когда мы устанавливаем пользовательское свойство —value, оно будет увеличиваться вверх и направо).
Если бы мы только выполнили поворот, индикатор прогресса размещался бы сверху от области прогресса. Нам нужно сдвинуть его. (Фактически сдвинуть влево, поскольку мы развернули его на 90 градусов.) Нам нужно использовать переход, чтобы сдвинуть элемент на высоту области прогресса. В моем примере это 15px в высоту, поэтому сдвиньте элемент на 15px. Если бы это было 30px в высоту, вы бы сдвинули его на 30 пикселей.
Теперь все начинает складываться. Когда он повернут, высота строки изменяется при изменении значения. Если это будет больше, чем высота области прогресса, тогда индикатор перекроет другие вещи на странице. Мы можем исправить это, установив обрезку для содержимого, выходящего за пределы элемента прогресса.
progress { overflow: hidden; }
Также из-за поворота высота индикатора прогресса (которая по умолчанию соответствует высоте области прогресса) это будет влиять на ширину повернутого индикатора. Поэтому нам нужно установить высоту индикатора прогресса равной 0.
::-moz-progress-bar { height: 0; }
Выполнив все это, мы можем установить для значение пользовательского свойства то же значение, что и для атрибута value.
p.style.setProperty('--value', val + '%');
Как по маслу!
Но мне не нужна никакая / другая анимация в IE и Edge
Невозможно отключить или настроить анимацию или время перехода для индикатора прогресса в IE или Edge (как я выяснил).
(Похоже, что на самом деле у Microsoft есть элемент-оболочка, которая и анимируется. Этот элемент-оболочка связывает элемент ::-ms-fill, не позволяя вносить любые изменения в анимацию.)
Если вы хотите увидеть все это на Codepen, посмотрите мою демо-версию.
Автор: Jonathan Snook
Источник: https://snook.ca/
Редакция: Команда webformyself.