Posted 5 months ago. Visible to the public. Linked content.

How to: expand an element's cover area beyond its container

Occasionally, your designer will hand you designs where elements break the layout's horizontal container width, like navigation buttons of a slider that should be at the left/right of the browser window, or simply by applying a background color that reaches until the left and right of the browser window.

In the past, we've done some horrible things to achieve that. Like margin: 0 -10000px plus overflow-x: hidden.
There is a much saner approach.

Consider the following markup:

<body> <div class="container"> <div class="section"> Hello </div> </div> </div>

Let's say .container encloses its contents like so:

.container { margin: 0 auto; max-width: 800px; }

If you simply set the background color of .section, it looks odd.

.section { background-color: #aaf; }

You can use the ::before and ::after elements to fill in the blanks for you. CSS calc will help you out:

.section { background-color: #aaf; position: relative; } .section::before, .section::after { background-color: #aaf; content: ''; position: absolute; top: 0; bottom: 0; } .section::before { left: calc(50% - 50vw); right: 100%; } .section::after { left: 100%; right: calc(50% - 50vw); }

Here is how we place the ::before element left of the section element (and ::after vice versa):

  • left: calc(50% - 50vw) is the key: left: 50% is the center of the element. We subtract half the viewport width and end up at the very left of the window.
  • right: 100% means that the right side of ::before ends at the left of .section.

Using this approach, we do not need to know about the section height or container dimensions [1] and won't overlay any contents of the element itself, while actually expanding the element's interactable area [2].

View the attached example to see it in action.

Note that if you have a vertical scrollbar, 100vw will include the scrollbar width, effectively causing a horizontal scrollbar. To cover clickable areas, it's often fine to use 99vw or 98vw and accept a small non-clickable margin. Or you could still use overflow-x: hidden and feel a little bad about it.

[1] One might argue that could also omit position: relative on .section, and place the before/after helpers using left: 0 or right: 0. However, you'd then need to know the height or start/end offset of the section itself.
For the "slider buttons" case, you'd need relative position on your element anyway (to vertically center them), so you're already halfway there.

[2] If you want to style a slider whose next/previous buttons live outside the slider and should appear only when hovering the entire "row" the slider is placed in, you should also use this. Otherwise buttons appear when hovering the (containered) slider, but disappear again when moving the mouse pointer to the left or right. Hovering the before/after elements actually means hovering the element itself.

Growing Rails Applications in Practice
Check out our new e-book:
Learn to structure large Ruby on Rails codebases with the tools you already know and love.

Owner of this card:

Arne Hartherz
Last edit:
5 months ago
by Arne Hartherz
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Arne Hartherz to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more