От автора: на протяжении долгого времени я горел желанием создать бегущую анимированную строку текста, которая бы изгибалась на углах. Есть несколько способов сделать такую строку, среди которых WebGL, но мне хотелось найти настолько простой способ, чтобы его можно была написать только на HTML и CSS.
Острые углы
Базовая разметка состоит из двух div с одинаковым контентом, которые находятся внутри другого контейнера
1 2 3 4 5 6 7 8 |
<div id="marquee"> <div> <span>ONE LOVE ONE HEART</span> </div> <div aria-hidden="true"> <span>ONE LOVE ONE HEART</span> </div> </div> |
Второй div является копией первого, но у него есть атрибут aria-hidden=»true», который делает его недоступным для приложений. Таким образом, текст читается один раз.
Внутренние DIV’ы размещены под углом друг к другу при помощи 3D ротации, а родительскому контейнеру задано подходящее значение свойства perspective. У родителя также задано свойство font-size: 0. Это сделано для того, чтобы внутренние элементы со свойством display: inline-block отображались без каких-либо зазоров:
1 2 3 4 5 6 7 8 9 10 |
#marquee { perspective: 500px; font-size: 0; } #marquee div { display: inline-block; height: 12rem; width: 30rem; position: relative; } |
Внутренние div’ы повернуты под немного разными углами при помощи свойства transform-origin. Также внутренним блокам задан отличающийся фон (для симуляции направления падения света) и значения цвета.
1 2 3 4 5 6 7 8 9 10 11 12 |
#marquee div:first-of-type { background: #e5233e; transform-origin: top right; transform: rotateY(-40deg); color: #fff; } #marquee div:last-of-type { background: #b31e31; transform-origin: top left; transform: rotateY(45deg); color: #f8c9d9; } |
Текст в блоках помещен в тег span, который растянут для того, чтобы вместился весь текст. Обрезание текста, когда он выходит за рамки блоков, имитируется при помощи свойства overflow: hidden:
1 2 3 4 5 6 7 8 9 |
#marquee div { font-size: 8rem; overflow: hidden; } #marquee div span { position: absolute; width: 400%; line-height: 1.4; } |
Бегущая строка
Тегов span несколько штук, и они занимают разные позиции: текст справа сдвинут на 30rem (т.е. на ширину контейнера div, чтобы текст вышел за пределы видимой области). Текст же слева сдвинут вправо уже на две ширины блока, а также ему задана тонкая тень text-shadow.
1 2 3 4 5 6 7 8 9 |
#marquee div:first-of-type span { transform: translateX(60rem); animation: leftcrawl 14s linear infinite; text-shadow: 4px 0px 4px rgba(0,0,0,0.3); } #marquee div:last-of-type span { transform: translateX(30rem); animation: rightcrawl 14s linear infinite; } |
Если родительским блокам div не задать свойство overflow:hidden и сделать текст разных цветов, то вы получите примерно следующее:
Обе строки текста необходимо анимировать. Мы не ставим задержку на левую строку текста, вместо этого обе строки двигаются одновременно, подходя к перегибу в один и тот же момент:
1 2 3 4 5 6 |
@keyframes leftcrawl { to { transform: translateX(-100rem); } } @keyframes rightcrawl { to { transform: translateX(-130rem); } } |
Задана линейная функция анимации, текст и не ускоряется и не замедляется.
Адаптивность
Данная техника будет работать вне зависимости от изменения трех параметров, перечисленных ниже. В этом вы можете убедиться в демо на CodePen:
Текст
Значение перспективы
Угол наклона DIV’ов
Тем не менее, код плохо работает на экранах маленькой ширины: текст становится меньше, а перспектива сильно увеличивается, что затрудняет чтение бегущей строки. Поэтому если ширина видимой области меньше 993px, мы заменяем презентацию на 2D версию и показываем только один из DIV’ов:
1 2 3 4 5 6 7 8 9 10 11 12 |
@media all and (max-width: 993px) { #marquee { perspective: none; } #marquee div:last-of-type { opacity: 0; height: 0; } #marquee div:first-of-type { width: 80%; } } |
Интересный факт заключается в том, что если задать элементу свойство display: none, то анимация полностью прекратится и возобновится только, когда элемент станет снова видимым. По этой причине я воспользовался другой техникой для сокрытия элементов: второму div’у было задано свойства opacity и htight в 0. Таким образом, при растяжении или сужении области просмотра анимация не будет останавливаться.
Заключение и улучшения
В общем и целом, я доволен результатом. В скором времени надеюсь применить данную технику на моих CSS синемаграфах. Однако в данную методику можно внести пару улучшений, большая часть из которых связана с дублированием контента. JavaScript может легко дублировать элементы и текст, но намного лучше реализовать это при помощи псевдоэлементов.
Источник: //thenewcode.com/
Редакция: Команда webformyself.