Expand side elements outside fixed width container

For one of my latest projects I needed to expand some elements outside a fixed width container in a way that their backgrounds reached the sides of the screen but its content remained within its parent container.

A picture is worth a thousand words so this is roughly what I was trying to achieve:

Fluid side elements within fixed container

I ran into an article on CSS Tricks with a nice technique to stretch a single elements outside its parent container, however for my use case the number of elements was unknown and I needed to expand the first and last on each row.

Using magic numbers

If we use a large fixed number as the element’s negative margin we can effectively “expand” it to that side, combining it with the same number as its padding will offset its content so only the background is stretched.

Initial implementation with fixed margins and paddings

Here we’re using margin-left: -2000px and padding-left: 2000px to stretch the first element to the left and the same values on margin-right and padding-right to stretch the last element to the right.

We can use almost any unit here but we’ll still run into the same problem, the layout will break if the screen is larger than what our magic number accounts for, also we’ll need to use overflow-x: hidden on our html / body elements to hide the extra horizontal space taken by our elements which is not a big deal but we can do better nowadays.

Enter math

Math’s boring I know but it’s the best way to represent what we need to do, basically we need to know exactly how much horizontal space we have available on the sides of our main container so we won’t need to rely on magic numbers. Luckily we can use the viewport’s width and our container’s width to get exactly what we want:

Side Width = (Viewport Width - Container Width) / 2

Using calc and vw units

The calc function and vw unit are well supported by every modern browser and provide a good way to express our formula in CSS.

Implementation using calc and vw units

We’re still using negative margin and padding however instead of relying on magic numbers we use calc and vw to represent our formula like this:

padding-left: calc((100vw - 100%) / 2);

This way the element expands exactly as much as needed without using magic numbers or having to use overflow: hidden on the parent element, we can also use the same formula with a negative -100vw for the margin property. This works really well when it’s paired with flexbox to allow multiple elements to take equal amounts of space.

Let me know if you have other use cases for calc and the vh / vw units, they’re very helpful to achieve cool layout structures without relying on CSS hacks or javascript.