Align the final row to the left in a flexbox that is centered

My issue involves a flexbox containing NxN squares. I need the container to adjust to fit as many squares as possible within the display width, while also center-aligning the flexbox on the page.

The problem arises when I set the CSS property:

justify-content: center

This results in an alignment issue with the last row as shown in the following image: https://i.stack.imgur.com/yzwru.jpg

If I change it to:

justify-content: left

It fixes the alignment of the last row but disrupts the overall center alignment of the container on the page. Is there a way to combine these two scenarios? For example, having 5 items centered with the last row aligning with the first item in previous rows?

Here is a minimal reproduction of the issue:

<style>
  div { display: flex; flex-wrap: wrap; justify-content: center; }
  i { display: block; width: 300px; height: 300px; background: black; margin: 10px; }
</style>
<div>
  <i></i> <i></i> <i></i> <i></i> <i></i>
  <i></i> <i></i> <i></i>
</div>

Answer №1

Your design layout follows a standard grid structure. In this case, utilizing CSS grid would be more suitable compared to using flexbox.

By incorporating the auto-fit property for the columns and specifying a fixed size for each, the grid will adjust to accommodate as many columns as possible within the container. Applying justify-content: center will center the columns while maintaining the left-to-right content flow.

Here's an example:

div {
    display: grid;
    gap: 10px;
    grid-template-columns: repeat(auto-fit, 160px);
    justify-content: center;
}

span {
    background: red;
    display: block;
    height: 160px;
}
<div>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
</div>

Answer №2

After some research, I came across the solution here

Implementing the following CSS code resolved the issue:

div:after {
    content: '';
    flex: auto;
    margin: 10px;
    max-width: 300px;
}

However, this caused a problem with responsiveness on iPad and mobile devices. To address this, you can apply the above CSS only for larger screens using a media query.

It is advised not to use this method; instead, consider switching from flex-box to grid layout as suggested by @nathan

Answer №3

Here is a unique approach to solve the problem at hand. I am utilizing Angular (Typescript) for this demonstration, but the underlying concept applies universally.

To begin, you will require the following two methods / functions:

  /** 
   * Obtain the width of each item within the flexfox (ensuring equal width!)
   */
  getFlexboxItemWidth(selector: string){
    return document.querySelector(selector)?.getBoundingClientRect().width
  }

  /**
   * Determine the number of additional, hidden flexbox items to insert
   */
  calculateFlexboxFillerItemCount(totalItems: number, selector: string, flexboxSelector: string): number{
    const flexboxWidth: number = document.querySelector(flexboxSelector)?.getBoundingClientRect().width as number
    const itemsPerRow: number = Math.trunc(flexboxWidth / (this.getFlexboxItemWidth(selector) as number))
    const itemsInLastIncompleteRow: number = totalItems % itemsPerRow
    return isNaN(itemsPerRow) 
            || isNaN(itemsInLastIncompleteRow) 
            || itemsPerRow - itemsInLastIncompleteRow === Infinity 
            || itemsInLastIncompleteRow === 0 
              ? 0 
              : itemsPerRow - itemsInLastIncompleteRow + 1
  }

After implementing these two methods, proceed with their incorporation:

  <!--The Flexbox-->
  <ion-list id="home-tab--item-list-container" *ngIf="items.length > 0">

    <!--Visible Flex Items-->
    <ion-card class="home-tab--item-card" *ngFor="let item of items" (click)="goToItemDetails(item)">
      <img [src]="item.images[0]">
      <ion-card-header>
        <ion-card-title>{{item.title}}</ion-card-title>
      </ion-card-header>
    
      <ion-card-content>
        {{item.description}}
        <div class="home-tab--item-slide-price">
          ${{item.cost.toFixed(2)}}
          <div class="home-tab--item-rental-period" *ngIf="item.rentalPeriod !== null">
             /{{item.rentalPeriod}}
          </div>
        </div>
      </ion-card-content>
    </ion-card>

    <!--Invisible Flexbox Items responsible for filling remaining space of last row-->
    <ion-card [ngStyle]="{width: getFlexboxItemWidth('.home-tab--item-card')+'px', visibility: 'hidden'}" *ngFor="let _ of [].constructor(calculateFlexboxFillerItemCount(items.length, '.home-tab--item-card', '#home-tab--item-list-container'))">
    </ion-card>

  </ion-list>

Lastly, here are the style modifications for improved visual representation:

#home-tab--item-list-container {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    width: 100%;
    overflow: auto;
}

.home-tab--item-card {
    min-width: 170px;
    max-width: 300px;
    cursor: pointer;
}

@media screen and ( max-width: 960px) {
    .home-tab--item-card  { flex: 0 1 30% }
}

End Result:

https://i.stack.imgur.com/ehFwb.gif

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 are some strategies for accessing the original values of form components that have not been altered when using ngModel?

I am currently developing a form and I intend to utilize the previous values as "value" in the form. By employing ngModel dynamically, I am able to change some properties. However, I have encountered an issue where the field that remains unchanged by the u ...

