Files
guizang-social-card-skill/references/screenshot-treatment.md
T
郭浩andClaude Opus 4.7 82d221bb90 v0.13 baseline · git 初始化 + 仓库瘦身
把所有本地 demo / 测试 / 上传图 / 调试脚本搬入 local-tests/,写
.gitignore 忽略整个测试目录与 node_modules/。本次起 skill 仓库
只跟踪:SKILL.md / HANDOFF.md / PRODUCT.md / assets/(3 模板)/
references/(15 规则文档)/ agents/openai.yaml / validate-social-deck.mjs
/ package.json + lock。

历次版本(v0.1-v0.12)的全部实质改动已包含在当前文件状态中——
HANDOFF.md 的版本历史段保留作为时间轴文字记录,但代码层面以
此 commit 为唯一基线,后续逐次 commit 对应 HANDOFF.md 新增段落。

HANDOFF/PRODUCT/category-cookbook/components/style-system 中的
demo 路径引用已加 local-tests/ 前缀。SKILL.md Step 5 line 190 的
'social-card-<slug>/' 是下游用户工作区的命名约定,未改动。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 22:00:55 +08:00

6.1 KiB
Raw Blame History

Screenshot Treatment

When the user supplies an app / web / code / dashboard screenshot, do not drop it raw into a .frame-img. The aspect ratio mismatch crops UI and the harsh edge looks SaaS-y. Use .frame-shot instead — a sibling class added to both seed templates.

When to reach for it

  • App / Web UI capture — anything with a status bar, tab bar, toolbar, or window chrome.
  • Code / terminal screenshots.
  • Dashboard / chart screenshots that need to keep every label readable.
  • IDE captures where text density matters more than composition.

For photographic content (people, scenery, products) — keep using .frame-img. The treatments below assume a pixel-perfect UI source where contain-fit is non-negotiable.

Anatomy

.frame-shot.r-{ratio}.corners-{sq|sm|md}.shadow-{none|soft|ed}.bg-{paper|grid|dot|grey-1|ink}.inset-{none|sub|bal}
  └─ <img src="…">         (object-fit: contain by default)

Optional wrapping:

.device-browser
  └─ .frame-shot.r-16x10.bg-paper
       └─ <img>

.device-phone
  └─ .frame-shot.r-3x4.bg-paper
       └─ <img>

Parameters

Pick six values before writing the markup. Treat this like the M16 cover decision tree — pick once, don't fiddle mid-build.

1. r-* ratio (required, matches slot)

Class Use
r-16x10 Default for app / web shots, looks like a real window
r-16x9 Landscape video / dashboard / wide chart
r-4x3 Classic desktop window, legacy app
r-3x2 DSLR-style — only if the source is photographic UI mockup
r-1x1 App icon / square widget
r-3x4 Mobile portrait shot (pair with .device-phone)
r-21x9 Multi-monitor / ultra-wide / WeChat hero

2. corners-* (style-locked default)

  • Swiss default: corners-sq. Use corners-sm only if the slot has surrounding shadow or chrome.
  • Editorial default: corners-sm (6 px). Bump to corners-md (14 px) for "cutout" feel on paper.

Never go above 14 px — anything bigger reads as iOS marketing.

3. shadow-* (style-locked default)

  • Swiss → shadow-none 90% of the time. shadow-soft only on screenshots that float on bg-grid / bg-dot. shadow-ed adds a 1px outline as part of the shadow — reserve for hero shots.
  • Editorial → shadow-soft on bg-paper-2 is the warm default. shadow-ed for hero shots.

4. bg-* (the screenshot "stage")

Token Swiss role Editorial role
bg-paper Default plain stage Same
bg-paper-2 n/a Default warm stage
bg-grey-1 Default plain stage n/a
bg-grid Engineering / data Field-notes engineering
bg-dot Subtle structure Subtle structure
bg-ink Dark-mode UI shot Dark-mode UI shot

Backgrounds are never accent-coloured. If the screenshot needs an accent emphasis, add a .t-cat chip or .kicker next to it — don't tint the stage.

5. inset-* (padding between shot and stage)

  • inset-none — image fills the frame. Use when the screenshot itself already has window chrome.
  • inset-sub (Swiss 20 px / Editorial 24 px) — default. Lets the stage breathe.
  • inset-bal (Swiss 48 px / Editorial 56 px) — when the shot is busy and needs to feel calm.

6. fit-cover (override)

Default is object-fit: contain — this is the whole point of .frame-shot. Only add .fit-cover when:

  • The slot is a hero where exact pixels of the source don't matter (e.g. a code shot used as a background pattern).
  • The user explicitly says they want the shot cropped.

Device chrome

Two wrapper classes ship with the seeds. They wrap a .frame-shot:

.device-browser

Adds a 32–36 px chrome bar with traffic-light dots. Use for web / desktop app captures.

<div class="device-browser">
  <div class="frame-shot r-16x10 bg-paper inset-none">
    <img src="assets/website.png" alt="Linear inbox">
  </div>
</div>

Pair with shadow-soft on the screenshot itself for a desk-photo feel.

.device-phone

Wraps a 3:4 or 16:10 shot in an ink-coloured bezel with 18-24 px rounded inner corners. Use for mobile captures.

<div class="device-phone">
  <div class="frame-shot r-3x4 bg-paper inset-none">
    <img src="assets/app.png" alt="WeChat detail">
  </div>
</div>

Don't stack corners-md on top of .device-phone — the bezel already rounds the inner shot.

Safe-area cropping

When the user delivers a full-screen capture (1290×2796 iOS / 1080×2400 Android / 1920×1080 desktop), do not show the status bar, dock, or browser tab strip unless that chrome is the subject. Crop before importing:

  1. Trim the iOS / Android status bar (top 47-59 px on retina).
  2. Trim the home indicator / nav gesture bar (bottom 34 px on iOS).
  3. For desktop: trim everything above the page content unless wrapped in .device-browser.

If you can't crop ahead of time, use object-position: center 6% to bias the visible region downward — but this is a workaround, not the preferred path.

Style cheat-sheet

Two recipes that cover 80% of cases.

Swiss product demo — pure stage, no shadow:

.frame-shot.r-16x10.corners-sq.shadow-none.bg-grey-1.inset-bal

Editorial deep-dive — desk-photo warmth:

.frame-shot.r-16x10.corners-sm.shadow-soft.bg-paper-2.inset-sub

For comparison shots (before / after), use the same parameters on both — different treatment between cells reads as inconsistency, not contrast.

Validator

validate-social-deck.mjs doesn't have a screenshot-specific rule (yet). The existing R1 / R2 / R5 still apply: a .frame-shot that overflows or pushes the footer is still a fail.

If a deck mixes .frame-img and .frame-shot on the same poster, that's usually a smell — pick one approach per poster.