Skip to content
Web Development23 September 2026 · 12 min read

Portrait vs Landscape Hero Media on Mobile

A 16:9 hero loses more than half its width on a portrait phone, and object-position cannot bring it back. The geometry, the four ways to ship a hero, and the capture matrix I shoot against.

Portrait vs Landscape Hero Media on Mobile

Responsive CSS cannot rescue a hero image that was composed for the wrong shape.

That is the whole argument, and it costs a week every time somebody learns it the slow way. You build a cinematic 16:9 hero. It looks expensive on the laptop. Then a visitor opens the site on a phone held upright, the building you framed so carefully is now a wall, the headline sits across the subject's face, and the thing that made the shot worth taking is somewhere off the left edge of the viewport.

You have probably tried to fix that in CSS. A different object-position, an aspect-ratio override at a breakpoint, maybe a scale transform to buy back some subject. Those tools slide the crop window around inside the frame you already have. None of them invent pixels that were never captured.

So the portrait vs landscape hero image question on mobile is not really a styling question. It is a capture question that shows up disguised as a styling question, three weeks after the shoot, when going back for another one is expensive.

Why does one 16:9 hero fail on a portrait phone?

An isometric conveyor feeding a wide panel of grey tiles into a narrow upright slot, with roughly half the panel shearing off at the edges and dropping as loose tiles into a collection bin below

A 16:9 source in a tall phone container loses more than half its width to the crop, so an off-centre subject vanishes before CSS gets a vote.

Run the arithmetic once and you stop arguing about it. Take a 390-pixel-wide iPhone viewport with a hero occupying roughly 500 pixels of height. Fill that 390×500 box using object-fit: cover from a 1920×1080 source and the browser scales until the short axis fits: height 1080 scales to 500, a factor of 0.463, which renders the full width at about 889 pixels. The container shows 390 of those. You keep 44% of the frame and throw away the rest.

Now place your subject where a good wide composition usually puts it, a third of the way in from one edge. It falls outside the surviving 44%. The phone does not clip it at the shoulder; it never receives it at all.

Calling that a rendering bug misplaces the blame. It is arithmetic you agreed to the moment you decided that one file would serve two aspect ratios.

Object-fit crops, it does not compose

A metal viewfinder frame sliding on a runner rail across a large printed plan on a drafting bench, the area inside the frame glowing in colour while everything outside it stays flat and grey, with open scissors resting beside the rail

object-fit and object-position choose which rectangle of an existing image survives. They are a pair of scissors with a ruler attached. Useful, and often enough for a portrait photo of a person where the head is near the middle, and useless for a composition whose meaning depends on the relationship between two things at opposite ends of a wide frame.

There is a CSS property that gets suggested here, object-view-box, which lets you define a viewbox inside a replaced element the way SVG does. It is still not Baseline and does not work across the browsers most of your traffic uses. Even if it shipped everywhere tomorrow it would not help, because it pans and zooms within the pixels you have. Same scissors. Nicer handle.

Actually, that overstates the pessimism slightly. There is one case where a single flexible image is the right call: when the subject is centred, the background is texture rather than content, and nothing in the frame carries meaning by its position. Skies. Fabric. Concrete. If your hero is a mood, one file is fine. If your hero is a statement, it is two files.

Should you ship separate portrait and landscape files?

An isometric junction plate splitting one incoming lit conduit into four outgoing conduits of different cross-sections: one wide and flat, one narrow, a doubled pair bound with a half-undone tie, and one that branches into two

Ship separate files whenever the subject's position inside the frame carries meaning; keep one flexible image only when the background is texture rather than content.

The decision is narrower than it looks. There are four real options and they sort by how much the composition matters and whether motion is involved.

ApproachAssets to produceSubject survives portraitChoose it when
One flexible image plus object-position1Only if centredBackground is texture, not content
Art-directed <picture> with media2 or more cropsYes, by constructionComposition carries meaning and the layout is static
Poster image plus art-directed <video>2 clips, 2 postersYes, with one caveat belowMotion is the point and you control both cuts
Separate components per breakpoint2 or moreYesThe hero's markup, not only its image, differs by device

The third column is the one people skip, and it is the only column a client ever notices.

For the <picture> route the mechanics matter. The browser walks the <source> elements in order, evaluates each media condition, and as MDN puts it, if a source's media condition evaluates to false the browser skips it and moves to the next. First match wins, and the <img> inside is mandatory rather than decorative, because it supplies both the fallback and the alt text. Order your portrait source before your landscape source or write conditions that cannot both be true, or you will ship the wide crop to phones and never see it on your own machine.

web.dev draws the distinction better than I can: srcset and sizes are suggestions you hand the browser, while a <source> is closer to a command. Art direction needs the command.

