
Parallax Text Reveal
Продължаваме поредицата с урок за parallax ефект, с който този път можем по интересен начин да променим цвета на текст.
С повечето библиотеки можем да вържем scroll-а на браузъра с цвета на текста, така че той да прелива плавно от един към друг. Тук обаче ще търсим нещо по-различно, така че един ред да е в един цвят до средата (вертикално), а надолу — в друг.
Нека този път започнем с примера на крайния резултат, а после ще говорим как сме го постигнали.
Пример
Parallax Text Reveal: https://magadanski.com/demo/parallax-text-reveal/
Път до целта
Нека разгледаме стъпка по стъпка какви особености имаме в markup-а, стиловете и JavaScript-а. Последният е доста малко.
HTML
<head>
-а е стандартен — charset meta, заглавие и стилове. Последните включваш шрифтът Poplar, зареден от TypeKit.
По-надолу в <body>
-то започваме със самия текст:
<h1 class="presents">
<span class="presents__manufacturer">MyManufacturer</span><br />
presents<br />
the <span class="presents__phone">MyPhone 1</span>
</h1>
Използвам различни класове за името на псевдо производителя и модела телефон. Върху тях ще акцентираме с Poplar и по-голям шрифт.
След това просто показваме една картинка на примерен телефон, който взех от Wikipedia.
Накрая добавяме един елемент, който да държи scroll-ващия се зелен фон. В него дублираме markup-а за заглавието.
<div class="intro-cover">
<h1 class="presents">
<span class="presents__manufacturer">MyManufacturer</span><br />
presents<br />
the <span class="presents__phone">MyPhone 1</span>
</h1>
</div>
После ще направим така, че едното да е бяло, а другото — зелено. Реално при scroll ще показваме едното и ще крием другото.
CSS
Нека да добавим стилове за текста си:
.presents {
position: fixed;
z-index: 200;
top: 12.5%;
left: 25%;
display: inline-block;
font: normal 38px/1.2 Arial, Helvetica, sans-serif;
transform: translateX(-50%);
}
Особеното е:
position: fixed
, за да не мърда при scrollz-index: 200
за да можем по-късно да си поиграем с показването и скриването на елементите. Ключово е кой е отгоре и кой отдолу при ефекта, който гоним.
top
, left
и transform
ги използваме за да наместим позицията.
Няколко реда за по-особените стилове на производител и модел:
.presents__manufacturer,
.presents__phone {
font-family: poplar-std, sans-serif;
}
.presents__manufacturer {
font-size: 1.68em;
}
.presents__phone {
font-size: 2.11em;
}
Позиционираме и картинката:
.phone-image {
position: fixed;
z-index: -100;
left: 50%;
bottom: 20px;
width: auto;
height: 67%;
transform: translateX(-50%);
}
Зелен overlay
Скриваме картинката и зелената версия на текста със зелен фон:
.intro-cover {
position: relative;
z-index: 200;
width: 100%;
height: calc(100vh - 120px);
margin-bottom: calc(100vh + 120px);
background: #45AFBB;
overflow: hidden;
}
Ключови стилове:
position: relative
— нужно е да е изрично да се окажеrelative
, за да повлияеz-index
-а по-долу. По подразбиране еstatic
, което по никакъв начин не се влияе от каквато и стойност да сме задали заz-index
z-index: 200
задаваме го със същата стойност като фиксирания текст. Тъй като този правоъгълник е по-късно в markup-а, при еднакъвz-index
той всъщност се показва отгоре.height: calc(100vh - 120px)
— правим го да е колкото целия екран, но без 120px. После картинката на телефона ще се “подава” отдолу.margin-bottom: calc(100vh + 120px)
— задаваме margin, така че да имаме поле за scroll. Без scroll няма паралакс. Стойността е 100vh, така че да имаме един цял екран scroll-ване + още 120px. Последните ще компенсират “дупката” от 120px, през която да наднича картинката.
Тъй като markup-а за заглавието се повтаря вътре в този зелен правоъгълник, той ще унаследи и стиловете. Ние обаче искаме няколко малки промени, така че презаписваме с:
.intro-cover .presents {
position: static;
color: #FFF;
transform: translate(calc(25vw - 50%), 12.5vh);
}
Задаваме статична позиция, защото иначе overflow
-а на контейнера няма да работи. А той ни трябва за да можем да “отрежем” този вътрешен текст.
Белият цвят е, за да се вижда текста, иначе става зелен текст на зелен фон.
Накрая използваме transform
, с който да постигнем същата позиция, без position
, left
и top
.
Конкретно стиловете left: 25wh
и transform: translateX(-50%)
ги обединяваме само в translate
с calc(25vw - 50%)
. Възползваме се от това, че calc()
е замислен за да сметне стойност на базата на различни мерни единици. В случая това е vw
(процент от широчината на целия прозорец) и %
(което в случая е процент от широчината на самия елемент.
JavaScript
JavaScript-ът е елементарен:
const coverPresents = document.querySelector('.intro-cover .presents');
window.addEventListener('scroll', function (e) {
requestAnimationFrame(function () {
coverPresents.style.transform = `translate(calc(25vw - 50%), calc(12.5vh + ${window.scrollY}px))`;
});
});
Първо си запазваме референция към .intro-cover .presents
в променлива. Това за да можем после директно да правим манипулации.
След това добавяме event listener за scroll
събитие. Задължително в callback функцията добавяме requestAnimationFrame
за такива събития. Същото по принцип правим и за resize
.
Накрая най-вътре променяме transform
стиловете на елемента. Задаваме нов translate
, в който вече не само X-а ще е с calc()
, ами и Y-а. Той, за да можем към основната позиция от 12.5vh
да добавим толкова пиксела, колкото сме scroll-нали. Местейки текста точно с толкова, с колкото сме scroll-нали, той визуално винаги ще излиза на едно място. А когато края на зеления контейнер дойде, тогава overflow: hidden
ще скрие белия текст.
Така достигаме до примера посочен по-горе.
Тестване
След няколко теста обаче, изглежда че ефектът върви според очакванията ни в повечето, но не всички случаи.
Аз поне като тествам на Chrome понякога при първи scroll с колелцето на мишката, или при приключване на scroll се получава едно прескачане:
На Firefox се държи малко по-добре, но на Edge е направо ужасно.
Все още не съм открил конкретната причина за тези артефакти, но доколкото ми е известно паралакс ефектите не работят особено добре при елементи с позиция различна от absolute
или fixed
. Това се казва и в статия на Dave Gamache “Parallax Done Right“:
Анимирайте само елементи с абсолютна или фиксирана позиция. Не съм 100% [сигурен] защо, но съм виждал значително подобрение в производителността само анимиране на абсолютни/фиксирани елементи. Веднага щом приложа дори една анимация на относителен/статичен елемент, броя кадри в секунда спада.
Dave Gamache
Подобен ефект може би ще е по-добре да се направи с <canvas>
, но там самият аз все още нямам много опит. Все пак ще опитам някой път да реализирам нещо подобно и ще споделя резултата.
[…] урока си Parallax Text Reveal вече споделих линк към една статия от Medium, на която […]