afv-library/samples/webapp-template-app-react-sample-b2e-experimental/.a4drules/skills/integrating-unsplash-images/implementation/usage.md

160 lines
4.7 KiB
Markdown
Raw 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.

# Unsplash Images — Implementation Guide
## URL Format
Always use the direct `images.unsplash.com` format with explicit sizing:
```
https://images.unsplash.com/photo-{PHOTO_ID}?w={WIDTH}&q={QUALITY}
```
| Parameter | Purpose | Recommended values |
|-----------|---------|--------------------|
| `w` | Pixel width served by the CDN | `600` card, `800` section, `1200` hero, `1920` full-bleed |
| `q` | JPEG quality 1100 | `80``85` (good balance of quality vs size) |
### Deprecated / broken formats — do NOT use
| Format | Why it fails |
|--------|-------------|
| `source.unsplash.com/random` | Deprecated; returns 404 |
| `source.unsplash.com/{WIDTH}x{HEIGHT}` | Deprecated; returns 404 |
| `source.unsplash.com/featured/?{query}` | Deprecated; returns 404 |
---
## How to find a valid photo ID
1. Go to [unsplash.com](https://unsplash.com) and search for the subject (e.g. "modern apartment").
2. Open a photo. The URL will look like `unsplash.com/photos/{slug}-{PHOTO_ID}` or `unsplash.com/photos/{PHOTO_ID}`.
3. The `PHOTO_ID` is the last hyphen-separated segment (e.g. `photo-1600596542815-ffad4c1539a9`).
4. Build your URL: `https://images.unsplash.com/photo-1600596542815-ffad4c1539a9?w=1200&q=85`
5. **Test the URL** in a browser before committing.
---
## Declaring image constants
Define all Unsplash URLs as named constants at the top of the file. Never inline URLs in JSX.
```tsx
const HERO_IMAGE = "https://images.unsplash.com/photo-1600596542815-ffad4c1539a9?w=1200&q=85";
const SECTION_IMAGE = "https://images.unsplash.com/photo-1514565131-fce0801e5785?w=800&q=85";
```
---
## Rendering images in JSX
### Hero / banner (decorative — empty alt)
```tsx
<div className="relative w-full overflow-hidden rounded-2xl">
<div className="relative aspect-[21/9] min-h-[280px] w-full md:aspect-[3/1]">
<img
src={HERO_IMAGE}
alt=""
className="h-full w-full object-cover"
loading="eager"
fetchPriority="high"
/>
<div className="absolute inset-0 bg-black/40" />
<div className="absolute inset-0 flex flex-col items-center justify-center px-4">
{/* overlay content */}
</div>
</div>
</div>
```
Key points:
- `alt=""` for decorative images (screen readers skip them).
- `loading="eager"` and `fetchPriority="high"` for above-the-fold heroes.
- `object-cover` prevents stretching.
- Semi-transparent overlay (`bg-black/40`) ensures text readability.
### Section accent (meaningful — descriptive alt)
```tsx
<div className="relative min-h-[240px] overflow-hidden rounded-2xl">
<img src={SECTION_IMAGE} alt="City skyline at sunset" className="h-full w-full object-cover" />
<div className="absolute inset-0 bg-gradient-to-r from-black/20 to-transparent" />
</div>
```
### Card thumbnail
```tsx
<div className="aspect-[4/3] overflow-hidden bg-muted">
<img
src={imageUrl}
alt=""
className="h-full w-full object-cover transition-transform hover:scale-105"
loading="lazy"
/>
</div>
```
Key points:
- `loading="lazy"` for below-the-fold images.
- `hover:scale-105` subtle zoom on hover.
- `bg-muted` fallback color while loading.
---
## Fallback when no image is available
Always provide a placeholder when the image URL may be null:
```tsx
{imageUrl ? (
<img src={imageUrl} alt="" className="h-full w-full object-cover" />
) : (
<div className="flex h-full items-center justify-center text-muted-foreground">
No image
</div>
)}
```
---
## Content Security Policy (CSP)
If the application enforces CSP headers, add `images.unsplash.com` to `img-src`:
```
img-src 'self' https://images.unsplash.com;
```
Other commonly needed origins for stock images:
| Origin | Purpose |
|--------|---------|
| `images.unsplash.com` | Unsplash photos |
| `images.pexels.com` | Pexels photos |
| `fonts.googleapis.com` | Google Fonts CSS |
| `fonts.gstatic.com` | Google Fonts files |
---
## Accessibility checklist
- [ ] Decorative images have `alt=""`
- [ ] Meaningful images have descriptive `alt` text
- [ ] Hero images use `loading="eager"` and `fetchPriority="high"`
- [ ] Below-fold images use `loading="lazy"`
- [ ] Text over images has sufficient contrast (use overlay like `bg-black/40`)
- [ ] All URLs verified to return a valid image (no 404s)
---
## Common mistakes
| Mistake | Fix |
|---------|-----|
| Using `source.unsplash.com` | Replace with `images.unsplash.com/photo-{id}?w=…&q=…` |
| Hardcoding an unverified URL | Open URL in browser first; replace if broken |
| Missing `w` parameter | Always set width — CDN returns full-res (5000px+) otherwise |
| `loading="lazy"` on hero | Use `loading="eager"` for above-the-fold images |
| No fallback for nullable URLs | Wrap in conditional with placeholder div |
| Inline URLs in JSX | Extract to named constants at file top |