배경을 뷰포트에 고정하고, 게이트 씬을 파이프라인으로 옮긴다
"스크롤할 때 이미지가 고정되어 원경처럼 보이는 게 패럴랙스의 꽃"이라는
지적이 맞았다. 느리게 같이 움직이는 것으로는 그 인상이 안 나온다 —
속도만 다를 뿐 방향이 같기 때문이다.
고정 배경
background-attachment: fixed 는 iOS Safari 가 GPU 메모리 때문에
throttle 해서 스크롤 중 배경이 튄다. 쓰지 않았다.
섹션에 clip-path: inset(0) 을 걸어 position: fixed 의 컨테이닝 블록으로
만들었다. 배경이 화면에 멈춘 채 그 섹션 안에서만 보인다.
실측: 스크롤 1000px 구간에서 viewportTop 이 계속 0.
대가 둘을 받아들였다
조상에 transform/filter/mask 를 못 쓴다 — 페이드 마스크를 포기했다
prefers-reduced-motion 에서는 absolute 로 되돌린다
전부 고정하지는 않았다. 종이는 손에 닿는 거리라 원경으로 두면 거짓말이다
재료·설치·프리플라이트 fixed 원경
사례 drift 두 결과물이 흐르는 자리
조판 drift 종이는 가깝다
게이트 씬을 파이프라인으로
히어로에서는 의미를 판독기가 자막으로 설명해야 했다. 그림이 스스로
말하지 못한다는 뜻이다. 옆에 여섯 단계가 적힌 자리로 옮기니 자막이
필요 없어졌다 — 판을 통과하면 그 단계가 켜진다.
캔버스는 sticky, 진행도는 섹션에서 읽는다.
travel 을 섹션 높이로 잡았더니 캔버스가 사라진 뒤에도 진행이 남아
6단계 중 3단계에서 멈췄다. (섹션 높이 - 뷰포트 높이)로 고쳤다.
캔버스 위 텍스트 대비 14.2:1.
스킬
motion.md 패럴랙스의 원형은 고정 · clip-path 기법과 그 대가
sticky 캔버스의 진행도 계산
three.md 씬의 의미는 옆의 콘텐츠가 반응할 때 성립한다.
자막이 필요하면 배치를 의심해라
This commit is contained in:
parent
1ed3c95542
commit
af3a08397e
12 changed files with 281 additions and 56 deletions
|
|
@ -448,6 +448,38 @@ JS 쪽 판정도 한 곳에 모은다. 설정이 도중에 바뀌면 반영한
|
|||
안 움직이는 섹션이 하나도 없으면 움직임에 의미가 없다는 뜻이고,
|
||||
`design.md` 에 "여기는 의도적으로 정지"라고 적어두지 않으면 다음 사람이 "빠뜨린 것"으로 보고 채운다.
|
||||
|
||||
### 패럴랙스의 원형은 "고정"이다
|
||||
|
||||
**배경이 뷰포트에 멈춰 있고 콘텐츠만 그 위를 지나갈 때 원경이 된다.**
|
||||
느리게 같이 움직이는 것으로는 그 인상이 안 나온다 — 속도만 다를 뿐 방향이 같기 때문이다.
|
||||
"패럴랙스를 넣었는데 티가 안 난다"의 절반은 이것이다.
|
||||
|
||||
**`background-attachment: fixed` 는 쓰지 마라.** iOS Safari 가 GPU 메모리 때문에 그것을
|
||||
throttle 해서 스크롤 중 배경이 튀거나 리셋된다.
|
||||
|
||||
대신 **부모를 `position: fixed` 의 컨테이닝 블록으로 만든다**:
|
||||
|
||||
```css
|
||||
.section { position: relative; clip-path: inset(0); } /* 컨테이닝 블록 + 클립 */
|
||||
.section > .bg { position: fixed; inset: 0; z-index: -1; }
|
||||
.section > .bg img { width: 100%; height: 100%; object-fit: cover; }
|
||||
```
|
||||
|
||||
`clip-path` 는 두 가지를 동시에 한다 — 배경을 섹션 밖으로 못 나가게 자르고,
|
||||
fixed 자식의 기준을 뷰포트가 아니라 **자기 자신**으로 잡아준다.
|
||||
그래서 배경이 화면에 고정되면서도 그 섹션 안에서만 보인다.
|
||||
|
||||
**두 가지 대가가 있다. 알고 써라.**
|
||||
|
||||
1. **조상에 `transform`·`filter`·`mask` 를 추가하면 즉시 깨진다.** 그것들도 컨테이닝 블록을
|
||||
만들기 때문에 fixed 가 섹션 기준이 되어 고정이 사라진다. 위아래 페이드 마스크를 얹고 싶어도
|
||||
못 얹는다 — 경계는 clip 으로 딱 잘리는 것을 받아들여야 한다
|
||||
2. `prefers-reduced-motion` 에서는 `position: absolute` 로 되돌려라. 고정 배경은
|
||||
스크롤 중 시각 부하가 크다
|
||||
|
||||
**전부 고정하지는 마라.** 가까이 있어야 할 재질(종이·질감)까지 원경으로 두면 거짓말이 된다.
|
||||
원경은 `fixed`, 중경은 아래의 비율 이동, 근경은 콘텐츠와 함께.
|
||||
|
||||
### 이동량은 절대값이 아니라 컨테이너 대비 비율이다
|
||||
|
||||
**패럴랙스가 "안 보인다"의 대부분은 이동량이 모자란 것이다.**
|
||||
|
|
@ -517,6 +549,25 @@ CSS-Tricks 의 예제도 `background-position: bottom 0px → bottom -400px`,
|
|||
너무 강하게 넣으면 안전한 이미지가 아니라 **없는 이미지**가 나온다.
|
||||
대비는 합성 방식으로 풀고, 이미지 자체는 볼 수 있게 만들어라.
|
||||
|
||||
### sticky 캔버스의 진행도는 섹션 높이가 아니다
|
||||
|
||||
캔버스를 `position: sticky; top: 0; height: 100dvh` 로 붙여두고 섹션이 지나가게 하는 패턴에서,
|
||||
진행도를 **섹션 높이로 나누면 안 된다.**
|
||||
|
||||
캔버스가 실제로 화면에 머무는 거리는 **(섹션 높이 − 뷰포트 높이)** 다.
|
||||
섹션 높이를 쓰면 캔버스가 위로 사라진 뒤에도 진행이 남아 **끝에 영영 도달하지 못한다.**
|
||||
|
||||
```js
|
||||
const travel = Math.max(section.getBoundingClientRect().height - innerHeight, 1);
|
||||
const progress = clamp(-section.getBoundingClientRect().top / travel, 0, 1);
|
||||
```
|
||||
|
||||
실측: 섹션 1493px · 뷰포트 900px 에서 섹션 높이로 나눴더니 6단계 중 **3단계에서 멈췄다.**
|
||||
`height - innerHeight` 로 바꾸자 6단계를 다 돌았다.
|
||||
|
||||
그리고 진행도의 기준 요소는 **캔버스가 아니라 섹션**이다. sticky/fixed 캔버스는 rect 가
|
||||
변하지 않으므로 자기 rect 로 재면 진행도가 고정된다.
|
||||
|
||||
### 배경도 한 섹션에 하나다
|
||||
|
||||
CSS 격자와 사진을 같이 깔았다가 걷어냈다. 두 배경이 서로 경쟁했고,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue