Combining left-aligned and centered elements within a grid using flexbox

Looking to create a fluid responsive grid layout using flexbox, without the need for media queries. The number of elements in the grid can vary and each item should have a fixed, equal width with left alignment. The entire group should have equal left and right margins.

Here's an example of what I'm aiming for:

This is how I attempted to achieve it:

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  margin: auto;
}
.item {
  height: 200px;
  width: 200px;
  background-color: purple;
  padding: 10px;
  margin: 10px;
}
<div class="container">
  <div class="item">Flex item 1</div>
  <div class="item">Flex item 2</div>
  <div class="item">Flex item 3</div>
  <div class="item">Flex item 4</div>
  <div class="item">Flex item 5</div>
</div>

Unfortunately, this approach did not yield the desired results:

I had hoped that by setting margin: auto on the container, it would size itself to accommodate an optimal number of items per row.

While solutions like Bootstrap or Foundation would make this task easier, I am curious if it can be achieved using flexbox alone.

Answer №1

CSS Grid

Implementing CSS Grid is a stylish and adaptable solution for layout design.

.container {
  display: grid;
  grid-template-columns: repeat(auto-fill, 200px);
  grid-auto-rows: 200px;
  grid-gap: 10px;
  justify-content: center;
}

.item {
  background-color: purple;
  padding: 10px;
}
<div class="container">
  <div class="item">Flex item 1</div>
  <div class="item">Flex item 2</div>
  <div class="item">Flex item 3</div>
  <div class="item">Flex item 4</div>
  <div class="item">Flex item 5</div>
</div>

However, it may lack support in older browsers like IE, requiring the use of Javascript to achieve similar functionality due to flexbox issues with width distribution.

Javascript Approach

The Javascript method calculates the necessary margin-left value to centrally align flexbox items, ensuring compatibility despite initial markup settings.

// get width of element with margins
function getOuterWidth(el) {
  var styles = window.getComputedStyle(el);
  var margins = parseFloat(styles["marginLeft"]) +
    parseFloat(styles["marginRight"]);

  return Math.ceil(el.getBoundingClientRect().width + margins);
}

// get width of element without paddings
function getContentWidth(el) {
  var styles = window.getComputedStyle(el);
  var paddings = parseFloat(styles["paddingLeft"]) +
    parseFloat(styles["paddingRight"]);

  return Math.ceil(el.getBoundingClientRect().width - paddings);
}

// Get top of element
function getTopOfElement(el) {
  return el.getBoundingClientRect().top;
}

var container = document.querySelector(".container");
var initialMarginLeft = parseFloat(window.getComputedStyle(container)["marginLeft"]);
// getting array of items
var items = Array.prototype.slice.call(document.querySelectorAll(".item"));

function centerItems() {
  if (items.length === 0) return 0;

  // set margin-left to initial value to recalculate it
  container.style.marginLeft = initialMarginLeft + "px";

  var topOfFirstItem = getTopOfElement(items[0]);
  var spaceTakenByElementsOnFirstLine = getOuterWidth(items[0]);

  for (var i = 1; i < items.length; i++) {
    // Break in case we are in second line
    if (getTopOfElement(items[i]) > topOfFirstItem)
      break;
    spaceTakenByElementsOnFirstLine += getOuterWidth(items[i]);
  }

  // Set margin-left to center elements
  var marginLeft = initialMarginLeft + (getContentWidth(container) - spaceTakenByElementsOnFirstLine) / 2;

  container.style.marginLeft = marginLeft + "px";
};

window.addEventListener("resize", centerItems);

centerItems();
.container {
  display: flex;
  flex-wrap: wrap;
}

.item {
  height: 200px;
  width: 200px;
  background-color: purple;
  padding: 10px;
  margin: 10px;
}
<div class="container">
  <div class="item">Flex item 1</div>
  <div class="item">Flex item 2</div>
  <div class="item">Flex item 3</div>
  <div class="item">Flex item 4</div>
  <div class="item">Flex item 5</div>
</div>

jQuery Implementation

// get width of element with margins
function getOuterWidth(el) {
  return $(el).outerWidth(true);
}

// get width of element without paddings
function getContentWidth(el) {
  return parseFloat($(el).css("width"));
}

function getTopOfElement(el) {
  return $(el).position().top;
}

var $container = $(".container");
var $items = $(".item");
var initialMarginLeft = parseFloat($container.css("margin-left"));