Here is the decision procedure, in order:

  1. Ask whether the subject's position inside the frame carries meaning. If no, ship one image and set object-position to the focal point. Stop here.
  2. Ask whether the hero moves. If it does not, use <picture> with a media condition on orientation or width, and produce a genuinely re-composed portrait crop rather than a centre cut of the wide one.
  3. If it does move, produce two clips, two posters, and art-direct both, then read the video caveat below before you ship it.
  4. If the portrait and landscape heroes need different markup and not only different pixels, split the component, and keep the copy and the interaction identical so the content stays one thing.

If you work in Next.js, the framework does not expose art direction through the Image component at all. The current Image API reference routes it through getImageProps, pulling a srcSet for each crop and assembling a plain <picture> around them, with different width, height and quality per source. Their own example ships 1440×875 for desktop and 750×1334 for mobile. Those are not two sizes of one picture. They are two pictures.

The visual decision and the network decision are the same decision

An isometric platform where a fat amber pipeline is capped off and leaking a pool of spent material across a seam, while a slim blue pipeline runs clean into a blank phone-shaped terminal

Choosing the crop and choosing the bytes are one act, because the element that selects the source also selects the download.

This is where a lot of otherwise careful work falls apart. Teams build both crops, then deliver them by rendering both elements and hiding one with display: none. How many megabytes does your phone pull down for an asset it will never paint? On that pattern, all of them. You have doubled the cost of the hero to solve a cropping problem, which leaves you worse off than the cropping problem did.

Here's how that went on Elpida Solutions.

Elpida Solutions uses dedicated landscape and portrait hero media because the dove, architecture and headline cannot share one crop without sacrificing the subject on a phone. I also had to prevent mobile from downloading the desktop clip it never displays; the wrong source selection wasted more than a megabyte per first visit. The visual decision and the network decision were the same problem.

A megabyte on a first visit is not a rounding error. The 2024 Web Almanac media chapter put the median largest image on a mobile page at 135 KB, and the 90th percentile at 1002 KB. A wasted desktop clip puts you past the worst tenth of the web before your real hero has loaded. The full Elpida Solutions case study covers how the rest of that build was verified, including the multilingual routing and the production checks.

The same chapter has a number worth sitting with. Only 9.3% of mobile pages use <picture> at all, 42% use srcset, and within the pages that do reach for <picture>, the media attribute appears on 40% of them, down three percentage points from 2022. Art direction is not a crowded field. Doing it properly is still a differentiator, which is an odd thing to say about a fifteen-year-old element.

Video has a trap that pictures do not

An isometric railway points mechanism whose lever sits fixed in one position, the second branch of track curving away over empty air with grit collected in its unused rail groove

A <video> evaluates its <source> list once when it loads and never re-evaluates it when the media condition changes, which <picture> does.

Rotate the phone from portrait to landscape after the page has loaded and the portrait clip stays on screen, stretched or letterboxed into a shape it was not cut for. Resize a desktop window across the breakpoint and nothing swaps. Scott Jehl, who did the work to get this feature restored, documents the limitation plainly and there is an open WHATWG issue asking the spec to make video behave like picture. Part of the difficulty is obvious once stated: swapping a source mid-playback means preserving the time code.

Some history explains why so many developers still believe this does not work at all. The media attribute was pulled from the video spec in 2014 and Chrome and Firefox dropped their implementations. Safari kept it. Both browsers restored support in version 120, so responsive video is usable today with the one-shot caveat. The stakes are not small either: Jehl cites a median video weight of almost 5 MB on mobile pages that use video, up 45% over five years.

The practical rule that falls out: art-direct on the initial load, accept that rotation will not re-cut, and choose a portrait composition that still reads acceptably at landscape phone dimensions. If you cannot accept that, listen for orientationchange, swap the source, and restore currentTime yourself. If your hero is decorative and short, do not bother.

Autoplaying heroes bring a second cost that has nothing to do with shape. A phone that holds several decoded clips at once can have its tab reclaimed by the system, which I wrote up separately in why mobile Safari reloads video-heavy pages.

What do you actually capture, and at what sizes?

Capture for the narrowest container you will ever ship, then crop outward, because you can always remove width and you can never add it back.

These are the widths worth framing against. They cover the overwhelming majority of phones in use, and the landscape row is the one people forget until a client rotates their handset during a review call.

TargetCSS widthWorking hero boxWhat the frame must protect
Small phone320px320 × 420Subject plus 12% margin on every side
Common Android360px360 × 470Same subject, headline baseline clear
iPhone standard390px390 × 500Subject, plus room for the overlay block
Large phone430px430 × 560Subject and overlay, plus any logo lockup
Phone landscape844 × 390844 × 300Subject survives a shallow band, no vertical detail below the fold

