[CSS] Pure CSS Parallax Websites

HYl·2022년 3월 24일
15
post-thumbnail


Parallax는 거의 JavaScript를 사용하여 처리되며, scroll 이벤트를 통하여 이벤트 핸들러에서 직접 DOM을 직접 수정하여 불필요한 reflowspaints 를 발생시킨다.

따라서, 브라우저 렌더링 파이프라인과 동기화되지 않은 상태에서 발생하여 프레임이 손실되고 버벅거린다.

그러나 모두 부정적인 것만은 아니다, requestAnimationFrame , DOM 업데이트의 지연은 parallax websites 을 긍정적으로 바꿀 수 있다.

결과적으로는, 만약 JavaScript의 의존성을 완전히 제거할 수 있다면 어떨까?

parallax effectCSS 로 구현하면, 모든 문제가 해소되고 브라우저가 hardware acceleration 을 이용할 수 있기 때문에 compositor가 모든 것을 처리할 수 있게된다. 그 결과, 프레임 rate가 일정하고, 스크롤이 매우 부드러워진다.


The theory

html

<div class="parallax">
  <div class="parallax__layer parallax__layer--back">
    <div class="title">This is the "back" background</div>
  </div>
  <div class="parallax__layer parallax__layer--base">
    <div class="title">This is the "base" background</div>
  </div>
</div>

css

* {
  margin: 0;
  padding: 0;
}

.parallax {
  perspective: 1px;
  height: 100vh;
  overflow-x: hidden;
  overflow-y: auto;
  font-size: 200%;
}
.parallax__layer {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  padding: 100vh 0;
}
.parallax__layer--base {
  transform: translateZ(0);
}

.parallax__layer--back {
  transform: translateZ(-1px);
}

.title {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

.parallax

parallax class 는 parallex magic 이 발생하는 곳이다.
heightperspective 를 정의하면, 원근범이 중심에 잠기므로 고정된 원점 3D 뷰포트가 생성된다.
overflow-y: auto 를 설정하면 요소 내부의 콘텐츠를 일반적인 방법으로 스크롤할 수 있지만, 하위 요소는 고정된 시점을 기준으로 렌더링된다. 이것이 parallax 효과를 만드는 핵심이다.

.parallax__layer

이름에서 알 수 있듯이 parallax 효과가 적용되는 콘텐츠의 레이어를 정의한다. 콘텐츠 흐름에서 요소를 꺼내 컨테이너의 공간을 채우도록 설정한다.

.parallax__layer--base & .parallax__layer--back

parallax 요소를 Z축을 따라 변환하여 (parallax 요소를 더 멀리 이동하거나 뷰포트에 더 가깝게 이동) parallax 요소의 스크롤 속도를 결정하는 데 사용된다. 간략하게 하기 위해 2개의 레이어 속도만 정의했다. 추후에 더 추가할 예정이다.

결과물을 살펴보면, "back" background font size가 줄어든 것처럼 보인다. 이처럼 3D 변환을 사용하면 요소의 크기가 변경되는 것처럼 보이는 부작용이 발생한다.

Depth correction 내용을 보며 이 문제를 해결해보자.


Depth correction

parallax 효과는 3D 변환을 사용하여 생성되므로 요소를 Z축을 따라 변환하면 뷰포트에 더 가까이 또는 더 멀리 이동하면 요소의 유효 크기가 변경되는 부작용이 있다. 이를 방지하기 위해서는 원래 크기로 렌더링되도록 요소에 scale() 변환을 적용해야 한다.

.parallax__layer--back {
  transform: translateZ(-1px) scale(2);
}

scale1 + (translateZ * -1) / perspective 으로 계산할 수 있다. 예를 들어 viewport perspective 을 1px로 설정하고 Z축을 따라 요소 -2px 를 변환하면 scale 계수는 3이 된다.


Controlling layer speed

Layer 속도는 perspective 과 Z 변환값의 조합에 의해 제어된다다. 음의 Z 값을 가진 요소는 양의 값을 가진 요소보다 느리게 스크롤된다. 값이 0 에서 멀어질수록 Parallax 효과가 두드러진다. (즉, translateZ(-10px)translateZ(-1px)보다 느리게 스크롤된다).


Parallax sections

앞의 예에서는 매우 간단한 내용을 사용하여 기본적인 기술을 설명했지만, 대부분의 Parallax 사이트는 페이지를 다른 효과를 적용할 수 있는 개별 섹션으로 나눈다. 방법은 아래와 같다.

먼저 layers 를 그룹화하기 위한 parallax__group 요소가 필요하다.

<div class="parallax">
  <div class="parallax__group">
    <div class="parallax__layer parallax__layer--back">
      ...
    </div>
    <div class="parallax__layer parallax__layer--base">
      ...
    </div>
  </div>
  <div class="parallax__group">
    ...
  </div>
</div>
.parallax__group {
  position: relative;
  height: 100vh;
  transform-style: preserve-3d;
}

이 예에서는 각 그룹이 뷰포트를 채우고 높이를 100vh로 설정하지만 필요에 따라 각 그룹에 임의의 값을 설정할 수 있다.
transform-style: preserve-3d 는 브라우저가 parallax_layer 요소와 위치를 평평하게 하는 것을 방지한다. position: relative는 자식 parallax_layer 요소를 그룹에 상대적으로 배치하기 위해 사용된다.

요소를 그룹화할 때 기억해야 할 중요한 규칙 중 하나는 그룹의 내용을 클리핑할 수 없다는 것이다.
parallax__groupoverflow: hidden 을 적용하면 Parallax 효과가 사라진다. 클리핑되지 않은 콘텐츠는 하위 요소가 넘치게 되므로 방문자가 문서를 스크롤할 때 콘텐츠가 올바르게 표시/숨겨지도록 그룹의 z-index 값을 창의적으로 사용해야 한다.

설계마다 구현이 다르기 때문에 계층화에 대한 명확한 규칙은 없다. Parallax 효과가 어떻게 작동하는지 알 수 있다면 계층화 문제를 디버깅하는 것이 훨씬 쉽다. 그룹 요소에 간단한 변환을 적용하면 이 작업을 수행할 수 있다.

.parallax__group {
    transform: translate3d(700px, 0, -800px) rotateY(30deg);
}

Example - debug option

https://keithclark.co.uk/articles/pure-css-parallax-websites/demo3/

개발자 도구 > Layers

디버깅을 할 때, 개발자 도구를 열어서 Layers 를 클릭하여 들어가서 확인해보면 더 정확하 게 디버깅을 할 때 도움이 될 것 같다.


오류 해결

웹킷 기반 브라우저는 3D 공간으로 변환되고 확장되면서 요소의 유효 폭을 올바르게 계산하지 못하는 것이다. 이 버그로 인해 사용자는 overflow 속성으로 정의된 조건을 무시하고 콘텐츠를 가로로 스크롤할 수 있다. transform-originperspective-origin을 뷰포트 오른쪽에 고정함으로써 이 오류를 회피할 수 있다.

.parallax {
  perspective-origin-x: 100%;
}
.parallax__layer {
  transform-origin-x: 100%;
}

REFERENCE

https://keithclark.co.uk/articles/pure-css-parallax-websites/

profile
꾸준히 새로운 것을 알아가는 것을 좋아합니다.

0개의 댓글