Top 7 div image layout patterns for AI‑generated media in SwiftUI
AI‑generated media is exploding in iOS apps, but the hardest part isn’t rendering images — it’s keeping your layouts stable and usable when those images arrive…

Top 7 div image layout patterns for AI‑generated media in SwiftUI
AI‑generated media is exploding in iOS apps, but the hardest part isn’t rendering images — it’s keeping your layouts stable and usable when those images arrive asynchronously.
DivKit has some of the best documented patterns for image‑heavy server‑driven UI (SDUI). At the same time, SwiftUI gives you powerful native primitives like AsyncImage, Grid, LazyVGrid, overlay, and containerRelativeFrame to build the same layout families directly on iOS.
This ranked roundup is for:
- iOS engineers and mobile leads shipping AI‑native features
- Teams evaluating server‑driven UI libraries and AI UI SDKs (Uzori vs DivKit, etc.)
- Anyone trying to turn LLM responses into real, native SwiftUI screens
We’ll walk through seven reusable "div image" layout patterns, ranked by how broadly useful they are for AI‑generated media and how well they map into modern SwiftUI and Uzori’s generative UI schema.
Each pattern covers:
- Where it shines in AI‑driven interfaces
- Where it breaks down on iOS (layout, performance, OS versions)
- How to encode it safely in a generative UI schema (DivKit JSON & Uzori/SwiftUI)
1. Hero / Cover Image
The hero or cover image is the backbone of most AI‑generated media screens: a single, high‑impact visual that anchors the rest of the UI.
What it is
In DivKit, this usually appears as a div-image with a fixed aspect ratio or size near the top of the card or screen.
In SwiftUI, it’s typically:
AsyncImage(url: url) { phase in
switch phase {
case .success(let image):
image
.resizable()
.scaledToFill()
.frame(maxWidth: .infinity)
.containerRelativeFrame(.horizontal)
.clipped()
case .empty:
placeholder
case .failure:
fallback
}
}
On iOS 17+, containerRelativeFrame lets the hero adapt to its container width without hard‑coding sizes.
Where it shines for AI‑generated media
- LLM‑generated feature headers – e.g., an AI concierge creates a roaming plan and shows one striking illustration at the top.
- Product storytelling – generated scene for a dress, hotel, or route.
- Streaming content – works well with phase‑aware placeholders while the AI image renders.
Because the hero is a single element, it’s also the easiest place to avoid layout instability: you can fix aspect ratio and size up front.
Where it breaks down on iOS
- Layout shifts from
wrap_content– DivKit explicitly warns thatwrap_contentimages can be recalculated after async load, causing layout jumps. The same problem appears in SwiftUI if you let the image size decide the layout after it downloads. - Older OS constraints –
containerRelativeFrameis iOS 17+ only. On earlier versions you need a fallback like.frame(height: 240)with.scaledToFill().
How to encode it safely in a generative UI schema
For a DivKit‑style schema:
- Require fixed aspect ratio (e.g., 16:9) or max height.
- Prohibit
wrap_contentheight for hero images. - Include explicit content mode (cover vs fit) and alignment.
For Uzori + SwiftUI:
- Define a
HeroImagecomponent type in Uzori’s schema:kind: "hero_image"aspectRatio: 16/9(or a small enum liketall,wide,square)contentMode: .fill | .fit
- Validate server‑side that the LLM can’t emit a hero without size constraints.
This pattern is ranked #1 because almost every AI‑generated media screen wants a hero, and getting this one component right removes the worst layout jitter.
2. Horizontal Gallery (Carousel)
The horizontal gallery (or carousel) is the workhorse pattern for browsing multiple AI‑generated variants side by side.
What it is
In DivKit, you’d typically use div-gallery configured for horizontal scrolling.
In SwiftUI, this is usually:
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 12) {
ForEach(images) { item in
AsyncImage(url: item.url) { phase in
// card-style image
}
.frame(width: 180, height: 240)
.clipShape(RoundedRectangle(cornerRadius: 12))
}
}
.padding(.horizontal)
}
Where it shines for AI‑generated media
- LLM‑driven exploration – AI proposes 5–10 options (e.g., outfits, room setups, itineraries) that you can quickly swipe through.
- Variant comparison – e.g., “show me lighter/darker color schemes” as separate cards.
- On‑device performance – keeps layout simple since all items share a common size.
This is also where DivKit’s dynamic datasets (item_builder) shine. A model can emit a structure describing a set of images, while the client renders them in a gallery.
Where it breaks down on iOS
- Too many items – dozens of AI‑generated images in a single
ScrollViewcan hurt performance. Use lazy loading or cap the number of visible cards. - Mixed aspect ratios – if you let a model supply arbitrary widths and heights per item, your gallery becomes visually noisy and harder to navigate.
How to encode it safely in a generative UI schema
For DivKit‑style JSON:
- Use a
gallerycontainer with:orientation: horizontalitem_sizeor per‑itemaspect_ratioconstraints
- Let the LLM vary content and ordering, not the core layout rules.
For Uzori + SwiftUI:
- Define a
HorizontalGallerycomponent with parameters:itemKind: .mediaCard | .thumbnailitemWidth,itemHeight(oraspectRatio+ max width)maxItems(to cap AI‑generated sets)
- Validate items server‑side and stream them into a SwiftUI
ScrollView.
This pattern ranks #2 because most AI UI SDK use cases — AI concierges, product explorers, visual search — benefit from a simple, stable horizontal gallery.
3. Pager (Full‑bleed Swiping)
A pager pattern shows one media item at a time, typically full‑bleed, with swipeable navigation.
What it is
DivKit exposes pager divs for swipeable pages of content.
In SwiftUI, on iOS 14+ you can approximate with TabView and PageTabViewStyle:
TabView(selection: $index) {
ForEach(images.indices, id: \.self) { idx in
AsyncImage(url: images[idx]) { phase in
// full-screen image view
}
.tag(idx)
}
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .automatic))
You can layer captions and controls with overlay.
Where it shines for AI‑generated media
- Focused review flows – AI produces a handful of options the user should evaluate one by one.
- Story‑style experiences – step‑by‑step guides, onboarding, or generated walkthroughs.
- High engagement – full‑screen swipes feel immersive and native.
Where it breaks down on iOS
- State management complexity – combining pagers with other navigational stacks can be tricky; you need a clear single source of truth for
selection. - Accessibility concerns – if the AI changes the number of pages dynamically, VoiceOver users need predictable ordering and announcements.
How to encode it safely in a generative UI schema
In a DivKit‑inspired schema:
- Describe a
pagercontainer with:- fixed page
layouttemplate - bounded number of items (e.g., 3–10)
- fixed page
- Allow the LLM to:
- reorder items
- swap text and images inside a fixed template
With Uzori + SwiftUI:
- Define a
PagedMediaview type with:items: [MediaCard]showsIndicators: Bool
- Keep the page layout static and let AI only control data and ordering.
Pager ranks #3 because it’s slightly more specialized than a gallery but incredibly powerful for AI‑guided flows where each screen represents a single, coherent idea.
4. Grid / Masonry Collection
When you need to show many AI‑generated images at once, you move into grid territory.
What it is
In DivKit you’d typically supply a div-grid with specified columns and item templates.
In SwiftUI, you’ll reach for LazyVGrid on iOS 14+ or Grid on iOS 16+:
let columns = [
GridItem(.flexible()),
GridItem(.flexible())
]
LazyVGrid(columns: columns, spacing: 12) {
ForEach(images) { item in
AsyncImage(url: item.url) { phase in
// image thumbnail
}
.aspectRatio(1, contentMode: .fill)
.clipped()
}
}
Apple’s docs highlightGridon iOS 16+ for regular, aligned layouts, andLazyVGridwhen profiling shows performance issues with too many views.
Where it shines for AI‑generated media
- Search & discovery – showing many generated thumbnails for “modern living rooms” or “evening gowns.”
- Parallel exploration – users can visually scan many AI outputs quickly.
- Server‑driven layouts – the grid structure maps cleanly into an SDUI schema.
Where it breaks down on iOS
- OS fragmentation –
LazyVGridis iOS 14+,Gridis iOS 16+. If you maintain a lower deployment target, your schema must not rely onGridsemantics alone. - Layout thrash with arbitrary sizes – if the LLM emits varying heights per item, your grid can degenerate into a masonry layout with unpredictable rows.
How to encode it safely in a generative UI schema
In a DivKit‑style schema:
- Fix column count or min/max item width.
- Allow the LLM to:
- decide which items appear
- choose sort order and groups
- Use templates to avoid duplicating JSON for each cell — DivKit’s docs explicitly recommend this to reduce response size and errors.
In Uzori + SwiftUI:
- Define a
MediaGridtype with:layout: .twoColumn | .threeColumn | .adaptive(minWidth:)itemAspectRatio: 1 | 4/3 | 3/4
- Handle OS differences:
- On iOS 16+: prefer
Gridfor simpler code. - On iOS 14–15: map to
LazyVGridbehind the scenes.
- On iOS 16+: prefer
Grid ranks #4 because it’s essential for media‑heavy search and browse flows, but it requires more careful OS‑aware handling than heroes and galleries.
5. Split‑Detail Card (Image + Text)
The split‑detail card is your classic “image on one side, text on the other” layout — ideal for concise, AI‑generated explanations tied to a visual.
What it is
In DivKit, this can be a container with a div-image and div-text arranged horizontally or vertically.
In SwiftUI, you build it with HStack or VStack:
HStack(spacing: 12) {
AsyncImage(url: model.imageURL) { phase in
// thumbnail
}
.frame(width: 96, height: 96)
.clipShape(RoundedRectangle(cornerRadius: 10))
VStack(alignment: .leading, spacing: 4) {
Text(model.title).font(.headline)
Text(model.subtitle).font(.subheadline)
Text(model.detail).font(.footnote)
}
}
.padding()
Where it shines for AI‑generated media
- AI explanations with visuals – generated troubleshooting cards, plans, or recipes.
- Hybrid flows – Uzori‑style assistants that need to show both the media and the reasoning.
- Compact lists – stacked inside a feed or comparison view.
Where it breaks down on iOS
- Text overflow – if the LLM generates paragraphs instead of tight copy, the card can grow too tall and break the layout rhythm.
- Misaligned orientation – AI may want to switch between horizontal and vertical splits; you need rules instead of free‑for‑all layouts.
How to encode it safely in a generative UI schema
For a DivKit‑inspired schema:
- Define a
card_media_detailtemplate with:- fixed thumbnail size
- max number of text lines or characters
- layout direction:
horizontalorvertical(small enum)
- Allow the model to customize content only, not layout.
In Uzori + SwiftUI:
- Define a
MediaDetailCardcomponent with:imagePosition: .leading | .toptitle,subtitle,bodymaxLinesper text field (validated server‑side)
- In your AI prompt, emphasize: “Use concise titles and subtitles; avoid full paragraphs in cards.”
This pattern ranks #5 because it’s the bridge between AI text and images, and it’s central to Uzori‑style, task‑specific interfaces.
6. Stacked Feed with Images
The stacked feed pattern is a vertical list of cards, each containing one or more images plus text.
What it is
In DivKit, this is usually a container with multiple child divs, often repeating a card template.
In SwiftUI, it’s typically:
ScrollView {
LazyVStack(spacing: 16) {
ForEach(items) { item in
MediaDetailCard(model: item)
}
}
.padding(.vertical)
}
You can mix and match HeroImage, Split‑Detail, and HorizontalGallery patterns within each card.
Where it shines for AI‑generated media
- Conversational AI interfaces – replacing long paragraphs of LLM text with structured, tappable cards.
- Dynamic result feeds – AI recomposes the feed based on user intent and backend data.
- Server‑driven experimentation – easy to A/B test card ordering and types.
Where it breaks down on iOS
- Infinite variance – if the LLM is allowed to invent new card layouts on the fly, your feed loses all visual consistency.
- Scrolling performance – mixed heroes, pagers, and grids in one feed can get heavy if you don’t reuse templates and cap counts.
How to encode it safely in a generative UI schema
For a DivKit‑style system:
- Use templates aggressively: DivKit’s docs emphasize that templates reduce JSON size and errors, and they’re ideal for feeds.
- Define a small set of card types the LLM can pick from:
hero,media_detail,gallery_card, etc. - Let the LLM control ordering, selection, and content only.
For Uzori + SwiftUI:
- Treat the feed as data + component palette:
- Components:
HeroImage,MediaDetailCard,HorizontalGallery, etc. - Data: ordered array of typed blocks
[{ type: "hero" ... }, ...].
- Components:
- Uzori validates this server‑side and streams it into a SwiftUI
ScrollView.
Stacked feed ranks #6 because it’s the natural replacement for chat‑style AI UIs, but it only works when you constrain the component set.
7. Background‑Image Overlay
The background‑image overlay pattern uses an image as a canvas with text, buttons, or gradients layered on top.
What it is
In DivKit, you often see this as a container with an image background plus foreground divs for text and controls.
Apple’s SwiftUI docs highlight overlay as a way to layer content while the underlying view maintains layout control.
Example in SwiftUI:
AsyncImage(url: url) { phase in
imageView(for: phase)
.overlay(alignment: .bottomLeading) {
LinearGradient(gradient: Gradient(stops: [
.init(color: .black.opacity(0.6), location: 0),
.init(color: .clear, location: 1)
]), startPoint: .bottom, endPoint: .top)
.frame(maxHeight: 120)
.overlay(alignment: .bottomLeading) {
VStack(alignment: .leading) {
Text(title).font(.headline)
Text(subtitle).font(.subheadline)
}
.padding()
}
}
}
.clipShape(RoundedRectangle(cornerRadius: 16))
Where it shines for AI‑generated media
- Content‑rich hero cards – e.g., generated travel image with route summary overlaid.
- Compact summarization – AI can produce a title + key metrics without occupying separate rows.
- On‑brand visual identity – overlays can enforce consistent gradients and typography even as images vary.
Where it breaks down on iOS
- Readability – AI‑generated images can be visually noisy. Without strong scrims and text contrast rules, overlays can become illegible.
- Tap targets – putting buttons on busy background images can confuse hit areas if not padded and constrained.
How to encode it safely in a generative UI schema
For DivKit‑style JSON:
- Treat overlays as structured layers:
- background image (fixed aspect ratio)
- gradient layer (preset options)
- text block (max lines, aligned to corners)
- Restrict the model to a palette of gradient types and text positions.
For Uzori + SwiftUI:
- Provide an
OverlayCardcomponent with:imageURLtitle,subtitlehasGradientScrim: Boolcta: ButtonConfig?
- Validate:
- maximum text length
- required gradient for accessibility (e.g., always enabled in dark overlay variants).
This pattern ranks #7 because it’s more advanced and style‑driven, but it’s incredibly powerful once your basic hero and gallery patterns are solid.
Comparison Table: Top 7 div image layout patterns
Here is a quick comparison of the seven patterns and how they map to DivKit and SwiftUI.