Shoot or render the portrait asset at 1080×1920 and crop down. Keep the subject inside the middle 76% of the portrait frame so a 12% safe margin survives on both axes at every width in that table. Put the text overlay in a zone you deliberately left quiet, not wherever the layout happens to drop it, and check the contrast against the darkest and lightest pixels that zone can contain at 320 and at 430.

One more constraint belongs in the capture brief rather than the stylesheet. Size the hero box in svh rather than vh or dvh. MDN is direct about why: dynamic viewport units mean content resizes while the user scrolls, which degrades the interface and costs performance as the address bar retracts. A hero that changes height mid-scroll re-crops itself under the reader's thumb.

Reduced motion is a crop decision too

If the visitor has asked for reduced motion, the still you serve them is the hero. Not a paused frame from a clip composed for movement. Pick a frame where the composition resolves on its own, export it as a proper portrait asset, and give it the same safe-area treatment as everything above.

Verify the waterfall, not the mockup

Open the network panel on a real phone profile, load the page cold, and look at what actually arrived. One hero asset should be there. If two are, your media conditions overlap or a hidden element is still fetching. This takes ninety seconds and catches the failure that every visual review misses, because a hidden download looks perfect. Load performance work I have written about elsewhere applies here too, in how to get a Webflow site under one second.

So: pull up your own hero on a phone right now, in portrait, and ask whether the subject is where you framed it. If it is not, the fix starts in the capture brief, not the stylesheet.

Free resource

Free SaaS MVP Scope Template

A Notion document with the full feature checklist, MVP vs. nice-to-have table, pre-build questions, and cost signals — so you walk into any developer call knowing exactly what to ask for.

Get the template →
DL

Dusko Licanin

Full-Stack Developer · Banja Luka, Bosnia

Full-stack developer shipping SaaS MVPs, web apps, and mobile apps using AI-augmented workflows — without agency coordination overhead. Live portfolio: BookBed, Callidus, Pizzeria Bestek.

Frequently Asked Questions

How do I art-direct a responsive hero image?

Art direction means serving a genuinely different crop per viewport through a <picture> element, rather than resizing one source file. Produce a portrait composition and a landscape composition as separate assets, then wrap them in <picture> with a media condition on each <source>. The browser evaluates those conditions in order and loads only the first match, so the phone never downloads the desktop crop. MDN's reference on source selection spells out the ordering rules. Keep the <img> inside the picture element, because it supplies both the fallback and the alt text. If you work in Next.js, assemble the picture yourself with getImageProps rather than stacking two Image components and hiding one.

Why does my hero video crop wrong on mobile?

Usually because a <video> evaluates its source list once at load and never re-evaluates it when the orientation or the viewport changes. A phone that loaded in portrait keeps the portrait clip after the visitor rotates it, and a desktop window dragged across a breakpoint keeps whatever it started with. Scott Jehl documents that behaviour, and an open WHATWG issue asks for video to match the picture element. Your two options are to accept it, choosing a portrait cut that still reads at landscape phone dimensions, or to listen for orientation changes, swap the source and restore currentTime in JavaScript yourself.

Can the picture element switch between portrait and landscape images?

Yes, and that is its intended use: put a media condition such as (orientation: portrait) or a max-width query on each <source> and give each one a separately composed crop. The browser walks the sources top to bottom, skips any whose condition evaluates false, and stops at the first match, so ordering matters more than people expect. Unlike video, picture re-evaluates when the condition changes, which means rotating the phone genuinely swaps the image. Adoption remains low. The 2024 Web Almanac found <picture> on 9.3% of mobile pages, with the media attribute present on 40% of those.

Is object-fit: cover enough for a mobile hero?

Only when the subject sits near the centre of the frame and everything around it is texture rather than content. object-fit: cover scales the source until its short axis fills the container and discards whatever falls outside, while object-position slides that surviving window around. A 1920x1080 source in a 390x500 phone box keeps roughly 44% of the original width. If the meaning of your composition depends on something a third of the way in from an edge, that something sits outside the window and no CSS value retrieves it. At that point you need a second capture, not a second stylesheet rule.

What size should a portrait hero image be?

Render the portrait master at 1080x1920 and keep the subject inside the middle 76% of the frame, so a 12% safe margin survives at every common phone width. That covers 320, 360, 390 and 430 CSS pixels once device pixel ratio is accounted for, and it leaves room for a text overlay in a zone you chose deliberately. Export a separate landscape master instead of upscaling a crop of the portrait one. Size the hero container in svh rather than vh or dvh, because MDN warns that dynamic viewport units resize content while the visitor scrolls, which re-crops the hero under their thumb.