hermes-hub/.agents/skills/frontend-design/imagery.md

226 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Imagery & Icons — No Stock, No Emoji
> Pictures are where generated sites collapse. The AI default is: stock photo with a gradient overlay, emoji instead of icons, and blobs for "visual interest." All three are instant tells (`anti-patterns.md` §3, §7, §8, §10). This file is what to do instead — in order of preference.
---
## The Imagery Decision Tree
Before adding any image, ask in order:
1. **Does this need an image at all?** Most marketing pages are improved by removing images. Typography is the design (`SKILL.md` principle 2). A strong headline on generous whitespace beats a mediocre photo.
2. **Can it be a CSS/SVG composition?** Covers, mockups, product visuals, data — abstract compositions read as designed and cost kilobytes (`performance.md`).
3. **Can it be a real photo with real art direction?** Only if real photographs exist (client photos, product shots, documentary sources). Never invented stock.
4. **Nothing above works?** Then the section is the wrong section. Cut it.
The tell: if you're searching a stock site for "team collaborating laptop" — the image has no reason to exist.
---
## CSS/SVG Art Direction (the default)
Abstract compositions are the house style for generated UI: they always match the token system, they never look stock, and they ship in bytes. Build them from the same tokens as the page — same surface, ink, hairline, accent.
### The vocabulary
| Composition | Build | Use for |
|---|---|---|
| **Rules & columns** | 1px lines, `repeating-linear-gradient` | Architecture, editorial, "structure" |
| **Concentric circles** | Nested `border` circles, one accent ring | Sound, music, focus |
| **Halftone / dot grid** | `radial-gradient` repeated | Print heritage, texture |
| **Grid artifacts** | Visible column rules + one filled cell | Swiss, data, "system" |
| **Layered planes** | 23 offset rectangles, one in accent | Product surfaces, layers |
| **Chart as image** | Simple SVG bars/lines with mono labels | Metrics, proof |
| **Poster crop** | Big numeral or letter, cropped by overflow | Covers, features |
```css
/* Dot grid — pure CSS texture */
.art--halftone {
aspect-ratio: 4 / 5;
background-image: radial-gradient(var(--ink) 1px, transparent 1.2px);
background-size: 14px 14px;
/* fade it: one clean idea, not wallpaper */
-webkit-mask-image: linear-gradient(#000 40%, transparent);
mask-image: linear-gradient(#000 40%, transparent);
}
/* Concentric — one accent ring as the "subject" */
.art--rings {
aspect-ratio: 1 / 1;
border-radius: 50%;
border: 1px solid var(--hairline);
display: grid; place-items: center;
}
.art--rings::before {
content: ''; width: 62%; height: 62%;
border-radius: 50%;
border: 1px solid var(--accent);
}
```
Rules:
- **One idea per composition.** Rules + circles + dots + gradient = mush. Pick one, execute precisely.
- Compositions live inside a defined box (`aspect-ratio`), like a print plate — not floating decor behind text.
- The accent gets one moment: one ring, one filled cell, one label. (`color.md` 510% rule still applies.)
- Mark decorative art `aria-hidden="true"` (`accessibility.md`); if it *carries* information, it's an `<svg>` with a `<title>` or adjacent text.
- Working examples: the cover plates in `examples/example-magazine.html`, the album covers in `examples/example-brutalist.html`, the CSS dashboard in `examples/example-saas.html`.
---
## If Photography Is Real
Photography is only an option when real photographs exist. Then direct it like a photo editor, not a stock buyer:
### The art direction brief (write it before choosing)
- **One light source, one lens, one palette.** Mixed light and mixed lenses read as assembled, not shot.
- **Documentary, not posed.** The workshop, not the handshake. Hands on work, not people pointing at whiteboards.
- **No smiling-person-with-laptop.** Ever. (`anti-patterns.md` §10.)
- **Crop with intent.** Full-bleed, hard edges, cropped off-grid — a brave crop is design; a centered subject is a placeholder.
- **Treatment is a system:** same ratio family, same caption style, same edge treatment across the page. Two ratios maximum.
### Sourcing, honestly
| Source | Verdict |
|---|---|
| Client/team photos (even phone-shot) | Best — real beats polished |
| Real product photography | Required for products |
| Public archives (museum/library, CC-licensed) | Great for editorial and history |
| UGC with permission | Good for lifestyle and community |
| Any stock site, any "similar images" | No |
### Treatment rules
- **No gradient overlays on text.** If text needs a scrim to be readable, the photo is wrong or the text is misplaced. (Scrim = gradient = `anti-patterns.md` §1's family.)
- Captions are design: mono or small italic, real information — who, where, when. "Image: ..." with a real fact, not "photo."
- Duotone/grayscale only as a system across all photos, using tokens.
- Grain/texture: once per page, subtle. (Also `aesthetics.md` §5.)
---
## Iconography
Icons are typography for concepts: one voice, measured precisely.
### The system
| Rule | Value |
|---|---|
| Sets | **Lucide**, **Phosphor**, **Tabler**, **Feather** — pick ONE per project |
| Stroke | 1.5px (2px at 24px+), `stroke-linecap="round"` or `square` — consistent |
| Sizes | 16px (inline), 20px (UI), 24px (feature) — one size per context |
| Color | `currentColor`, always — icons inherit ink/muted like text |
| Alignment | Optically centered; 16px icons align to the x-height of body text |
| In UI chrome | Icon + label for anything ambiguous; icon-only with `aria-label` |
### The correct way to ship an icon
```html
<!-- Icon + text label (default) -->
<a href="/docs" class="nav-link">
<svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="1.5"
stroke-linecap="round" stroke-linejoin="round">
<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/>
<path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/>
</svg>
<span>Docs</span>
</a>
<!-- Icon-only button (needs a name) -->
<button aria-label="Close menu" class="icon-btn"></button>
```
- **Inline SVG, not icon fonts** (fonts break, shift, and announce garbage).
- Same set means same grid (24×24 viewBox), same stroke, same corner philosophy. Never mix Lucide with Font Awesome on one page.
- `aria-hidden="true"` on decorative icons; labels do the naming (`accessibility.md`).
- **Emoji are not icons.** In product UI: never. In content (a genuinely playful brand voice): maybe once, on purpose. (`anti-patterns.md` §3.)
---
## Avatars & Logo Bars
### Avatars
- **Initials, not mystery silhouettes.** Two letters in a circle using tokens beat every default placeholder.
```css
.avatar {
width: 32px; height: 32px;
border-radius: 50%;
display: grid; place-items: center;
background: var(--surface-sunken);
color: var(--ink);
font-size: var(--text-xs);
font-weight: 500;
letter-spacing: 0.02em;
}
```
- Real photos only if they're real people (testimonials: real quotes or no testimonials — `checklist.md` §Content).
### Logo bars ("trusted by")
- Only logos of **real, permissioned customers.** Invented logos for invented companies is the definition of `anti-patterns.md` §15 — lying.
- Treatment: monochrome at ~60% ink, hover restores full ink; uniform optical height (1824px), real wordmarks, no fake " Inc.".
- No logo bar at all > a fake one. A single specific sentence ("Vercel's design team uses this weekly") beats twelve gray rectangles.
---
## Favicon & Social Image (the 10-minute craft pass)
Agents ship pages with no favicon and a blank social card — the two places everyone *will* look.
### Favicon
```html
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="icon" href="/favicon.png" sizes="32x32"> <!-- fallback -->
<link rel="apple-touch-icon" href="/apple-touch-icon.png"> <!-- 180×180 -->
```
Design it like a poster at 16px: the mark's single element (one letter, one ring, one bar) in accent or ink on surface. Test at 16px — if unreadable, simplify.
### Open Graph / Twitter card
```html
<meta property="og:image" content="https://example.com/og/issue-14.png">
<meta name="twitter:card" content="summary_large_image">
```
- 1200×630, designed like a print cover: brand type, issue/product name, one accent moment, real metadata.
- It should look like the site — same face, same tokens. Not a screenshot of the hero, not a logo centered in gray.
- Zero-OG-image pages render as blank gray rectangles in every share. That's the first impression most visitors get.
---
## Imagery Anti-Patterns
| ❌ Don't | ✅ Do |
|---|---|
| Stock photo + gradient overlay + headline on top | CSS/SVG composition, or photo with real crop and real caption |
| Emoji as feature/status icons | One icon set, inline SVG, `currentColor` |
| Blob/mesh backgrounds "for depth" | Whitespace, hairlines, one composition per section |
| Mystery-man avatar placeholder | Initials in a token circle |
| Fake logo bar of invented companies | Real customers, or a specific sentence, or nothing |
| Icon fonts / emoji symbols for UI glyphs | Inline SVG from one set |
| Mixing icon styles (solid + outline, two sets) | One set, one stroke, one size per context |
| alt="image" / alt="IMG_2841" | Real alt text or `alt=""` when decorative |
| Photos in 5 aspect ratios across one page | One ratio family, treated as a system |
| No favicon, no og:image | Designed 16px mark + 1200×630 social cover |
| AI-generated "photo of our team" | No photography exists → composition or no image |
---
## Ship Gate
- [ ] Every image passed the decision tree (needed? composition? real photo? otherwise cut)
- [ ] Compositions: one idea each, built from tokens, `aria-hidden` or titled
- [ ] Photos (if any): real, one light, one crop system, captioned with facts
- [ ] Icons: one set, one stroke, `currentColor`, labeled or `aria-label`-ed
- [ ] Favicon designed and tested at 16px
- [ ] og:image designed like a cover, same type system
- [ ] No emoji in UI, no stock, no blobs — zero exceptions
See also: `anti-patterns.md` (§3, §7, §8, §10, §15, §16), `performance.md` §Images, `accessibility.md` §Images & Media, `content.md` (captions are copy).