Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to preserve a spacing template on multiple lines using a flex-box container

Here is where I'm starting: http://jsfiddle.net/Vercingetorix333/7b2L25a5/2/

As you can see The spacing that I have on either end of the container (flex size: 10) is much larger than the spaces between the content (flex size: 2.5). At the moment when a user decreases the size of the html window, the elements do eventually wrap to the second line (as intended).

What I'd like to do however is set the first window resizing break-point / responsiveness factor so that when content does move to the second line (maybe using @media.... in css?) it takes the two right-most content divs in one go.

Then I desire for each line in the container to look like this:

large buffer - content - small buffer - content - large buffer

Can I do this purely in css? Or do I need some javascript?

Edit: Adding my code from Fiddle (for posterity's sake).

HTML

<div class="outer_container">

    <div class="outer_buffer"></div>

    <div class="content">Some Content</div>
    <div class="inner_buffer"></div>
    <div class="content">Some Content</div>
    <div class="inner_buffer"></div>
    <div class="content">Some Content</div>
    <div class="inner_buffer"></div>
    <div class="content">Some Content</div>

    <div class="outer_buffer"></div>

</div>

CSS

.outer_container{
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
}
.outer_buffer{
    flex-grow: 10;
}
.inner_buffer{
    flex-grow: 2.5;
}
.content{
    width: 50px;
    border: solid 1px red;
}
like image 766
Vercingetorix Avatar asked Sep 03 '14 18:09

Vercingetorix


1 Answers

You could do it like this answer. I'm using two sets of large (flex-grow 10) and small (flex-grow 2.5) buffer divs for first and second window resizing break-points and I've systematically assigned display: none to one set at a time to show only one set of large and small buffer divs for each @media query break-point. I'm using two container divs and each container div have two content divs and at the first window resizing @media query break-point moves the right container to the second line. Actually, it takes the two right-most content divs in one go as per your desire result.

Please look at my answer's edited section (below) to accomplish it with minimum HTML markup by using the CSS pseudo-elements (i.e. :after and :before).

Result:

At first @media query break-point the result look like this:

large buffer (10) - content - small buffer (2.5) - content - large buffer (10)
large buffer (10) - content - small buffer (2.5) - content - large buffer (10)

All you need to do is calculate the max-width of CSS @media queries break points as per .content size for this solution.

For Example: If you set the width of .content to 200px then:

1st @media query break point of max-width is: 4 x 200px = 800px

2nd @media query break point of max-width is: 2 x 200px = 400px

Example: JSFiddle - DEMO

JSFiddle - DEMO

.wrapper {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
}
.container {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    flex-grow: 2.5;
}
.content {
    width: 50px;
    border: solid 1px red;
}
.lg {
    flex-grow: 10;
}
.sm {
    flex-grow: 2.5;
}
.w-buffer {
    display: block;
}
.c-buffer {
    display: none;
}
@media (max-width: 224px) {
    .wrapper {
        display: block;
    }
    .container {
        justify-content: center;
        flex-grow: 0;
    }
    .w-buffer {
        display: none;
    }
    .c-buffer {
        display: block;
    }
}
@media (max-width: 120px) {
    .wrapper {
        display: flex;
    }
    .w-buffer, .c-buffer {
        display: none;
    }
}
<div class="wrapper">
    <div class="w-buffer lg"></div>
    <div class="container">
        <div class="c-buffer lg"></div>
        <div class="content">Some Content</div>
        <div class="c-buffer sm"></div>
        <div class="content">Some Content</div>
        <div class="c-buffer lg"></div>
    </div>
    <div class="w-buffer sm"></div>
    <div class="container">
        <div class="c-buffer lg"></div>
        <div class="content">Some Content</div>
        <div class="c-buffer sm"></div>
        <div class="content">Some Content</div>
        <div class="c-buffer lg"></div>
    </div>
    <div class="w-buffer lg"></div>
</div>

You could also use the CSS Pseudo-elements (i.e. :after and :before) to reduce the number of buffer divs.

JSFiddle - DEMO

body {
    margin: 8px;
}
.wrapper {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
}
.container {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    flex-grow: 2.5;
}
.content {
    width: 50px;
    border: solid 1px red;
}
.pseudo-buffer:before, .pseudo-buffer:after {
    content:" ";
    display: block;
}
.wrapper.pseudo-buffer:before, .wrapper.pseudo-buffer:after {
    flex-grow: 10;
}
.buffer {
    flex-grow: 2.5;
}
@media (max-width: 224px) {
    .wrapper {
        display: block;
    }
    .container {
        justify-content: center;
        flex-grow: 0;
    }
    .wrapper.pseudo-buffer:before, .wrapper.pseudo-buffer:after {
        display: none;
    }
    .container.pseudo-buffer:before, .container.pseudo-buffer:after {
        flex-grow: 10;
    }
}
@media (max-width: 120px) {
    .wrapper {
        display: flex;
    }
    .wrapper.pseudo-buffer:before, .wrapper.pseudo-buffer:after, .container.pseudo-buffer:before, .container.pseudo-buffer:after, .buffer {
        display: none;
    }
}
<div class="wrapper pseudo-buffer">
    <div class="container pseudo-buffer">
        <div class="content">Some Content</div>
        <div class="buffer"></div>
        <div class="content">Some Content</div>
    </div>
    <div class="buffer"></div>
    <div class="container pseudo-buffer">
        <div class="content">Some Content</div>
        <div class="buffer"></div>
        <div class="content">Some Content</div>
    </div>
</div>

[EDITED]

You could also do it without using any buffer divs just by set the width to container as per @media queries break-point and I'm using two @media queries break-point because I think, if there is only one content div per line then content divs should be horizontally center inside the container div and If you don't want to use the second @media query break-point then just remove it and set min-width: 104px; to the container for @media (max-width: 208px). You could do it like this JSFiddle DEMO

JSFiddle - DEMO

body {
    margin: 20px 0px 0px 0px;
}
.wrapper {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
}
.content {
    width: 50px;
    border: solid 1px red;
}
.container {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    flex-grow: 7.5; /* Total space between 4 content divs same as 3 x 2.5 flex-grow */
}
.wrapper:before, .wrapper:after {
    content: " ";
    flex-grow: 10;
}
@media (max-width: 208px) {
    .container {
        width: 104px; /* 2 (content divs per line) x 52px (content div's width) */
        flex-grow: 2.5;
    }
}
@media (max-width: 104px) {
    .container {
        width: 52px;
        flex-grow: 0; /* Set value 0 to center content divs inside the container */
    }
}
<div class="wrapper">
    <div class="container">
        <div class="content">Some Content</div>
        <div class="content">Some Content</div>
        <div class="content">Some Content</div>
        <div class="content">Some Content</div>
    </div>
</div>
like image 169
Anonymous Avatar answered Oct 12 '22 01:10

Anonymous