어느 덧 회사 창립 5년 차.
처음으로 사업팀에서 공식 회사 홈페이지에 대한 요청이 들어왔습니다.
TF는 빠르게 구성되었고, 기획자 1명, 백엔드 개발자 1명, 외주 디자이너 1명, 그리고 프론트엔드 개발자인 저까지 총 4명이 함께하게 되었습니다.
작업 기간은 약 한 달 정도로 짧았기 때문에 개발은 병렬적으로 진행해야 했습니다.
그럼에도 불구하고, 특히 메인 페이지에는 디자인과 인터랙션에 보다 공을 들이기로 결정했습니다.
그렇게 오픈한 웹사이트가 바로
👉 www.flatten.co.kr
오늘은 이 사이트의 메인(홈) 페이지 인터랙션과 애니메이션, 그리고 패럴렉스 효과에 대해 기록해보려 합니다.
이번 글에서는 Part 1: 텍스트와 이미지가 등장하는 애니메이션을 먼저 소개합니다.
Part 2: 에서는 스크롤시 이미지가 확장되는 패럴렉스 스크롤에 대해 기록하려 합니다. 이것은 위의 웹사이트에서 테스트 해볼 수 있습니다.
1.텍스트를 한 글자씩 순차적으로 등장시키기
(그라디언트 마스크 효과로 텍스트가 부드럽게 나타나도록 구성)
2.텍스트 사이에 이미지(또는 영상)이 자연스럽게 확장되며 삽입되기
<div id="home">
<main>
<section class="cover web">
<p>
<span class="f" data-id="1">em</span>
<span class="f skip" data-id="2">
<span class="window">
<img src="..." alt="">
</span>
</span>
<span class="f" data-id="3">powering</span>
</p>
<p>
<span class="f" data-id="4">FANDOM</span>
<span class="f" data-id="5">&</span>
<span class="f" data-id="6">brand</span>
<span class="f skip" data-id="7">
<span class="window">
<img src="..." alt="">
</span>
</span>
</p>
<p>
<span class="f" data-id="8">through</span>
<span class="f skip" data-id="9">
<span class="window">
<img src="..." alt="">
</span>
</span>
<span class="f" data-id="10">data</span>
</p>
</section>
</main>
</div>
span {
mask-image: linear-gradient(90deg, #fff 33.3%, rgba(255, 255, 255, 0.1) 66.6%);
mask-position: 100% 100%;
mask-size: 300% 100%;
transition: mask-position 1s cubic-bezier(0.6, 0, 0.2, 1);
&.on {
mask-position: 0 100%;
}
&.skip {
mask-image: none;
}
}
span.f[data-id='2'].on,
span.f[data-id='7'].on,
span.f[data-id='9'].on {
animation: expandWidthBounce 1s forwards;
.window {
width: calc(240 / 1920 * 100vw);
opacity: 1;
}
}
mask-image: linear-gradient(90deg, #fff 33.3%, rgba(255, 255, 255, 0.1) 66.6%);
mask-image는 보이게 할 영역과 가릴 영역을 지정하는 속성입니다.
이 예제에서는 왼쪽 33%는 완전히 보임(#fff), 오른쪽 66%는 점점 투명해짐.
즉, 마스크 이미지가 왼→오 방향으로 흘러가며 텍스트가 점점 드러나는 효과를 만듭니다.
💡 mask-image는 background-image와 사용 방식이 거의 같습니다.
다만, 배경이 아닌 보임/숨김을 제어하는 용도입니다.
mask-position: 100% 100%;
mask-position은 mask-image가 시작되는 위치를 지정합니다.
100% 100%이면 마스크가 요소의 오른쪽 아래에서 시작합니다.
이후 애니메이션을 통해 mask-position을 0 100%으로 이동시킴으로써 마스크가 왼쪽으로 이동하며 글자를 드러냅니다.
&.on {
mask-position: 0 100%;
}
mask-size: 300% 100%;
mask-size는 마스크 이미지의 확대 비율을 지정합니다.
300% 100%이면 너비가 요소 자체의 3배 크기가 됩니다.
그래서 마스크가 이동할 때, 텍스트 전체를 부드럽게 감쌀 수 있게 됩니다.
즉, 넓은 마스크가 오른쪽에 숨어 있다가 왼쪽으로 슬라이딩되며 글자가 하나씩 보이도록 유도합니다.
속성 | 역할 |
---|---|
mask-image | 마스크의 형태 설정. 주로 gradient를 사용해 어느 부분이 보일지 정의. |
mask-position | 마스크의 시작 위치 지정. 처음에는 가려진 상태에서 시작해 점차 드러냄. |
mask-size | 마스크의 전체 크기 설정. 더 넓게 잡아야 마스크가 이동하며 자연스럽게 나타남. |
일부 브라우저(특히 Safari)에서는 mask- 대신 -webkit-mask-를 사용해야 하므로 크로스 브라우징 시 아래와 같이 쓰는 걸 추천합니다.
span {
-webkit-mask-image: linear-gradient(...);
mask-image: linear-gradient(...);
}
$(document).ready(function () {
setTimeout(function () {
$('.f').each(function () {
$(this).addClass('on');
});
}, 1500); // 1.5초 후 등장
});
저는 프로젝트에 제이쿼리를 사용했습니다.
document.addEventListener('DOMContentLoaded', function () {
setTimeout(function () {
document.querySelectorAll('.f').forEach(function (element) {
element.classList.add('on');
});
}, 1500);
});
📎 실제 반응형이 구현된 데모는 https://www.flatten.co.kr 에서 확인해보세요!
다음 글에서는
이미지가 스크롤에 따라 커지며 화면 전환되고,
패럴렉스 효과로 부드럽게 연결되는 구조에 대해 소개합니다.
짧은 시간 안에 디자인, 인터랙션, 반응형까지 챙겨야 했던 프로젝트였지만
오히려 덕분에 많은 기술을 테스트하고 정리할 수 있었던 기회였습니다.
다음 글에서는 패럴렉스와 Lenis.js 스크롤 제어까지 다뤄볼게요.
읽어주셔서 감사합니다!