326

Is there a way to have a child DIV within a parent container DIV that is wider than its parent. The child DIV needs to be the same width as the browser viewport.

See example below: enter image description here

The child DIV must stay as a child of the parent div. I know I can set arbitrary negative margins on the child div to make it wider but I can't work out how to essentially make it 100% width of the browser.

I know I can do this:

.child-div{
    margin-left: -100px;
    margin-right: -100px;
}

But I need the child to be the same width as the browser which is dynamic.

Update

Thanks for your answers, it seems the closest answer so far is to make the child DIV position: absolute, and set the left and right properties to 0.

The next problem I have is that the parent has position: relative, which means that left and right properties are still relative to the parent div and not the browser, see example here: jsfiddle.net/v2Tja/2

I can't remove the position: relative from the parent without screwing everything else up.

Yvonne Aburrow
  • 2,602
  • 1
  • 17
  • 47
Camsoft
  • 11,718
  • 19
  • 83
  • 120
  • Your requirements don't really make sense. The "child div" must stay as a child of the parent div, and yet the parent div has `position: relative`? What do you need `position: relative` for? I guess what I'm asking is: what are you trying to do? – thirtydot Apr 07 '11 at 21:28
  • @Camsoft Did you see my comment on my answer? That works for me, Also check my website http://edocuments.co.uk/ which does what you are trying to do in a different way – Blowsie Apr 08 '11 at 14:41
  • 1
    @Camsoft in addition , there really should be no need for any jquery / js in your solution – Blowsie Apr 08 '11 at 14:42

15 Answers15

348

Here's a generic solution that keeps the child element in the document flow:

.child {
  width: 100vw;
  position: relative;
  left: calc(-50vw + 50%);
}

We set the width of the child element to fill the entire viewport width, then we make it meet the edge of the screen by moving it to the left by a distance of half the viewport, minus 50% of the parent element's width.

Demo:

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  overflow-x: hidden;
}

.parent {
  max-width: 400px;
  margin: 0 auto;
  padding: 1rem;
  position: relative;
  background-color: darkgrey;
}

.child {
  width: 100vw;
  position: relative;
  left: calc(-50vw + 50%);

  height: 100px;
  border: 3px solid red;
  background-color: lightgrey;
}
<div class="parent">
  Pre
  <div class="child">Child</div>
  Post
</div>

Browser support for vw and for calc() can generally be seen as IE9 and newer.

Note: This assumes the box model is set to border-box. Without border-box, you would also have to subtract paddings and borders, making this solution a mess.

Note: It is encouraged to hide horizontal overflow of your scrolling container, as certain browsers may choose to display a horizontal scrollbar despite there being no overflow.

Community
  • 1
  • 1
Nils Kaspersson
  • 8,816
  • 3
  • 29
  • 30
  • 4
    What do you know, it does indeed work in IE9. +1 Nice – CatShoes Jul 29 '14 at 18:24
  • 14
    This was exactly what I was looking for thank you very mutch. IMO this is a better answer than the accepted one since this one doesn't break document flow – Rémi Dec 14 '14 at 15:11
  • 23
    vw is no good. If you have a vertical scrollbar then 100vw will give you a horizontal scrollbar. – Sunny Jan 26 '15 at 13:29
  • 2
    It seems that this only works one level down. Is there a way for it to work regardless of how many parent elements a child element has? – mythofechelon Aug 14 '15 at 15:12
  • @mythofechelon as you can see in [this fork](http://codepen.io/Mest/pen/xGemMK?editors=110), it works even if the child element is nested in elements with `padding` and/or `margin`. It won't, however, work if you assign a `width` to them – even if that width is 100%. If you need to set a width then you'll need add the distance between the child and the parent elements to the calc(). – Nils Kaspersson Aug 14 '15 at 16:00
  • @Nils Kaspersson That's great, thank you. Is there a way to remove a property with CSS? – mythofechelon Aug 17 '15 at 12:52
  • @mythofechelon Yeah, kind of. Just set the property to its initial value. In the case of `width`, the default value is `auto`. Refer to MDN, or your dev tools, or any similar resource for the initial values of any properties. In the future you'll be able to use the [`initial`](https://developer.mozilla.org/en-US/docs/Web/CSS/initial) keyword, but we're still waiting for Microsoft to implement it. – Nils Kaspersson Aug 17 '15 at 12:58
  • 1
    @Nils Kaspersson Awesome, thank you again! Tip: Squarespace uses the LESS compiler so `left: calc(~"-50vw + 50%");` must be used or it will be translated into `left: calc(0vw);` – mythofechelon Aug 17 '15 at 13:19
  • 3
    This is the right answer to wrap wider child element into a `position: relative` parent! – Hanfei Sun Sep 24 '15 at 04:45
  • How does this appear when degraded by older browsers? – Merchako Feb 25 '16 at 05:05
  • @Merchako Invalid/unknown values invalidate the entire property declaration, so browsers that don't support `vw` will ignore both rules. Remove the `width` and `left` declaration to see what it would look like. If a browser supports `vw` but doesn't support `calc()` then you'll get an unwanted `left`-assignment. Use feature detection to set the rules if you need to support such a browser. – Nils Kaspersson Feb 25 '16 at 08:22
  • A simple `margin-left: calc(...);` does the same thing as the `position: relative;` & `left calc(...);` combo. Is there some reason `position: relative;` is a better choice? – typo Mar 09 '19 at 06:50
  • @typo `margin` theoretically affects surrounding elements whereas `left` does not. Chances are you can achieve the exact same result with `margin`, I just prefer using the most correct property. – Nils Kaspersson Mar 12 '19 at 13:28
  • @mythofechelon same for xf as well - wondering why it was glitching, but your modification for less solved it. Many thanks! – DanielSon May 07 '19 at 10:05
  • I guess `overflow: overlay` can be added to the parent to remove horizontal scrollbar – BrunoElo Mar 25 '22 at 04:57
140

Use absolute positioning

.child-div {
    position:absolute;
    left:0;
    right:0;
}
Blowsie
  • 40,239
  • 15
  • 88
  • 108
  • 14
    Ok, next question, what if the parent or another ancestor has layout i.e. position: relative, see: http://jsfiddle.net/v2Tja/2/ – Camsoft Apr 07 '11 at 14:00
  • 1
    how about another parent div being position:static, and another div inside with position:relative? http://jsfiddle.net/blowsie/v2Tja/3/ – Blowsie Apr 07 '11 at 15:20
  • 11
    is there a way to do this, whith the .child-div's height auto and still have the correct placement below? – Philippe Gilbert Apr 02 '13 at 19:28
  • 2
    and don't set the parent div to "overflow:hidden" ^^ – chris Nov 05 '13 at 10:35
  • @Blowsie how about `position:fixed `. why it doesn't work properly? – Mostafa Ghadimi Jul 03 '19 at 12:44
  • no, if you use position:absolute, the content will be placed on top of everything else on your application, which is awful!! Nils Kasperssons answer is the right way!! – OutlawSloth Dec 21 '21 at 10:58
  • 1
    Best answer. No scrollbar problems. High cross-browser compatibility. Thanks!!! – jMike Sep 20 '22 at 18:02
26

I've searched far and wide for a solution to this problem for a long time. Ideally we want to have the child greater than the parent, but without knowing the constraints of the parent in advance.

And I finally found a brilliant generic answer here. Copying it verbatim:

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.

.child-div {
  width: 100vw;
  position: relative;
  left: 50%;
  right: 50%;
  margin-left: -50vw;
  margin-right: -50vw;
}
Daniel
  • 11,332
  • 9
  • 44
  • 72
  • 1
    I found if I want it to be, say, 90% of the viewport width, I can use the above but set width to `90vw`. Also, it appears that `margin-right` has no effect in any case. – Jason Dufair Oct 31 '17 at 17:45
  • had to change the margin-left and right values cause my wrapper is 80% of viewport width. So in my case it had to be margin-left:-10vw and margin-right:-10vw and then it perfectly worked! thanks! – Timotheus0106 Jul 12 '19 at 18:53
8

Based on your suggestion original suggestion (setting negative margins), I have tried and come up with a similar method using percentage units for dynamic browser width:

HTML

<div class="grandparent">
    <div class="parent">
        <div class="child">
            <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolore neque repellat ipsum natus magni soluta explicabo architecto, molestias laboriosam rerum. Tempore eos labore temporibus alias necessitatibus illum enim, est harum perspiciatis, sit, totam earum corrupti placeat architecto aut minus dignissimos mollitia asperiores sint ea. Libero hic laudantium, ipsam nostrum earum distinctio. Cum expedita, ratione, accusamus dicta similique distinctio est dolore assumenda soluta dolorem quisquam ex possimus aliquid provident quo? Enim tempora quo cupiditate eveniet aperiam.</p>
        </div>
    </div>
</div>

CSS:

.child-div{
   margin: 0 -100%;
   padding: 0 -100%;
}

.parent {
    width: 60%;
    background-color: red;
    margin: 0 auto;
    padding: 50px;
    position:relative;
}

.grandparent {
        overflow-x:hidden;
        background-color: blue;
        width: 100%;
        position:relative;
    }

The negative margins will let the content flow out of the Parent DIV. Therefore I set the padding: 0 100%; to push the content back to the original boundaries of the Chlid DIV.

The negative margins will also make the .child-div's total width expands out of the browser's viewport, resulting in a horizontal scroll. Hence we need to clip the extruding width by applying an overflow-x: hidden to a Grandparent DIV (which is the parent of the Parent Div):

Here is the JSfiddle

I haved tried Nils Kaspersson's left: calc(-50vw + 50%); it worked perfectly fine in Chrome & FF (not sure about IE yet) until I found out Safari browsers doesn't do it properly. Hope they fixed this soon as I actually like this simple method.

This also may resolve your issue where the Parent DIV element has to be position:relative

The 2 drawbacks of this workaround method is:

  • Require extra markup (i.e a grandparent element (just like the good ol' table vertical align method isn't it...)
  • The left and right border of the Child DIV will never show, simply because they are outside of the browser's viewport.

Please let me know if there's any issue you find with this method ;). Hope it helps.

Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252
Austeroid
  • 101
  • 1
  • 6
6

Flexbox can be used to make a child wider than its parent with three lines of CSS.

Only the child’s display, margin-left and width need to be set. margin-left depends on the child’s width. The formula is:

margin-left: calc(-.5 * var(--child-width) + 50%);

CSS variables can be used to avoid manually calculating the left margin.

Demo #1: Manual calculation

.parent {
  background-color: aqua;
  height: 50vh;
  margin-left: auto;
  margin-right: auto;
  width: 50vw;
}

.child {
  background-color: pink;
  display: flex;
}

.wide {
  margin-left: calc(-37.5vw + 50%);
  width: 75vw;
}

.full {
  margin-left: calc(-50vw + 50%);
  width: 100vw;
}
<div class="parent">
  <div>
    parent
  </div>
  <div class="child wide">
    75vw
  </div>
  <div class="child full">
    100vw
  </div>
</div>

Demo #2: Using CSS variables

.parent {
  background-color: aqua;
  height: 50vh;
  margin-left: auto;
  margin-right: auto;
  width: 50vw;
}

.child {
  background-color: pink;
  display: flex;
  margin-left: calc(-.5 * var(--child-width) + 50%);
  width: var(--child-width);
}

.wide {
  --child-width: 75vw;
}

.full {
  --child-width: 100vw;
}
<div class="parent">
  <div>
    parent
  </div>
  <div class="child wide">
    75vw
  </div>
  <div class="child full">
    100vw
  </div>
</div>
Markus
  • 352
  • 1
  • 4
  • 10
4

I used this:

HTML

<div class="container">
 <div class="parent">
  <div class="child">
   <div class="inner-container"></div>
  </div>
 </div>
</div>

CSS

.container {
  overflow-x: hidden;
}

.child {
  position: relative;
  width: 200%;
  left: -50%;
}

.inner-container{
  max-width: 1179px;
  margin:0 auto;
}
smonff
  • 3,399
  • 3
  • 36
  • 46
hsuastegui
  • 49
  • 2
3

I tried some of your solutions. This one :

margin: 0px -100%;
padding: 0 100%;

is by far the best, since we don't need extra css for smaller screen. I made a codePen to show the results : I used a parent div with a background image, and a child div with inner content.

https://codepen.io/yuyazz/pen/BaoqBBq

blogob
  • 490
  • 5
  • 19
2

I had a similar issue. The content of the child element was supposed to stay in the parent element while the background had to extend the full viewport width.

I resolved this issue by making the child element position: relative and adding a pseudo element (:before) to it with position: absolute; top: 0; bottom: 0; width: 4000px; left: -1000px;. The pseudo element stays behind the actual child as a pseudo background element. This works in all browsers (even IE8+ and Safari 6+ - don't have the possibility to test older versions).

Small example fiddle: http://jsfiddle.net/vccv39j9/

Seika85
  • 1,981
  • 2
  • 18
  • 29
  • This seems to work, but it causes the browser to show a horizontal scrolbar since the width is 4000px. What's the workaround to keep the pseudo element within the viewport's width? – Aaron Hudon Jul 10 '14 at 03:18
  • Of course you have to set the body or the page wrapping div to `overflow-x: hidden`. – Seika85 Oct 13 '14 at 13:46
2

To make child div as wide as the content, try this:

.child{
    position:absolute;
    left:0;
    overflow:visible;
    white-space:nowrap;
}
brooksrelyt
  • 3,925
  • 5
  • 31
  • 54
Toki
  • 268
  • 3
  • 10
1

I know this is old but for anyone coming to this for an answer you would do it like so:

Overflow hidden on a element containing the parent element, such as the body.

Give your child element a width much wider than your page, and position it absolute left by -100%.

Heres an example:

body {
  overflow:hidden;
}

.parent{
  width: 960px;
  background-color: red;
  margin: 0 auto;
  position: relative;    
}

.child {
  height: 200px;
  position: absolute;
  left: -100%;
  width:9999999px;
}

Also heres a JS Fiddle: http://jsfiddle.net/v2Tja/288/

Tom Chinery
  • 611
  • 6
  • 2
1

Adding to Nils Kaspersson's solution, I am resolving for the width of the vertical scrollbar as well. I am using 16px as an example, which is subtracted from the view-port width. This will avoid the horizontal scrollbar from appearing.

width: calc(100vw - 16px);
left: calc(-1 * (((100vw - 16px) - 100%) / 2));
Mi-Creativity
  • 9,554
  • 10
  • 38
  • 47
A-Zone
  • 41
  • 1
  • 8
  • 1
    I believe the `16px` which you need to subtract because it is causing the horizontal scrollbar is the default margin/padding of the browser, instead of subtracting it just use this `html, body{ margin:0; padding:0 }` thus yo uwon't need to make extra calculation for the `16px` – Mi-Creativity Feb 06 '16 at 19:51
  • This is when the page content is longer and goes below the fold and the scroll bar appears automatically. Of course, when content is within the fold, this is not needed. I add the 16px to the formula only when I know the page content is going to be long and the scroll bar would indeed appear. – A-Zone Feb 08 '16 at 06:41
  • i think it won't work on mobile. mobile has no scrollbar. – hjchin Dec 29 '16 at 01:42
1

Assuming the parent has a fixed width, e.g #page { width: 1000px; } and is centered #page { margin: auto; }, you want the child to fit the width of browser viewport you could simply do:

#page {
    margin: auto;
    width: 1000px;
}

.fullwidth {
    margin-left: calc(500px - 50vw); /* 500px is half of the parent's 1000px */
    width: 100vw;
}
Nabil Kadimi
  • 10,078
  • 2
  • 51
  • 58
1

you can try position: absolute. and give width and height , top: 'y axis from the top' and left: 'x-axis'

Sam
  • 1,233
  • 1
  • 9
  • 16
Khurram Ijaz
  • 1,844
  • 5
  • 24
  • 43
0

Then solution will be the following.

HTML

<div class="parent">
    <div class="child"></div>
</div>

CSS

.parent{
        width: 960px;
        margin: auto;
        height: 100vh
    }
    .child{
        position: absolute;
        width: 100vw
    }
Himavan
  • 385
  • 3
  • 16
  • While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. – R Balasubramanian Aug 02 '18 at 15:17
0
.parent {
    margin:0 auto;
    width:700px;
    border:2px solid red;
}
.child {
    position:absolute;
    width:100%;
    border:2px solid blue;
    left:0;
    top:200px;
}
Sam
  • 1,233
  • 1
  • 9
  • 16