Maintaining consistent spacing across multiple lines with a flex-box container: A guide

Here is my starting point: Click here

The spacing I have on the sides of the container is larger than between the content. When resizing the window, the elements eventually wrap to the second line.

I want to set a breakpoint so that when the content moves to the second line, the two right-most content divs move together.

On each line in the container, I want it to look like this:

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

Can this be done with CSS only or do I need JavaScript?

Edit: Adding code from Fiddle below.

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;
}

Answer №1

Here is an innovative approach to achieving the desired result. By utilizing two sets of buffer divs with different flex-grow values (10 for large and 2.5 for small), we can control the display of content based on media query breakpoints. This method involves systematically toggling the visibility of each set of buffer divs to show only one set at a time, resulting in a seamless transition between layouts.

To minimize HTML markup, consider using CSS pseudo-elements like :after and :before as outlined in the edited section below.

Result:

Upon reaching the first media query breakpoint, the layout will appear as follows:

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

To implement this solution, calculate the max-width of your media queries based on the size of the .content elements.

For Example: If .content has a width of 200px, then:

1st media query breakpoint max-width: 4 x 200px = 800px

2nd media query breakpoint max-width: 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 enhance the efficiency of your layout by leveraging CSS Pseudo-elements (:after and :before) to reduce the number of buffer divs required.

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]

An alternative approach involves adjusting the width of the container based on media query breakpoints, eliminating the need for buffer divs. By setting specific widths and flex-grow values within two separate media queries, you can achieve centered content alignment without additional markup. Check out this JSFiddle DEMO for a practical example.

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>

Answer №2

UPDATE: In this revised solution, I have corrected my previous example based on incorrect assumptions about the item count limitation and their behavior. You can view the updated code snippet in this jsfiddle link: http://jsfiddle.net/7b2L25a5/32/, and for the JavaScript version - http://jsfiddle.net/7b2L25a5/38/

REVISED SOLUTION

To achieve the desired layout, I recommend adding an additional wrapper instead of multiple 'buffer' divs. Adjust the flex-basis and flex-grow values of the inner wrapper dynamically based on the number of items per line. This way, the spacing between items stretches proportionally with the outer 'buffers' using pseudo-elements within the outer container:

body { margin: 10px 0; }

.outer_container {
    display: flex;
    flex-wrap: nowrap;
    justify-content: stretch;
}

.outer_container::before,
.outer_container::after {
    content: '';
    flex: 4 0 0;
}

.middle_container {    
    display: flex;
    /* adjust flex value depending on items per line */
    flex: 1 0 104px;
    flex-wrap: wrap;
    justify-content: space-between;
}

.content{
    width: 50px;
    border: solid 1px red;
}

@media screen and (min-width: 260px) {
    /* adjust flex value for different item counts per line */
    .middle_container { flex: 3 0 208px; }
}
<div class="outer_container">
    <div class="middle_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>
The number of media queries required will vary based on the layout variations. For two variations (2 or 4 items per line), only one media query is necessary.

Answer №3

I don't quite understand the purpose of using buffer divs in this scenario. By properly styling the top component with CSS, you should be able to eliminate the need for buffers altogether.

.wrapper {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
}

Check out the fiddle

Answer №4

To accomplish this task using only CSS, you will need to utilize the @media rule along with an external CSS file.

Within your CSS file, the structure may resemble the following:

@media all { 
    .class  
    #id
}

The @media all declaration is a default set for screens not specifically targeted. For specific screen sizes, use the format below:

@media screen and (min-width: 1278px) and (max-width: 1282px) {
#id
.class
}

By specifying ids and classes within the parentheses above, you can create rules that override those in the @media all section. These rules will only apply to screens with widths between 1278px and 1282px; targeting a screen size of 1280px wide and variable height, such as a 12-inch netbook.

The key lies in understanding the overall structure. For example, if you have four 400px square images totaling 1600px in width, on an 800px screen two images would display per line.

Implementing flexbox without proper HTML markup could lead to unwanted transitions, where items may not align correctly across lines. To achieve a specific layout like having two items move together to the second line, correct coding is essential.

The ideal markup is as follows:

<div id="Container">

<div id="Inner"> <div id="Box">Content1</div> <div id="Box">Content2</div> </div>
<div id="Inner"> <div id="Box">Content3</div> <div id="Box">Content4</div> </div>

</div>

Accompanied by the correct CSS styling:

#Container { position: relative; width: auto; min-width: 800px; display: flex; flex-flow: row wrap; } 

#Inner { position: relative; display: inline-block; }

#Box { position: relative; display: block; }

Although the flex container is relatively new, potential glitches may arise during implementation. Adjustments like changing the position attribute or ensuring default fallback settings may be necessary for optimal functionality.

I am confident that the information provided addresses your query effectively. Best of luck with your design endeavors!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to delete the <li> element from a webpage

Here is the HTML code snippet that I am working with: <form name="package_type_documents" action="" method="post" enctype="multipart/form-data"> <div class="hor-form"> <ul> <li> <div class="answ ...