This comparison table maps each div image pattern to its closest DivKit and SwiftUI primitives, plus a primary AI use case so teams can choose the right layout quickly.
- 1 — Pattern: Hero / Cover; DivKit primitive(s):
div-image; SwiftUI primitive(s):AsyncImage,containerRelativeFrame; Best for AI use case: Single key visual in AI‑generated summary screens - 2 — Pattern: Horizontal Gallery; DivKit primitive(s):
gallery; SwiftUI primitive(s):ScrollView(.horizontal),HStack; Best for AI use case: Variant exploration, product carousels - 3 — Pattern: Pager; DivKit primitive(s):
pager; SwiftUI primitive(s):TabViewwithPageTabViewStyle; Best for AI use case: Full‑screen review of AI options - 4 — Pattern: Grid / Masonry; DivKit primitive(s):
grid; SwiftUI primitive(s):LazyVGrid,Grid; Best for AI use case: Search & discovery across many AI images - 5 — Pattern: Split‑Detail Card; DivKit primitive(s):
container+image; SwiftUI primitive(s):HStack,VStack; Best for AI use case: Explanatory cards mixing text and visuals - 6 — Pattern: Stacked Feed with Images; DivKit primitive(s):
container+ templates; SwiftUI primitive(s):ScrollView,LazyVStack; Best for AI use case: AI‑driven feeds and assistant‑style timelines - 7 — Pattern: Background‑Image Overlay; DivKit primitive(s):
backgroundimage; SwiftUI primitive(s):overlay,ZStack; Best for AI use case: Rich hero cards with titles and CTAs over media
How Uzori fits into these patterns
Uzori sits at the intersection of generative UI and server‑driven UI:
- You integrate a single SwiftUI screen using the Uzori iOS SDK.
- Uzori’s engine takes:
- user requests
- your backend APIs (typically via OpenAPI)
- And returns server‑validated SwiftUI screens streamed into your app.
For the patterns above, Uzori provides:
- A typed schema for each component (hero, gallery, grid, card, feed, overlay).
- A server‑side validator that ensures the LLM can only:
- assemble existing components
- fill in data
- choose layouts within safe, pre‑approved constraints
That means you can:
- Compress weeks of UI iteration into AI‑driven layout exploration.
- Keep everything native (SwiftUI, no webviews or remote code execution).
- Combine the structure of DivKit‑style SDUI with the intelligence of generative AI.
In practice:
- Patterns like hero, gallery, and split‑detail cards become your building blocks.
- Uzori turns LLM responses into those concrete SwiftUI views.
- You keep firm control over layout stability, OS compatibility, and brand fidelity.
Recommendations by use case
Instead of picking one “best” pattern, match patterns to your use case:
- AI concierge or assistant in a production app
Start with:- #1 Hero / Cover
- #5 Split‑Detail Card
- #6 Stacked Feed with Images
- Visual product discovery or search (e‑commerce, travel, real estate)
Focus on:- #2 Horizontal Gallery
- #4 Grid / Masonry Collection
- #7 Background‑Image Overlay (for highlighted picks)
- Creative tools and design exploration
Lean into:- #2 Horizontal Gallery (variants)
- #3 Pager (full‑screen review)
- Guided configuration flows (plans, bundles, multi‑step wizards)
Combine:- #1 Hero / Cover (context per step)
- #5 Split‑Detail Cards (options per step)
- #3 Pager (step‑by‑step review) or #6 Feed (summary)
If you’re evaluating Uzori vs DivKit and other server‑driven UI frameworks, treat these patterns as the baseline you must support. The differentiator isn’t “can it show images?” but “can it safely encode layout intent while letting AI orchestrate flows?”
Uzori’s value is that it gives you that AI interface layer on top of your existing APIs, without giving up native SwiftUI quality.
FAQ: div image layout patterns and AI‑generated media in SwiftUI
1. Why is layout stability a bigger risk than image rendering for AI‑generated media?
Because AI images often load asynchronously and vary in size, layouts that depend on intrinsic image size (wrap_content in DivKit, unconstrained Image in SwiftUI) can shift after load. DivKit’s docs explicitly warn about this. Using fixed aspect ratios, placeholders, and size constraints keeps your UI stable even as images stream in.
2. How do I choose between a horizontal gallery and a pager in SwiftUI?
Use a horizontal gallery when you want quick scanning of multiple options at once, often as small cards. Use a pager when you want focused review, one option at a time, typically full‑screen. Both can be driven from the same AI data; your schema should express them as different layout types over the same media set.
3. What’s the best way to map DivKit’s image layouts into SwiftUI on older iOS versions?
LazyVGridcovers most grid use cases from iOS 14 up.TabViewwithPageTabViewStyleprovides a pager starting in iOS 14.- For hero images, use
frame(height:)+.scaledToFill()instead ofcontainerRelativeFrameon iOS 16 and below.
Your generative UI schema should avoid depending on APIs newer than your minimum deployment target; Uzori can handle the mapping internally.
4. How does Uzori differ from dropping a generic AI chat box into my iOS app?
Uzori doesn’t return chat text; it returns typed SwiftUI screens built from components like heroes, galleries, grids, and cards. The AI decides what UI to compose, but your server validates it against a schema before it hits the user. That means your AI UI is:
- Native SwiftUI
- Safe and structured
- Deeply integrated with your existing backend data and flows
5. Can I gradually adopt these patterns instead of rewriting my whole app?
Yes. A common rollout path is:
- Integrate Uzori as a single SwiftUI screen behind a feature flag.
- Start with one pattern, usually hero + split‑detail cards inside a simple feed.
- Add galleries, pagers, and overlays once you’re confident in the schema and analytics.
You keep your existing navigation and architecture, and Uzori fills in generative, server‑driven screens where they add the most value.
By standardizing on these seven div image layout patterns and encoding them into a tight, server‑validated schema, you can let AI design rich, media‑heavy SwiftUI interfaces — without sacrificing native quality, safety, or iteration speed.