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

Change the text color of the Vuetify button to customize its appearance

Is there a way to change the default active color for button text in a toolbar using CSS? v-btn(:to="item.path" active-class="v-btn--active toolbar-btn-active") {{item.meta.title}} I attempted to override it with this custom class: .toolbar-btn-active { ...

The style of the button label does not persist when onChange occurs

Encountered an interesting issue here. There is a button designed for selection purposes, similar to a select item. Here's the code snippet: <button class="btn btn-primary dropdown-toggle" style="width: 166%;" type="button" id="dropdownMe ...

Bizarre Incident Management

My latest project involves a simplistic website featuring arrow images (png) positioned on the left and right sides with fixed placement, allowing users to navigate to the next page. However, an issue arises where the cursor seems unable to select the an ...

Submitting search parameters with an HTML button

Is there a way to replace the lower input text field with a button, like this: <input type="button" class="button" name="search" value="Urban" onclick="">. HTML CODE: <form method="post" action="search.php" id="search_form"> <input typ ...

What is the best way to create a transparent sticky header that blends with the background while still maintaining visibility over images and text?

On my web page, the background features a radial gradient but the content extends beyond the viewport, causing the center of the gradient to not align with the center of the screen, producing the desired effect. However, I'm facing an issue with a sti ...

Position icons and images on the right side, and the textarea on the left side of the page (using Twitter

Summary: Here is the desired end result shown in the image below. Alternatively, you can refer to the JSFiddle. Ideally, only CSS should be used without changing the DOM structure. The icons need to be aligned completely to the right using the .pull-right ...

Ways to split up array objects in an axios GET request

Hello, I recently implemented an AXIOS GET request that returns an array of objects. However, the current example I am using retrieves the entire array at once, and I need to separate the objects so that I can work with them individually. class CryptoAP ...

Can someone tell me where I can locate the CSS file once I've finished using Scene Builder?

Currently, I am working on my database project using Scene Builder. I have applied some CSS styling and would like to locate the CSS file in order to attach it to my IntelliJ project for further code editing. Can anyone guide me on where to find the CSS ...

Python Web Scraping Automation Tool - Inconsistent Encountering of 511 Error Code

My latest project involves opening Firefox with Selenium, extracting HAR files using BrowserMobProxy, and accessing JSON data from those files at timed intervals. Occasionally, however, I encounter a 511 Error: <!DOCTYPE html><html><head> ...

"Items within mui Grid do not properly align within the Grid container

I'm struggling to fit two large Grid items inside a Grid container. The Grid container needs to be 100% of the screen's height (or parent container) Grid items are large and need to fill the container while remaining scrollable Image #1 shows t ...

Clicking on the image does not result in a larger image being displayed

Currently working on an assignment that requires a modal pop-out to display larger versions of photos when clicked, with the option to go back using the X button. Unfortunately, I'm facing issues with the X button not functioning properly and images n ...

Is it possible to align a CSS table row with its corresponding table header even when the table row is deeply nested within the table structure?

I am looking to keep the structure of my HTML code consistent and unaltered. However, this has resulted in a form tag being nested inside a table row before the table cells can begin. The information I need to display is tabulated data, which makes CSS t ...

modify the inherent CSS property

I am working with a component that I have inherited, including its CSS style, and I need to modify one of its properties. Current CSS: .captcha-main-image { width: 100%; height: auto; } <img class ="captcha-main-image" id="captchaImage" src= ...

Lately, I've been working on a practice website I'm developing, and I'm facing some issues with my hyperlinks

Get the omisphere download I created this hyperlink because my previous attempts didn't work, but unfortunately, this one still isn't functioning properly. Is it possible that the issue is with my CSS? ...

Modifying the page header content using JavaScript

There's this snippet of code that alters the image on another page: <div class="imgbx"> <button onclick="window.location.href='index.html?image=images/xr-black.jpg&tit=XR-black'" >Invisible ...

Exploring ways to display all filtered chips in Angular

As a new developer working on an existing codebase, my current task involves displaying all the chips inside a card when a specific chip is selected from the Chip List. However, I'm struggling to modify the code to achieve this functionality. Any help ...

Having trouble retrieving the toDataURL data from a dynamically loaded image source on the canvas

Currently, I am working on a project that involves a ul containing li elements with images sourced locally from the "/images" folder in the main directory. <section class="main"> <ul id="st-stack" class="st-stack-raw"> ...

Is there a way to horizontally center a content container in Flutter similar to a "max-width" container in CSS?

How can I create a centered content box like this in Flutter?: .content-box { margin-left: auto; margin-right: auto; width: 100%; max-width: 600px; background-color: blue; height: 100vh; } <div class="content-box"> Cont ...

When it comes to Shopify Schema, the section settings are functional within the <style> tag, whereas the block settings do not seem to have the same

While working on updating a section with multiple blocks, I encountered an unusual issue. My goal was to incorporate a new block into an existing section. The schema has been set up correctly, and everything is functioning as anticipated. However, the prob ...

The code for the bouncing image isn't functioning properly outside of the JSFiddle environment

I'm having issues with this jQuery snippet in my web application. It works fine on jsfiddle, but not when I add it to my project. Here's the code: $('.myimage').mouseenter(function() { $(this).effect('bounce',500); }); Her ...