Brandon Durham
Brandon Durham

Reputation: 7717

Calculating column size outside of the scope of the grid container

In my grid system the container that houses the grid is full browser width for all breakpoints but one: xl, or 1920px and up. Above 1920px the container has a max-width of 1920px and is centered on the screen, so the outside gutters are different sizes, depending on the width of your viewport. Calculating column widths inside of this container is a breeze. If I want an element to span 6 columns, I just do this:

width: calc((6 / 12 * 100%) - 24px;

In pseudo code, that breaks down like this:

width = (columns / totalColumns) - gutter;

Now here’s my conundrum: I’m adding an element that exists outside of the scope of the grid container but somehow need to be able to make it also adhere to the grid layout. It’s essentially an overlay, and is position: fixed. The overlay fills the full viewport with a semi-transparent background and has an interior element called .Panel (the white box in the below screenshot).

.Panel has two sizes for each breakpoint: default and expanded. For most breakpoints, default is equal to 50vw - gutter (top example in below screenshot). Simple. No problem. Gutters have static px sizes for all breakpoints, so they’re super easy to work with. However, expanded is a bit trickier.

For the expanded state, the .Panel will have to stick to the right side of the screen and the left side of the .Panel has to begin at column 2. Here is an visual aid:

panel layout

Since the column widths use percentage values, I’m not entirely sure how to do the calculations in CSS alone to ensure that, no matter the size of your 1920px-and-up viewport, the .Panel will start at column 2 and end at the right side of the viewport.

Any suggestions around how to pull this off?

Upvotes: 2

Views: 667

Answers (1)

Brandon Durham
Brandon Durham

Reputation: 7717

Okay, so the way I ended up pulling this off was to move my overlay into the grid container. Reason being I can’t access the scope of the grid container from outside of it (50% inside the container means something different than 50% outside of it), but I can access the scope of the viewport (viewport units) from within the grid container.

Adding this line ensures that the overlay panel starts at the correct column and extends outside of the grid container all the way to the right side of the viewport:

margin-right: calc((50vw - 100% / 2) * -1);

Pseudo code:

margin-right: calc((half_viewport_width - grid_container_width / 2) * -1);

This just gets the width of the viewport, subtracts the width of the grid container leaving me with the gutters between the grid container and viewport boundaries. I only need the size of one gutter, so I divide by 2. Finally, we need negative margins, so I multiply by -1.

body {
    background-color: grey;
    margin: 0;
}

.wrapper {
    background-color: tomato;
}

.grid-container {
    background-color: pink;
    display: flex;
    margin: 0 auto;
    max-width: 800px;
}

.panel {
    background-color: white;
    flex-grow: 1;
    height: 50vh;
    margin-left: 25%;
    margin-right: calc((50vw - 100% / 2) * -1);
    width: 75%;
}
<div class="wrapper">
    <div class="grid-container">
        <div class="panel">
            Panel!
        </div>
    </div>
</div>

Upvotes: 2

Related Questions