디자인 SSOT 를 세우고 3D 를 배경 재질로 되돌린다
지적받은 것: 모바일 마진·패딩, 폰트 웨이트, 버튼 스타일 불일치, SSOT,
스크롤바, 모바일 메뉴, 그리고 3D 를 왜 상자에 넣었는지.
3D 의 역할을 잘못 잡았다
lusion.co 의 "3D 는 액자 안"은 3D 자체가 상품일 때의 규칙이다.
우리는 절차를 파는데 액자에 넣을 상품이 없어 "저 상자는 뭐냐"가 됐고,
의미를 게이트 판독기가 자막으로 설명하고 있었다.
이 씬의 역할은 재질이다. 배경으로 되돌리고 값을 전부 낮췄다 —
테두리 광 0.85->0.42, 알파 0.72->0.34, UV 경계 0.05->0.17, 이동 60%
ResizeObserver 로 캔버스를 따라가게 했다. window.resize 만 듣는 동안
히어로 높이 변화를 놓쳐 배경이 화면의 3분의 2만 덮었다
SSOT
웨이트 6종(400/500/560/600/620/660) -> 3종. 셋은 토큰에 없던 값이었다
.btn + btn-solid/btn-quiet. 두 버튼이 높이 36 vs 44, 패딩 16 vs 8,
테두리 1px vs 0, 웨이트 400 vs 500 이었다
--header-h. 간격을 clamp 로 바꾸자 관계가 끊겨 h1 이 헤더 뒤로 들어갔다
--space-5~8 과 --gutter 를 clamp 로. 고정이면 모바일 여백이 화면의 26%
scrollbar-color 지정
모바일
좌우 여백 24 -> 32px, 섹션 상하 112 -> 56px
헤더에 섹션 앵커 4개. 900px 미만은 details 기반 메뉴(JS 0바이트)
패럴랙스는 섹션마다 다른 말을 한다
히어로 글자 상승 / 배경 하강 — 반대 방향이라야 시차가 보인다
파이프라인 단계명 고정, 산출물만 지연 — 인과
재료 타일이 서로 다른 깊이 — 표면은 한 겹이 아니다
프리플라이트 뒤 항목일수록 늦게 — 로그는 흐른다
수치 없음. 의도적 정지 — 계기판의 바늘은 떨지 않는다
스킬
three.md §0-A 를 역할별로 갈랐다. "액자 안"만 적어둔 것이 잘못된
일반화였고 내가 거기 그대로 걸렸다. 재질일 때의 값 교정을 실측으로 남김
tokens.md 웨이트·컨트롤·헤더 높이·반응형 간격 — 토큰이 아예 없던 네 축
motion.md 섹션별 패럴랙스 배정표. 움직이지 않는 것도 결정이다
390px 실렌더: 가로 스크롤 0, 대비 실패 0, 웨이트 3종, radius 2종. 테스트 22개 통과
This commit is contained in:
parent
4b853355e3
commit
9c9ab2de7e
18 changed files with 606 additions and 231 deletions
|
|
@ -1,4 +1,5 @@
|
|||
---
|
||||
import { ko, en } from "../i18n/content";
|
||||
import "../styles/fonts.css";
|
||||
import "../styles/tokens.css";
|
||||
import "../styles/base.css";
|
||||
|
|
@ -18,6 +19,10 @@ const FONT_CSS = {
|
|||
|
||||
const alt = lang === "ko" ? "/en/" : "/";
|
||||
|
||||
// 헤더 내비게이션. 본문과 같은 콘텐츠 파일에서 온다 — 라벨을 레이아웃에
|
||||
// 하드코딩하면 두 언어판이 어긋난다.
|
||||
const nav = (lang === "ko" ? ko : en).nav;
|
||||
|
||||
// 파비콘: 페이지의 스파인 모티프를 그대로 쓴 단순 기하 마크.
|
||||
// data: URI 안의 SVG 는 상위 문서의 커스텀 프로퍼티를 읽지 못한다.
|
||||
// 하드 게이트 #1 의 유일한 예외이고, 값은 tokens.css 와 손으로 맞춘다.
|
||||
|
|
@ -91,12 +96,35 @@ const FAVICON =
|
|||
</svg>
|
||||
<span>designpaca</span>
|
||||
</a>
|
||||
<nav aria-label={lang === "ko" ? "언어" : "Language"}>
|
||||
|
||||
<nav class="nav-main" aria-label={lang === "ko" ? "섹션" : "Sections"}>
|
||||
{nav.items.map((i) => <a href={i.href}>{i.label}</a>)}
|
||||
</nav>
|
||||
|
||||
<div class="header-end">
|
||||
{/* 언어는 국가가 아니다. 국기 아이콘을 쓰지 않는다 */}
|
||||
<a href={alt} hreflang={lang === "ko" ? "en" : "ko"} lang={lang === "ko" ? "en" : "ko"}>
|
||||
<a
|
||||
class="btn btn-quiet btn-sm"
|
||||
href={alt}
|
||||
hreflang={lang === "ko" ? "en" : "ko"}
|
||||
lang={lang === "ko" ? "en" : "ko"}
|
||||
>
|
||||
{lang === "ko" ? "English" : "한국어"}
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
{/* 모바일 메뉴. details 라 JS 가 0바이트이고, 키보드와
|
||||
스크린리더 대응이 브라우저 기본으로 온다 */}
|
||||
<details class="nav-mobile">
|
||||
<summary class="btn btn-quiet btn-sm" aria-label={nav.menu}>
|
||||
<svg viewBox="0 0 16 16" width="15" height="15" aria-hidden="true">
|
||||
<path d="M2 4h12M2 8h12M2 12h12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
|
||||
</svg>
|
||||
</summary>
|
||||
<div class="nav-sheet glass">
|
||||
{nav.items.map((i) => <a href={i.href}>{i.label}</a>)}
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
|
@ -160,7 +188,7 @@ const FAVICON =
|
|||
left: 0;
|
||||
right: 0;
|
||||
z-index: 3;
|
||||
padding-inline: var(--space-4);
|
||||
padding-inline: var(--gutter);
|
||||
}
|
||||
.header-inner {
|
||||
max-width: 1180px;
|
||||
|
|
@ -176,28 +204,75 @@ const FAVICON =
|
|||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
font-weight: 560;
|
||||
font-weight: var(--weight-medium);
|
||||
letter-spacing: -0.01em;
|
||||
text-decoration: none;
|
||||
}
|
||||
.mark { color: var(--accent); flex: none; }
|
||||
.site-header nav a {
|
||||
/* ---- 섹션 내비 (데스크톱) --------------------------------- */
|
||||
.nav-main {
|
||||
display: none;
|
||||
gap: var(--space-1);
|
||||
margin-inline: auto;
|
||||
}
|
||||
.nav-main a {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 36px;
|
||||
min-height: var(--control-h-sm);
|
||||
padding-inline: var(--space-3);
|
||||
border-radius: var(--radius-sm);
|
||||
font-size: inherit;
|
||||
background: var(--glass-tint-2);
|
||||
border: 1px solid var(--glass-edge);
|
||||
/* muted 로 두면 유리 위에서 2.59:1 이다. 언어 전환은 내비게이션이지
|
||||
보조 정보가 아니므로 ink 로 올린다(하드 게이트 #7) */
|
||||
color: var(--ink);
|
||||
color: var(--ink-muted);
|
||||
text-decoration: none;
|
||||
transition: color var(--dur-instant) var(--ease-out),
|
||||
background var(--dur-instant) var(--ease-out);
|
||||
background-color var(--dur-instant) var(--ease-out);
|
||||
}
|
||||
.nav-main a:hover { color: var(--ink); background: var(--glass-tint); }
|
||||
|
||||
.header-end {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
flex: none;
|
||||
}
|
||||
|
||||
/* ---- 모바일 메뉴 ------------------------------------------
|
||||
details 를 쓴 이유는 JS 0바이트 때문만이 아니다. 열림 상태,
|
||||
Esc, 포커스 순서, aria-expanded 를 브라우저가 이미 맞게 한다.
|
||||
직접 만들면 그 넷을 전부 다시 구현해야 하고 보통 틀린다. */
|
||||
.nav-mobile { position: relative; }
|
||||
.nav-mobile > summary {
|
||||
list-style: none;
|
||||
padding-inline: 0;
|
||||
width: var(--control-h-sm);
|
||||
}
|
||||
.nav-mobile > summary::-webkit-details-marker { display: none; }
|
||||
.nav-mobile > summary::marker { content: ""; }
|
||||
|
||||
.nav-sheet {
|
||||
position: absolute;
|
||||
top: calc(100% + var(--space-2));
|
||||
right: 0;
|
||||
min-width: 11rem;
|
||||
padding: var(--space-2);
|
||||
display: grid;
|
||||
gap: 2px;
|
||||
z-index: 4;
|
||||
}
|
||||
.nav-sheet a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: var(--control-h);
|
||||
padding-inline: var(--space-3);
|
||||
border-radius: var(--radius-sm);
|
||||
color: var(--ink);
|
||||
text-decoration: none;
|
||||
}
|
||||
.nav-sheet a:hover { background: var(--glass-tint-2); }
|
||||
|
||||
@media (min-width: 900px) {
|
||||
.nav-main { display: flex; }
|
||||
.nav-mobile { display: none; }
|
||||
}
|
||||
.site-header nav a:hover { color: var(--ink); background: var(--glass-tint); }
|
||||
|
||||
.site-footer {
|
||||
padding-block: var(--space-6);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue