28

Let's say we have a container that is centered in the viewport ...

.centered{margin: 0 auto; width:960px;}

... and inside that container I have another that needs to have a width of 100% the viewport width. I could set the margin to ...

.widest{margin: 0 -480px}

... for example. The thing is that the value won't be -480px, but actually the viewport width (960px) - the .centered width / 2 ... all good and easy with calc(), only I need a result that is a negative value.

.widest{
  margin: 0 calc( (100vw - 960px) / 2 );
}

I've tried subtracting the lot from 0 to get a negative value, but no go.

I don't want to use JS and I only have issues in Webkit - not with the calc() though - my problem is that if I hack it into submission by doing ...

.widest{
  margin: 0 -100%;
}

... my page scrolls horisontally in Chrome/Safari.

Your thoughts?

BoltClock
  • 630,065
  • 150
  • 1,295
  • 1,284
Jayx
  • 3,486
  • 3
  • 26
  • 35

4 Answers4

48

EDIT: A simpler trick than previous ones: calc(0px - something) - with an unit - works while calc(0 - something) doesn't. See Fiddle 3

These "tricks" work:

calc(1px - something - 1px);
calc(-1 * something)
calc(0px - something) /* new */

where 0 - something didn't (at least with your example).

Fiddle 1
Fiddle 2

FelipeAls
  • 20,411
  • 7
  • 49
  • 71
25

Yes, this is possible, to a point. The crucial part is to set the width of the element to 100vw then offset it by negative half the viewport width plus half the width of the centered element using, e.g. calc(-50vw + 200px):

Demo Fiddle

Given the HTML

<div id='center'>center
    <div id='full'>full width</div>
</div>

CSS

html, body {
    height:100%;
    width:100%;
    margin:0;
    padding:0;
    text-align:center;
    position:relative;
}
#center {
    width:400px;
    height:100%;
    background:red;
    margin:0 auto;
}
#full {
    width:100vw;
    height:100px;
    background:green;
    margin-left:calc(-50vw + 200px);
}
SW4
  • 65,094
  • 17
  • 122
  • 131
  • That would work if the layout was this simple, and I may just resolve to this, but the container that needs to become a "strap" across the page doesn't have the same height everywhere (although the height is fixed where used) - I'll also have to set margin/padding to the top of the next element to prevent it being overlaid by #full – Jayx Aug 08 '14 at 13:58
  • ... also: I would really like to know if it's possible to get a negative value from calc() – Jayx Aug 08 '14 at 13:58
  • I like both approaches, but this one feels a little less hackish ... also feeling a tad daft for not figuring this out by myself. Thanks – Jayx Aug 13 '14 at 06:56
  • 1
    @sw4 this is a nice solution. I cannot, however, figure out how to get it working for responsive `fluid`-ish layout where the `#center` does not have a static width, but a `max-width`, like [here](https://codepen.io/afkatja/full/QMvKGM) – afkatja Aug 09 '17 at 07:56
  • @afkatja if I've interpreted your point correctly, this article contains the solution required for a fluid center. `.full-width { width: 100vw; position: relative; left: 50%; right: 50%; margin-left: -50vw; margin-right: -50vw; }` https://css-tricks.com/full-width-containers-limited-width-parents/ – Dan Eastwell Nov 20 '17 at 09:35
7

I have another possible solution. You can devide by -2, so you'll get a negative Result

.widest{
  margin-left: calc( (100vw - 960px) / -2 );
}
sneduka
  • 71
  • 1
  • 1
2

You could try next solution

.some-class {
   margin-left: calc(-1px - ((100vw - 100%) / 2) + 1px);
}
Oleg Sewruk
  • 873
  • 7
  • 11