패럴랙스를 실제로 보이게 고치고 격자를 걷어낸다

"티가 안 난다"는 지적이 맞았다. 세 가지를 동시에 잘못하고 있었다.

1. 이동량이 모자랐다
   여유를 28% 잡아놓고 92px 만 움직였다. 스크롤 1800px 구간에서 5%다.
   공식은 이미지를 컨테이너보다 크게 만들고 초과분 전체를 움직이는 것.
   depth 0.45 -> 높이 145%, translateY(-31.03%). 같은 구간에서 374px.
   translateY(%) 는 자기 크기 기준이라 컨테이너 높이를 몰라도 맞는다.

2. overflow: hidden 이 view() 타임라인을 죽이고 있었다
   overflow: hidden 은 스크롤 컨테이너를 만들고, 그러면 자식의 view() 가
   문서가 아니라 그 상자를 기준으로 잡힌다. 이미지는 상자 안에서 늘 같은
   자리라 진행도가 고정된다. 콘솔 에러도 없고 computed 값도 정상이라
   두 스크롤 위치에서 transform 을 재보고서야 이동 0px 인 것을 알았다.
   잘라내는 일은 섹션의 overflow: clip 에 맡겼다.

3. opacity 로 눌러 이미지를 지웠다
   어두운 광원 사진을 opacity 0.5 로 깔면 검정도 빛도 같이 죽는다.
   mix-blend-mode: screen 으로 바꿨다 — 검정은 투명, 밝은 곳만 더해진다.
   그래서 불투명도 0.85~1.0 을 써도 본문 대비가 안전하다.
   생성 프롬프트도 같은 함정이었다. "어둡게"를 너무 강하게 넣어서
   안전한 이미지가 아니라 없는 이미지를 만들었다.

격자 배경 제거
   사진이 들어온 뒤로 배경이 두 겹이라 서로 경쟁했고 표로 읽혔다.
   배경도 한 섹션에 하나다.

스킬 motion.md 에 넷 다 반영
   이동량 공식 · overflow 함정 · screen 합성 · 배경은 한 겹
This commit is contained in:
Yun Chan 2026-08-20 15:57:40 +09:00
parent 5a18806fb6
commit 1ed3c95542
11 changed files with 181 additions and 85 deletions

View file

@ -419,67 +419,19 @@ a:hover { color: var(--accent); }
패럴랙스는 깊이 차가 보여야 성립한다. 배경이 단색이면 앞의 것이
px 어긋나 봐야 아무도 느낀다 기준면이 없기 때문이다.
그래서 배경을 깐다. 다만 이미지가 아니라 페이지가 주장하는 ,
간격 눈금 자체를 격자로 그린다. --grid-cell --space-5 . */
.bg-grid,
.bg-glow,
기준면은 `BgPhoto` 컴포넌트가 만든다.
CSS 그린 격자를 한동안 같이 깔았는데 걷어냈다. 사진이 들어온 뒤로는
배경이 겹이 되어 서로 경쟁했고, 격자는 배경이라기보다 표로 읽혔다.
배경도 섹션에 하나여야 한다. */
.has-bg {
position: relative;
isolation: isolate;
/* 배경 레이어는 위아래로 14% 삐져나온다(패럴랙스 여유).
clip 하지 않으면 삐져나온 부분이 이웃 섹션 위에 얹힌다
조판 섹션의 종이가 섹션 하단에 밝은 띠로 나타났다. */
/* 배경 이미지는 컨테이너보다 크고 패럴랙스로 움직인다.
clip 하지 않으면 초과분이 이웃 섹션 위로 넘친다. */
overflow: clip;
}
/* 섹션은 subgrid 이고 `.section > *` 전부 main 칼럼(561px) 배치된다.
절대배치라도 그리드 영역이 잡히면 그게 컨테이닝 블록이 되므로,
배경이 화면 가운데 561px 띠로만 깔렸다. 전체 폭으로 되돌린다. */
.bg-photo { grid-column: full; }
.bg-grid::before,
.bg-glow::before {
content: "";
position: absolute;
inset: -12% 0;
z-index: -1;
pointer-events: none;
}
.bg-grid::before {
background-image:
repeating-linear-gradient(to right,
var(--line-strong) 0 1px, transparent 1px var(--grid-cell)),
repeating-linear-gradient(to bottom,
var(--line-strong) 0 1px, transparent 1px var(--grid-cell));
/* 가장자리에서 지운다. 화면 끝까지 격자가 가면 표가 되어버린다 */
-webkit-mask-image: radial-gradient(135% 95% at 50% 45%, black 22%, transparent 92%);
mask-image: radial-gradient(135% 95% at 50% 45%, black 22%, transparent 92%);
opacity: 0.7;
}
/* 히어로의 두 광원이 페이지를 관통한다. 섹션마다 자리가 다르다 */
.bg-glow::before {
background:
radial-gradient(42% 46% at var(--glow-x, 78%) var(--glow-y, 32%),
color-mix(in oklab, var(--accent) 15%, transparent), transparent 70%),
radial-gradient(38% 42% at calc(100% - var(--glow-x, 78%)) 78%,
color-mix(in oklab, var(--glow-2) 13%, transparent), transparent 68%);
}
@media (prefers-reduced-motion: no-preference) {
@supports (animation-timeline: view()) {
/* 배경이 가장 느리다. 콘텐츠보다 적게 움직여야 뒤에 있는 것으로 읽힌다 */
.bg-grid::before { --par-from: -34px; --par-to: 34px; }
.bg-glow::before { --par-from: -58px; --par-to: 58px; }
.bg-grid::before,
.bg-glow::before {
animation: par linear both;
animation-timeline: view();
animation-range: cover 0% cover 100%;
}
}
}
/* ---- 유틸 -------------------------------------------------- */
.visually-hidden {
position: absolute;