8.8 KiB
See shared-standards.md for common technical constraints.
Image Layout Specification
Layout rules for pages where the image is placed side-by-side with body text as a container block. Strategist and Executor both follow these rules when the image's narrative intent is side-by-side.
Core principle (side-by-side): compute container layout from the image's original aspect ratio so the image displays completely — no excess whitespace, no cropping.
Scope: this spec applies to side-by-side intent only. Other intents (hero / full-bleed, atmosphere / background, accent / inline) use full-bleed placement where ratio alignment is not a constraint and cropping is expected — the ratio→split table below does NOT apply. See
references/strategist.md§h for intent selection.
Layout Decision Flow
1. Decide narrative intent (hero / atmosphere / side-by-side / accent) — see strategist.md §h
2. If intent = side-by-side: continue below. Otherwise: compose per narrative; this spec does not apply.
3. Get image original dimensions → Calculate ratio (width/height)
4. Select layout type based on ratio
5. Calculate maximum display size for the image
6. Allocate remaining space for text area
7. Fill results into the Design Specification's image resource list
When to run: if image approach includes "B) User-provided", run the scan and populate the image resource list after the Strategist's Eight Confirmations and before content analysis / outlining.
Layout Type Selection (side-by-side intent)
| Image Ratio | Layout Type | Image Position | Description |
|---|---|---|---|
| > 2.0 (ultra-wide) | Top-bottom split | Top full-width | Image spans canvas width, height proportional |
| 1.5-2.0 (wide) | Top-bottom split | Top | Image width = content area width, height proportional |
| 1.2-1.5 (standard) | Left-right split | Left | Image height-first fit, width proportional |
| 0.8-1.2 (square) | Left-right split | Left | Image takes content area height, width proportional |
| < 0.8 (portrait) | Left-right split | Left | Image height = content area height, width proportional |
Boundary ratio (e.g., 1.5): decide by text volume — more text → left-right; less text → top-bottom.
Dimension Calculation Formulas
Canvas Parameters (All Formats)
| Format | Canvas | Margins (L/R, T/B) | Content Area (W x H) | Title Height | Content Start Y |
|---|---|---|---|---|---|
| PPT 16:9 | 1280x720 | 60, 60 | 1160 x 600 | 60px | 80px |
| PPT 4:3 | 1024x768 | 50, 50 | 924 x 608 | 60px | 70px |
| Xiaohongshu | 1242x1660 | 60, 80 | 1122 x 1500 | 80px | 100px |
| WeChat Moments | 1080x1080 | 60, 60 | 960 x 960 | 60px | 80px |
| Story | 1080x1920 | 60, 120/180 | 960 x 1620 | 80px | 140px |
| WeChat Article | 900x383 | 40, 40 | 820 x 303 | 40px | 50px |
Below, W = content area width, H = content area height (excludes title). PPT 16:9 example: W=1160, H=600.
Top-Bottom Layout Calculation
Image width = W = 1160 px
Image height = W / R = 1160 / R px
Text area height = H - image height - gap(20px)
Validation: Text area height >= 150px (at least 3-4 lines of text)
If not satisfied → Switch to left-right layout
Left-Right Layout Calculation
Method 1 (height-first, suitable for portrait images):
Image height = H = 600 px
Image width = H x R = 600 x R px
Text area width = W - image width - gap(20px)
Method 2 (width-constrained, for wide images converted to left-right):
Image width = W x 0.7 = 812 px
Image height = image width / R
Text area width = W - image width - gap(20px)
Validation: Text area width >= 280px; otherwise reduce image area width.
Layout Examples
Ultra-wide Image (ratio 2.45)
Original: 1960x800, R=2.45 → Top-bottom split
Image: 1160x473, Text area: 1160x147 → 7:3 top-bottom
Standard Landscape (ratio 1.38)
Original: 1614x1171, R=1.38 → Left-right split
Image: 773x560 (left), Text area: 367x560 (right) → 7:3 left-right
Wide Image Edge Case (ratio 1.75)
Original: 1820x1040, R=1.75
Try top-bottom: image height=663, text area=-43 ❌
Switch to left-right: image 780x446 (left), text area 360x600 (right) → 7:3 left-right
Portrait Canvas Override
Default selection table assumes landscape or square canvas. For portrait canvases (height > width), left-right splits leave both columns too narrow — use the override below.
| Canvas Orientation | Image Ratio | Recommended Layout | Reason |
|---|---|---|---|
| Portrait (Xiaohongshu, Story) | > 1.5 (wide) | Top-bottom | Same as landscape canvas |
| Portrait (Xiaohongshu, Story) | 1.2-1.5 (standard) | Top-bottom | Left-right too narrow on tall canvas |
| Portrait (Xiaohongshu, Story) | 0.8-1.2 (square) | Top-bottom | Image fits well in top half |
| Portrait (Xiaohongshu, Story) | 0.5-0.8 (portrait) | Left-right | Portrait image on tall canvas works |
| Portrait (Xiaohongshu, Story) | < 0.5 (extreme portrait) | Left-right | Image takes one side, text the other |
Square canvases (WeChat Moments 1:1): use the standard landscape rules.
Multi-Image Layout
For slides with multiple images, divide the content area evenly using the formulas below.
Grid Formulas
columns = number of columns
rows = number of rows
gap = 20px (PPT formats) or 30px (social formats)
cell_width = (W - (columns - 1) * gap) / columns
cell_height = (H - (rows - 1) * gap) / rows
Common Patterns
| Image Count | Layout | Grid | Description |
|---|---|---|---|
| 2 (both landscape) | Side-by-side | 2x1 | Two equal columns |
| 2 (both portrait) | Stacked | 1x2 | Two equal rows |
| 2 (mixed) | 1 large + 1 small | Custom | Landscape top (full-width), portrait right-bottom |
| 3 | 1 large + 2 small | 1+2 | Left large (50% width), right column with 2 stacked |
| 4 | Grid | 2x2 | Equal-sized cells |
Example: 2x2 Grid on PPT 16:9
W=1160, H=600, gap=20
cell_width = (1160 - 20) / 2 = 570
cell_height = (600 - 20) / 2 = 290
Image positions:
(60, 80) 570x290 (650, 80) 570x290
(60, 390) 570x290 (650, 390) 570x290
Multi-image slides: use
preserveAspectRatio="xMidYMid meet"on all images for consistent in-cell display.
Prohibited Practices
| Prohibited | Correct Approach |
|---|---|
| Fixed 50:50 or arbitrary ratios | Dynamic calculation based on image ratio |
| Forcing wide image into square container | Use top-bottom layout or increase image area width |
| Placing portrait image in narrow horizontal strip | Use left-right layout, image on left |
| Image whitespace exceeding 10% | Recalculate layout or choose alternative approach |
| Cropping key image content | Use preserveAspectRatio="xMidYMid meet" |
| Text area too small to read | Ensure text area >= 150px (top-bottom) or >= 280px (left-right) |
Handoff Fields
This spec only defines layout calculation. Write computed fields into the Image Resource List defined in svg-image-embedding.md:
| Field | Meaning |
|---|---|
Ratio |
Original image width / height |
Layout plan |
Top-bottom / left-right / grid, including split ratio when relevant |
Image area |
Computed display rectangle size |
Text area |
Computed remaining text area size |
For SVG <image> syntax, path rules, preserveAspectRatio, external refs, and Base64 embedding: see svg-image-embedding.md.
SVG Image Embedding Examples
Complete display (data charts, side-by-side — must not crop):
<image href="../images/xxx.png"
x="60" y="80" width="780" height="446"
preserveAspectRatio="xMidYMid meet"/>
Crop-to-fill (backgrounds and hero images only):
<image href="../images/bg.png"
x="0" y="0" width="1280" height="720"
preserveAspectRatio="xMidYMid slice"/>
Automation Tool
python3 scripts/analyze_images.py <project_path>/images # Default: PPT 16:9
python3 scripts/analyze_images.py <project_path>/images --canvas ppt43 # PPT 4:3
python3 scripts/analyze_images.py <project_path>/images --canvas xiaohongshu # Xiaohongshu
--canvas selects target format (default ppt169). The tool computes layout type (top-bottom / left-right), image display area, and text area per the formulas above. Output is a Markdown table — paste directly into the image resource list.
Role Responsibilities
| Role | Responsibility |
|---|---|
| Strategist | Run analyze_images.py, calculate layout per this spec, populate image resource list |
| Executor | Strictly follow the layout plan and dimensions in the image resource list when generating SVGs |