Identical HTML elements appearing across multiple DOM pages

My question might seem silly, but I'm facing an issue. I have several HTML pages such as index.html and rooms.html, along with a main.js file containing scripts for all of these pages. The problem arises because I have variables like const HTMLelemen ...

Tips for incorporating transitions into CSS styling

After successfully adding a picture over an element when hovering over it, I decided to include a transition: 0.2s; property but unfortunately the transition effect is not working as expected. Why is this happening? My intention is for the picture to smoot ...

Having trouble bringing in css files

I'm having trouble loading a CSS file when trying to import it into another CSS file. I've tried various ways of defining the path but nothing seems to work. Any insights on what might be causing this issue? https://i.sstatic.net/IwaY1.png ...

Unleash the power of jQuery by incorporating the Ajax functionality with a hover option to enhance user interactivity. Utilize the .ajax

On my website, I have a calendar displayed with dates like "11/29/2014" stored in an attribute called "data-date". The goal is to check the server for a log file corresponding to that date and change the CSS of the div on mouse hover. Here is the current ...

Trigger JQuery function post CSS styling completion

Upon using $(document).ready(function() {...}, it seems that the function is invoked after the DOM has loaded, but potentially before CSS styles have been completely applied. My goal is to obtain the width of a particular element. Strangely, when attempti ...

Ways to Create a Webpage with a Single Color Palette

Struggling to update the background color on my webpage and hitting a wall. Even with content, the black background only extends as far as the content does. I've experimented with extending the content, using the body selector, and universal selector ...

Uninterrupted jQuery AJAX calls

I have a scenario where I need to periodically update an image on my view using ajax every 10 seconds. Any suggestions on how I can achieve this? Appreciate the help. ...

Is there a way to modify the rounded corners of a checkbox in material-ui?

After importing material-ui into my react app, I was able to change the color and size of a checkbox as shown. However, I am having trouble changing the icon's border radius. How can I achieve this? import FormGroup from '@mui/materi ...

Overlay displayed on top of a single div element

Trying to implement a loading overlay in an Angular project within a specific div rather than covering the entire page. Here's a Fiddle illustrating my current progress: #loader-wrapper { top: 0; left: 0; width: 100%; height: 100%; ...

An issue with the font display

I'm having trouble with a specific font on my webpage and jsfiddle, even though it works fine on w3schools website. Here's an example on jsfiddle HTML <div> With CSS3, websites can finally use fonts other than the pre-selected "web-safe" ...

Error: Material-UI prop type validation failed - Please specify either `children`, `image`, `src`, or `component` prop

Despite having an image prop in CardMedia, I kept encountering this error. Here is a snippet of the code: Error description: const Post = ({ post, setter }) => { const classes = useStyles(); return( <Card className={classes.card} ...

I'm having trouble getting this text to align properly next to the image. Plus, I can't seem to achieve a horizontal screen alignment either

There seems to be an answer available, but I'm clearly not understanding it, so I've come here seeking further explanation and assistance. CSS can be quite complex, right? Here's a screenshot of my current project: https://i.stack.imgur.com/ ...

What is the best way to utilize the bootstrap grid system for smaller screens while incorporating a table?

I have a PHP generated table that retrieves data and dynamically displays it in a table. It is crucial to ensure that the table data adjusts according to the screen size. Below is the code snippet: echo "<div class='container'><div cla ...

App builder shows raw HTML code instead of generating a dynamic table

I am currently working on an application that requires gathering data in a csv format from Google Sheets and importing it into App Inventor. Additionally, I need to include HTML code to display the table in a more visually appealing way. Here is what the ...

Display one div and conceal all others

Currently, I am implementing a toggle effect using fadeIn and fadeOut methods upon clicking a button. The JavaScript function I have created for this purpose is as follows: function showHide(divId){ if (document.getElementById(divID).style.display == ...

The navigation bar is failing to redirect to another page upon clicking in Bootstrap 5

The problem arises when attempting to navigate with the navbar item, as it fails to redirect to the intended page and provides no feedback. However, upon removing the bootstrap.bundle.min.js, the redirect feature operates as expected. Nonetheless, the coll ...

Adjust the top position of a div element at regular intervals

How can I make the top position of an absolutely positioned div with children change every x seconds using jQuery? I tried using setInterval but it only changes once. Here is my code: .com_prices { width: 100%; height: 100%; overflow: hidden; back ...

Guide to updating the value of an input field with Selenium in Python

I have an input element that I need to clear its current value and input a new one. The HTML structure is as follows: <input class="input-mini" type="text" name="daterangepicker_start" value=""> To locate this element, I used the following code: ...

What is the best way to compile an array of permissible values for a specific CSS property?

One interesting aspect of the CSS cursor property is its array of allowed values, ranging from url to grabbing. My goal is to compile all these values (excluding url) into an array in JavaScript. The real question is: how do I achieve this without hardco ...