I bookmarked a tweet a few months ago, as it was a bonafide CSS trick and that’s what we love around here.
The issue is: how do we make a full-browser-width container when we’re inside a limited-width parent?
Starting Point

We want to stretch it exactly as wide as the browser window.
Here’s some minimal assumed markup:
<!-- parent -->
<main>
<p>Stuff.</p>
<!-- container we want to be full width -->
<figure class="full-width">
<!-- could be whatever content -->
<img src="dog.jpg" alt="">
</figure>
</main>
Considerations
If we could use absolute positioning, we could set the container to be at left: 0;
and width: 100%;
– but we can’t, because we want the container to remain in flow.
Can’t we just apply some negative margin to each side and pull it outwards? In some circumstances, we can!
With Known % Width
Let’s say the parent container was 60% wide and centered. That means there is 20% width on either side of it. But margin is calculated based on the parent element, so to pull it to the left 20% of the browser window, you’d need 1/3 of the width of the parent, so…
main {
width: 60%;
margin: 0 auto;
/* creates 20% margins on either side */
}
.full-width {
/* 1/3 of 60% = the 20% margin on either side */
margin-left: -33.33%;
margin-right: -33.33%;
}
With Known Non-% Parent Width
Under most other circumstances, we just don’t have enough information to know exactly how far to pull out the full width container with negative margins.
Well, unless…
We could use the width of the browser window in our CSS math. The amount we want to “pull” to the left and right is half the width of the browser window plus half the width of the parent. (Assuming the parent is centered.)
So, so our parent is 500px wide:
.full-width {
margin-left: calc(-100vw / 2 + 500px / 2);
margin-right: calc(-100vw / 2 + 500px / 2);
}
A fixed width like that feels a little red-flaggy (i.e. what happens on narrower screens?), all this would likely be wrapped in a media query that makes it only apply on larger screens:
@media (min-width: 500px) {
main {
width: 500px;
margin: 0 auto;
}
.full-width {
margin-left: calc(-100vw / 2 + 500px / 2);
margin-right: calc(-100vw / 2 + 500px / 2);
}
}
Since our demo was an image, you might also do something like .full-width img { width: 100%; }
too, to get that full coverage.
If it’s less brain bending, you might have luck reducing to:
@media (min-width: $max-width) {
.full-width {
margin-left: calc(50% - 50vw);
margin-right: calc(50% - 50vw);
}
}
Translate
Since animations (probably) aren’t involved here, it’s probably not super necessary, but you could pull the container back to the edge with transforms instead.
@media (min-width: 40em) {
.full-width {
width: 100vw;
transform: translateX(calc((40em - 100vw)/2));
}
}
@supports()
The above idea was taken from a Pen by Brandon Mathis where he combined that idea with wrapping it all in @supports
.
/* See warning below */
@supports (width: 100vw) {
.full-width {
width: 100vw;
}
@media all and (min-width: 40rem) {
.full-width {
transform: translateX(calc((40rem - 100vw)/2));
}
}
}
The idea here is that none of this would apply if the browser didn’t support viewport units. That way you could pull fallback behavior above this in the CSS and let this override it if it can.
Seems like a good idea, but in my testing only Firefox got this right. Chrome would sometimes incorrectly apply the media query when it wasn’t supposed to (screenshot). (I say “sometimes” as it seemed like a redraw would “fix” it, only to not apply the media query the other direction.) Edge also didn’t seem to apply the media query rules at all (screenshot). Maybe nested @-rules are a bit buggy yet.
No calc() needed
Sven Wolfermann followed up Jon Neal’s idea with a clever variation that doesn’t need calc():
.full-width {
width: 100vw;
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw;
margin-right: -50vw;
}
The idea here is: push the container to the exact middle of the browser window with left: 50%;
, then pull it back to the left edge with negative -50vw
margin.