function centerItems() {
  if ($items.length === 0) return 0;

  // set margin-left to initial value to recalculate it
  $container.css("margin-left", initialMarginLeft + "px");

  var topOfFirstItem = getTopOfElement($items[0]);
  var spaceTakenByElementsOnFirstLine = getOuterWidth($items[0]);

  for (var i = 1; i < $items.length; i++) {
    // Break in case we are in second line
    if (getTopOfElement($items[i]) > topOfFirstItem)
      break;
    spaceTakenByElementsOnFirstLine += getOuterWidth($items[i]);
  }

  // Set margin left to center elements
  var marginLeft = initialMarginLeft + (getContentWidth($container) - spaceTakenByElementsOnFirstLine) / 2;

  $container.css("margin-left", marginLeft + "px");
};

$(window).resize(centerItems);

centerItems();
.container {
  display: flex;
  flex-wrap: wrap;
}

.item {
  height: 200px;
  width: 200px;
  background-color: purple;
  padding: 10px;
  margin: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="container">
  <div class="item">Flex item 1</div>
  <div class="item">Flex item 2</div>
  <div class="item">Flex item 3</div>
  <div class="item">...etc...</div>
  <div class="item">Flex item 5</div>
</div>

Answer №2

If you're looking for a simple solution, one approach is to include a series of invisible, zero-height items at the end of your regular items:

<div class="parent">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="dummyItem"></div>
  <div class="dummyItem"></div>
  <div class="dummyItem"></div>
  <div class="dummyItem"></div>
</div>

Additionally,

.parent {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
}

.parent .item,
.parent .dummyItem{
  width: 50px;
  height: 50px;
  background: white;
  margin: 5px;
}

.parent .dummyItem {
  height: 0;
}

If the longest row in your layout can accommodate n visible items, you will need at least n-1 dummy items for this method to be effective.

The only drawback to this technique is that if there is only one row of items, they may not be perfectly centered but rather aligned mostly to the left.

View Codepen Example.

Answer №3

Unable to achieve desired layout using flexbox right away (I couldn't figure it out myself). One option is to use justify-content: center; but this will center all children resulting in a layout like:

The workaround I found is to introduce another parent element and wrap everything inside it.

Check out this CodePen example: http://codepen.io/justd/pen/rOeMGZ

You'll likely discover a solution that works for you by experimenting with various CSS techniques.

Answer №4

Although I tried using flexbox, I couldn't achieve this specific behavior. However, it can easily be done with CSS Grid. Simply add justify-content: center to the container.

Check out this example on CodePen

Answer №5

To achieve the desired layout, set a specific width for the container and then apply margin: 0 auto to the containing element. This will center it horizontally on the page instead of spanning the full width.

For a visual example, you can check out this Codepen link: http://codepen.io/janedoe/pen/RzKlja

Answer №6

If you're struggling with getting your grid container to work properly, try adding a max-width to it. This will allow the auto margins to function correctly. Currently, your container is expanding 100% to both sides, leaving no room for the auto margin to take effect.

To ensure that your container expands to a maximum of 3 items per row, set the max-width to 660 (item width + item margin):

.container {
  max-width: 660px;
  margin: 0 auto;
  display: flex;
  flex-flow: row-wrap;
}
.item {
  width: 200px;
  height: 200px;
  margin: 10px;
}

Check out this Codepen example for reference: http://codepen.io/kgrote/pen/qbpGWZ

With this setup, the container will fluidly expand until reaching its maximum width, then center itself while maintaining a left-aligned grid layout for its children. As the container shrinks, the children will stack accordingly.

Answer №7

It's essential to structure your page with default margins on the left and right using percentages instead of pixel widths. This approach ensures that your page will be responsive and display well on all devices without needing Javascript. If you desire, you can also set a maximum width for added control over the layout. By making these adjustments in the CSS code provided below, you should achieve the desired result effortlessly.

.pageLayout {
    margin: 0 auto;
    width: 80%;
    /* add optional max width  */
}

.container {
  display: flex;
  flex-wrap: wrap;
}
.item {
  height: 200px;
  width: 200px;
  background-color: purple;
  padding: 10px;
  margin: 10px;
}
<div class="pageLayout">
  <div class="container>
    <div class="item">Flex item 1</div>
    <div class="item">Flex item 2</div>
    <div class="item">Flex item 3</div>
    <div class="item">Flex item 4</div>
    <div class="item">Flex item 5</div>
  </div>
</div>

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

The Material UI - makeStyles function is having difficulties generating the intended styles

After implementing withStyles and makeStyles from material-UI, I encountered an issue where the CSS styling was not as expected, despite the correct class name being returned. For example, consider the following component: import React, { Component } fro ...

Issue with horizontal scrolling functionality in DataTables

I have a table with over 10 columns, and I am using datatables to display the data. I have enabled horizontal scrolling due to the large number of columns, but the scroll is not appearing. Can someone please assist me with this issue? Here is a screenshot ...

Strip the CSS styling from an image (the CSS being included in the generated code)

I need to remove the CSS styling from an image, but I can't modify the generated code where it's coming from. My actual code looks like this: <div class="bubble"> <img id="one" src="/static/webupload/MyronArtifacts/images/descarga.png ...

Choose the immediate sibling located right after a specific element

My goal is to have the second paragraph following a h1 element display a dropcap, with the first being reserved for the author and date. Although I've tried using different CSS combinations like h1 + p::first-letter {}, it only affects the first para ...

What is the process for enabling SASS line numbers using Yeoman's Grunt.js file?

Recently, I used Yeoman (1.4.5) to scaffold a new web application. Within my Gruntfile.js, I configured it as follows: ... // When requested, compile Sass to CSS and generate necessary files sass: { options: { lineNumbers:true, sourceMap: true, ...

Creating a Sticky Header and Footer with Responsive Design: Ensuring Content Div Expansion between Them

Greetings. I am working on creating a simple responsive HTML layout as described below: HTML: <div id="header"></div> <div id="content"></div> <div id="footer"></div> CSS: #header{ wi ...

Can you explain the meaning of the tag "&" ">" "*" in the context of useStyles functions?

After experimenting with React and Material-UI, I came across an interesting pattern in the code. When using the useStyle function, developers often create a class called 'root' and utilize the tag & > *. I tried to research the meaning be ...

Angular Tag < with CSS styling

Why should we use the angular tag in CSS? For example: .class << span Typically, we use these types of tags: body { background-color:#d0e4fe; } h1 { color:orange; text-align:center; } p { font-family:"Times New Roman"; font-si ...

What are the steps to employ a query string to display a specific image?

If I understand correctly, I can utilize a query string and parse it to display certain information. How would I apply that concept to load a specific image? https://codepen.io/anon/pen/qYXexG <div id="gallery"> <div id="panel"> <img ...

Ways to ensure a row of floated images within a <div> container adjusts its size in sync with the browser

Struggling to resize four images inside a div as the browser window is resized? Frustrated that when the window is too small, the last image moves to the next row? Want them all to stay in one row? Despite searching for solutions, adjusting max-widths to 2 ...

Improving the layout and size of text within input fields

How can we adjust the input text positioning to the right so it's not directly against the edge? Is there a way to move 'searching' 5px to the right? ...

Is there a way to ensure that the 'pointermove' event continues to trigger even after the dialog element has been closed?

I am working on a project that involves allowing users to drag elements from a modal dialog and drop them onto the page. I have implemented a feature where dialog.close() is called once the user starts dragging. This functionality works perfectly on deskto ...

Conceal the page's content as it moves beneath a stationary div

My issue involves a fixed div position with a margin from the top of the page. When I scroll my page, the content of my relatively positioned div (containing page content) is visible under the fixed div due to the margin from the top of the page. Despite s ...

Scrolling animations do not support the Translate3d feature

I'm struggling to implement a smooth scroll effect on the header of my website. My approach involves using transform:translate3d for animation, with the goal of keeping the header fixed at the top and moving it out of view as the user scrolls down. I ...

Discover the magic of Bootstrap 3.0 Popovers and Tooltips

I'm struggling with implementing the popover and tooltip features in Bootstrap. While I have successfully implemented drop downs and modals, the tooltips are not styled or positioned correctly as shown in the Bootstrap examples, and the popover featur ...

Achieving Vertical Alignment of Text and Icon in the Same Line Using HTML and CSS

I am struggling to align these icons vertically center with the text. However, there seems to be a slight offset of a few pixels. I have experimented with different solutions, but this is the closest I could get to. Can anyone explain why it's not ali ...

Tips for keeping a div fixed at a specific scroll level

Is there a way to keep a specific side div fixed at a particular scroll level, similar to the "How to format" bar on the right side of the Stack Overflow ask question page? You can see it when you try asking a question. How can this be achieved - with CS ...

Ensure that the dropdown menu remains visible even after the mouse no longer hovers over it

Looking to create a main menu with dropdown items that appear when the user hovers over them? You may have noticed that typically, the dropdown disappears once the hover event is lost. But what if you want the menu to stay visible and only disappear upon c ...

Is there a way to give only the left corners of a button a rounded look?

Here is the visual representation of the button: https://i.stack.imgur.com/Bjlkp.png ...

Troubleshooting display problems with the categories menu in Opencart version 1.5.1 caused by IE

For our opencart website, we utilize the li element for the sub categories items. displays properly on all modern browsers. However, we need to ensure compatibility with Internet Explorer 6 as well. ...