What is causing the animate function to hide the other div once the animation is completed?

Check out the code here http://codepen.io/kongakong/pen/wMQrBR Javascript Section: $(document).ready(function () { init(); }); function init() { $('#test').on('click', function () { $('.answer').animate({width: ...

How to utilize Node.js to send a document to Amazon S3

I recently wrote a function to upload files to S3 using the 'aws-sdk' in JavaScript, but I encountered an issue. When I replaced Body with Body: "test", the function executed successfully and I could see the content 'test' in my S3 buc ...

Managing an undetermined quantity of elements from a form in PHP

Currently developing an inventory page for my job. I've crafted a page that will iterate through my database and showcase all the items stored within. include 'auth.php'; //authentication required for login change $sql="SELECT * FROM `inven ...

Send the loop index as a parameter to a function within the onclick attribute of an HTML <input> element using vue.js

My goal was to develop a basic to-do list using vue.js to familiarize myself with it. Now, I've successfully added a remove button next to each item. To achieve this, I included a remove() function in JavaScript with a id parameter, which corresponds ...

Adjust the height automatically in extjs hbox layout with this quick guide

When I try to dynamically set data in this layout, the layout doesn't resize properly and the final result looks like this. This is the code I'm currently using: win = Ext.create('widget.window', { title: 'Layout Window&apo ...

content inside a span tag using the ng-bind directive is invisible

Here is my issue. <span class="col-sm-3 col-md-3" ng-bind-template="{{controller.getToolTip()}}"> <span class="icon " ng-class="controller.getIcone()" aria-hidden="true"></span> </span> Within my controller, the getToolTip() fu ...

Preserving KendoGrid Selection Status During Navigation Between Pages

When using kendoGrid, I encounter an issue where the selected product ID does not persist across different pages. Initially, when the grid is loaded, the corresponding row is selected based on the productID. However, after unchecking the product ID on the ...

The functionality of Jquery datatables seems to be faulty when navigating to the second page

While utilizing the jQuery datatables plugin, I encountered an issue where the event click function only worked on the first page and not on subsequent pages. To address this problem, I discovered a helpful resource at https://datatables.net/faqs/ Q. My ...

send Javascript syntax errors and console.log output to a different location

I'm experimenting with ways to redirect output from the javascript console to my own custom functions. Here's what I've attempted: window.console.error = window.console.debug = window.console.log window.console.log = mylog; function mylo ...

Retrieve the JSON array value from the observable and pass the information to the frontend

Attempting to retrieve a JSON array from a json-server using observables, then passing the value to the frontend for search functionality on the received JSON array. Created a service and utilized HTTP get method to establish a connection with the server ...

Scraping a p tag lacking a class attribute with the help of BeautifulSoup4 (Bs4)

I am attempting to scrape this information from a website: enter image description here Within the HTML, there is a div tag with a class. Inside that div tag, there is another div tag and then a lone p tag without a class. My objective is specifically to ...

Switching between different elements in an array using React

I've got a collection of appointments and I need to create a React view that will show them one by one. Users should be able to navigate through the appointments using arrow buttons. Here's an example of what the data looks like: const arr = [ ...

Dynamic WordPress Website Designs

Seeking recommendations for responsive WordPress themes that offer extensive CSS and structural customization options. The goal is to retain all of WordPress's built-in features, such as blogging capabilities, while having the freedom to completely co ...

In Internet Explorer 8, the Radmenu hover menu may appear below surrounding Radmenus

Utilizing a radmenu, I am able to dynamically generate a submenu structure by examining folders in sharepoint document libraries. However, when placing multiple controls on the page, the root menu from other controls overlaps with the submenu of the curren ...

Koa.js route() isn't a defined function

Recently, I created a basic koa app that should return rss xml based on a tag using a parameter. However, for some reason the middleware is unable to read the router from the router file and I cannot figure out why it's not working as expected. The ap ...

Missing Modal in Fullcalendar Display

I am working on setting up an HTML modal for FullCalendar in Django using various solutions, but unfortunately, the modal does not appear when clicked. I have tried different approaches and consulted resources, but so far, I have not been successful. Any ...

Bootstrap image badges

I am seeking help to place badges on an image, similar to the example picture below. My knowledge of CSS is limited, so any assistance would be greatly appreciated. .product { margin: 0 30px 30px 0; width: 360px; position: relative; float: left; ...

Loop through a JSON object

I am looking to iterate through a JSON object called transactionByFop. Here is the HTML code: <div ng-show="searchController.orderCAT.results.length" ng-repeat="(key,obj) in searchController.orderCAT.results track by $index"> <dl sty ...

Is there a way in HTML to navigate directly to a specific element on another page, even if it is not currently visible

I have used an anchor to navigate to a specific element on another page from the current page. However, the specific element I want to navigate to is not currently visible because it is controlled by JavaScript to keep the page short. The element is only s ...