Бесконечная бегущая строка на чистом CSS. Улучшения и новые функции
Опубликовано 16 сент. 2024 г.
Всем привет, друзья. Я тут почти полгода ничего не писал, и даже сайт не обновлял: было много дел и по работе, и по личной жизни. Сейчас лучше не стало, но борьба с ленью - мой конёк, хотя ни одной победы в этой равной битве мною пока еще одержано не было 🤣 Но лиха беда начало, или как там говорят…
С удивлением наблюдал как на мой сайт порой забегало по сотне человек в день, сейчас поменьше, но я эту частичку интернета вообще не пиарю, не рекламирую нигде, поэтому даже такие показатели для меня восхитительны. Главный драйвер koltan.dev - это блог. Я писака - так себе, однако людям интересны некоторые решения, которые я применял в своей работе, и которые описал здесь.
Самой популярной статьей в блоге является материал про мои мучения по созданию css-тикера. В своей работе в этом году я уже несколько раз применял это решение на живых проектах, и даже немного поискал улучшений для своей бегущей строки без JavaScript. Данный материал как раз об этом. Сразу скажу, что я много ума к моментам, здесь описанным, не прикладывал. Все достаточно просто, но может быть полезно для тех, кто не привык сам копаться, а находится в вечном поиске всего готового. В общем, поехали.
Меняем скорость бегущей строки
Я являюсь величайшим умельцем, когда дело доходит до css-анимаций (нет!), поэтому изначально решил, что единственным вариантом изменения скорости своего тикера будет изменение размера шрифта текста внутри него. Чем буквы меньше, тем скорость выше. Все оказалось куда элегантнее. Если посмотреть изначальный код, то можно увидеть заветные числа определяющие скорость движения анимаций.
section {
display: flex;
overflow-x: hidden;
}
div {
font-size: 70px;
font-size: sans-serif;
line-height: 1.3;
padding: 24px 0;
white-space: nowrap;
display: inline-block;
}
.div1 {
animation: marquee1 20s infinite linear;
animation-delay: -20s;
}
.div2 {
animation: marquee2 20s infinite linear;
animation-delay: -10s;
}
@keyframes marquee1 {
0% {
transform: translateX(100%);
}
100% {
transform: translateX(-100%);
}
}
@keyframes marquee2 {
0% {
transform: translateX(0%);
}
100% {
transform: translateX(-200%);
}
}
(В дальнейшем я не буду приводить весь код, а только самое важное)
Здесь стоить вспомнить, что наша бегущая строка является таковой только благодаря повторению контента, когда внутри контейнера бегущей строки у нас есть два элемента с одинаковым текстом, каждому из которых мы задаем разные параметры в свойстве animation
.
<section>
<div class="div1">Привет! Я бегущая строка </div>
<div class="div2">Привет! Я бегущая строка </div>
</section>
Так вот, чтобы изменить скорость бегущей строки нужно правильно изменить эти параметры, сохранив пропорции, если это можно так назвать. Я говорю о свойствах animation-duration
, которое определяет продолжительность анимации, и animation-delay
, устанавливающее время ожидания перед воспроизведением анимации. Если разницу в числах не сохранить, то можно получить эффект, когда один элемент с бегущим текстом, налетает на другой. Поэтому, если мы хотим сохранить плавность хода строки, и, допустим, уменьшить ее скорость, то делаем такое:
.div1 {
animation: marquee1 50s infinite linear;
animation-delay: -50s;
}
.div2 {
animation: marquee2 50s infinite linear;
animation-delay: -25s;
}
А если хотим увеличить, то такое:
.div1 {
animation: marquee1 10s infinite linear;
animation-delay: -10s;
}
.div2 {
animation: marquee2 10s infinite linear;
animation-delay: -5s;
}
Суть и тех и других перемен в том, что в первой части тикера, для первого HTML-элемента, мы оставляем равенство по модулю между animation-duration
и animation-delay
, а во втором элементе оставляем двукратное превосходство animation-duration
над animation-delay
, опять же, по модулю, то есть не учитывая отрицательные значения у animation-delay
. Разница лишь в том, что для уменьшения скорости бегущей строки, нужно увеличить количество секунд в обоих свойствах, а для увеличения скорости, наоборот, уменьшить.
Для пояснения кода стоит упомянуть, что уменьшенное в два раза свойство animation-delay
у второго элемента бегущей строки необходимо, поскольку второй элемент должен следовать за первым с той же скоростью, но при этом учитывая то, что впереди едет точно такая же по величине часть строки, которую нужно пропустить и не наехать на нее.
Также не стоит забывать, что отрицательные значения у свойств задержки анимации необходимы, чтобы тикер ехал как надо.
Останавливем бегущую строку при наведении
«Так, так, так», - подумал я, когда захотел, остановить бегущую строку по наведении. - «Делов то, пишем на hover к свойству animation значение none и готово». Не тут то было. Оказывается, что если написать так:
section:hover div {
animation: none;
}
То бегущая строка остановится, но при этом прыгнет в самое начало. Очень некрасиво получится. Чтобы этого избежать нужно использовать одно из свойств css-анимации - animation-play-state
.
section:hover div {
animation-play-state: paused;
}
Значение paused
как раз сделает то, что нужно - остановит анимацию в том, месте где она была до наведения мыши, без прыжков и некрасивостей. У animation-play-state
есть еще одно возможное значение - running
, которое запускает анимацию. Этим можно поиграться, например, создав кнопки и привязав к ним действия через JS. Но я этого делать не буду, у меня тут третий пункт улучшений для нашей бегущей строки подоспел 😀.
Запускаем бегущую строку в обратную сторону
Нужно отметить, что мы до сих пор не трогали ключевые кадры анимации, а осуществляли все манипуляции с временем задержки и со скоростью бегущей строки. Теперь же нам потребуется изменить @keyframes
, чтобы тикер поехал в другую сторону.
Для начала поменяем местами «нулевую» и конечную позиции для первой части бегущей строки, чтобы она стартовала со стопроцентного со знаком «минус» смещения по оси X, а заканчивала с положительным стопроцентным смещением
@keyframes marquee1 {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}
Второй же блок контента в бегущей строке должен начать ехать с «минус двух сотен процентов», а заканчивать в «нуле».
@keyframes marquee2 {
0% {
transform: translateX(-200%);
}
100% {
transform: translateX(0%);
}
}
И все. Думаю, если поменять здесь translateX
на translateY
, то у нас должна получиться вертикальная бегущая строка, но это не точно 😀.
Крутим бегущую строку пальцем
Если есть потребность, то можно немного добавить интерактивности в наш тикер. К примеру, на сенсорных устройствах можно включить возможность прокручивать тикер пальцем в любую сторону. Делается это очень просто: добавляем возможность прокрутки на контейнер бегущей строки.
section {
display: flex;
overflow-x: auto;
}
Здесь, однако, могут случится неприятности. Может поехать макет, так как бегущая строка захочет влезть в экран полностью. Возможно overflow-x: auto;
лучше прописать для мобильных экранов, не трогая десктопы, чтобы глаза не мозолил горизонтальный скроллбар. А лучше вообще его убрать с помощью того же css.
section::-webkit-scrollbar { /* хром, сафари */
width: 0px;
}
section {
-ms-overflow-style: none; /* IE 10+ */
scrollbar-width: none; /* Firefox */
}
Для взаимодействия со строкой на несенсорных девайсах придется написать JavaScript-код. Но поскольку эта статья о pure css, то и скриптами мучить ее не будем.
Итого
Мы немного проапгрейдили нашу бегущую строку из статьи практически годичной давности. Все решения здесь описанные несложные, но пришел я к ним не сразу, поскольку заняться этим тикером глубже просто не было времени. Кстати, наверняка и у вас тоже найдутся интересные решения для бегущей строки без JS. Напишите мне в телеграм, если хотите. А пока все. Всем счастья и любви 😀!