Very clever! This way you don’t need any information about the parent width at all. Do note that both this and the calc()
version require the parent to be exactly centered in the browser.
You might even think: why bother with the right
and margin-right
? It’s true you don’t really need it on a left-to-right site, but if there is any chance of direction: rtl;
happening, you’ll need the right properties, so having both is more bulletproof.
I’m gonna put a fork of this method here, as it seems the most useful.
See the Pen full viewport width image (container) inside article by Chris Coyier (@chriscoyier) on CodePen.
This is just awesome, thank you!
The Chrome bug might be from not measuring viewport units correctly when the document’s
overflow
is set to something other thanauto
. I ran into that problem with this technique too (scroll down to “Oh no, a horizontal scrollbar”), and it doesn’t look like they’ve fixed it since then.I just found the reason reading this text here:
“At some point, the items will overflow the viewport. On Windows, a scroll bar will appear, slightly shrinking the viewport. On OS X, a smart scroll bar will appear over the content which shows and hides automatically, thus not affecting the viewport. How is that relevant? Here’s a bit of the specification:”
In the same idea, here an code pen to get Image sized to half of the viewport with bootstrap3..perhaps this can be useful for somebody
Very cool, but please don’t do this if you can help it
It would probably be useful to explain why not.
Great summary, Chris! I wrote a post on this very topic, though I’d completely missed Jonathan Neal’s tweet! Great minds and all that.
Personally, I prefer the
calc
version. Allow me to be a self-quoting dork to explain why:Can this be used for emails?
Considering you generally can’t even safely use a float within emails, I’d say don’t use this. It’ll probably just fall back to typical standard positioning where not supported, but some clients do weeeeird things to email.
Maybe with simples a fallback?
No. 100% and 50% would refer to the parent’s width, thus cancelling any effect.
If the browser doesn’t support vw, just don’t use anything.
Unfortunately, the issue is that “full width” image will always be cut by the vertical browser scrollbar (~25px). Anyone has a solution for that?
For now, everyone is just using JS, or modifying layout of parent containers (to just apply width:100% to the image).
Curious about this too. It is possible with using calc():
.full-width {
width: calc(100vw – 25px);
position: relative;
left: 50%;
right: 50%;
margin-left: calc(-50vw + 12.5px);
margin-right: calc(-50vw + 12.5px);
}
@Vince:
Then you’d have a 12.5px gap on the right on devices whose OS and/or settings defaults to having a scrollbar over the content, namely every single Mac without a standard mouse plugged in and every single mobile device.
The truth is, while this technique surely would be ideal in a perfect world, the current spec for the viewport units is so dumb it prevents us from using it, as well as vw-based grids.
See Gabriel Tadeu’s comment for details on the spec.
Genius! You’ve delivered again Chris.
I was racking my brain just yesterday on how to get full width colored backgrounds when inside a
.container
.What you say, about a such decision?
p.s. sry for my eng
The not so cool method of selecting anything but the image:
See the Pen full viewport width image (container) inside article – simple version by David Bullock (@serkai) on CodePen.
That’s amazing! Thanks!
I’m still wondering where could this trick be useful…
Say you are a publication, and you have some great photos and want to display some of them at 100%, whoever is writing the content just needs to drop the images in the middle of said text and boom! full with images.
Really? Ever written a blog and wanted a full-bleed image?
Very nice trick, thank you. :) BTW I was wondering how you got the idea of that amazing lorem ipsum-like text filled with bacon and similar words in many languages. :D
http://baconipsum.com/
Thank you, wefegererg!
What about this solution?
theres even Zombie and skateipsum :)
Yup – I found a bug with regards to that specific situation in Chrome – turns out,
@media
blocks inside@supports
were not being re-evaluated on resize. I sent a bug report (and blogged about the bug) and the Chromium folks had a fix real quick – so that particular situation should be resolved soon. :-)Very cool! Have to say I prefer this method though:
.full-width {
width: 100vw;
position: relative;
left: 50%;
transform: translateX(-50%);
}
hell ya! this is awesome!
Awesome! I didn’t even thought about doing this.. Will consider this in near future.. =D
Awesome sauce!
I had created a CodePen last year just for doing that. I did it with margin-left and translateX.
awesome!
Great article!
FYI The image is missing in the CodePen.
Although this is a great and easy solution, it also feels a bit ‘hacky’, breaking out of the box this way. If you can control your markup, I guess it would always be nicest to have a container for your paragraphs, etc. and have your images be the 100% width.
Thanks for the ‘no calc needed’ solution!
Here’s an additional tip: if you want to have content inside any full-width element, you can apply your main wrapper properties to all child elements of any .full-width element like this: