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, за да не мърда при scroll
  • z-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”

Вашият коментар

Вашият имейл адрес няма да бъде публикуван. Задължителните полета са отбелязани с *

Този сайт използва Akismet за намаляване на спама. Научете как се обработват данните ви за коментари.