Aligning CSS Grid Center Based on Changing Content Quantity

In my current setup, a series of images are fetched from a database. When three or more images are added, it visually displays in three columns.

However, if there are fewer than three images, they align to the left within the parent container due to the display: grid; property I am using (as demonstrated by the red boxes in the code example).

I am wondering if it is possible to have one or two images centered within the parent element instead. While I could use JavaScript to detect the number of images and adjust the layout accordingly by changing the wrapper to display: flex, I am curious if there is a CSS-only solution for this scenario.

It's important to note that when there are more than three images present, I must stick with CSS Grid for the layout.

Note: I've commented out two of the red boxes in the HTML to illustrate the issue when only one red box is present.

Codepen: https://codepen.io/anna_paul/pen/xxXrVJQ

body {
  display: flex;
  justify-content: center;
  margin: 0
  width: 100%;
  height: 100vh;
}

.wrapper {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-gap: 1rem;
  max-width: 1250px;
}

.box {
  width: 200px;
  height: 200px;
  background: red;
}
<div class="wrapper">
  <div class="box"></div>
<!--   <div class="box"></div>
  <div class="box"></div> -->
</div>

Answer №1

Here is a simple way to achieve this:

.container {
  display: grid;
  grid-auto-flow: column; /* set flow direction to columns */
  justify-content: center; /* align items to the center */
  grid-gap: 1rem; /* set gap between items */
  max-width: 600px;
  border: 1px solid;
  margin: 10px auto;
}
.box:nth-child(3n + 1) {grid-column: 1;} /* set position of first box in every row */
.box:nth-child(3n + 2) {grid-column: 2;} /* set position of second box in every row */
.box:nth-child(3n + 3) {grid-column: 3;} /* set position of third box in every row */

.box {
  width: 100px;
  height: 100px;
  background: red;
}
<div class="container">
  <div class="box"></div>
</div>
<div class="container">
  <div class="box"></div>
  <div class="box"></div>
</div>
<div class="container">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>
<div class="container">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"\"></div>

Answer №2

When using 1fr for each column, even if a column is empty it still takes up 33% of the available space. To avoid this, consider using units other than fr, such as:

grid-template-columns: auto auto auto;
grid-template-columns: repeat(3, auto);

grid-template-columns: repeat(3, minmax(min-content, max-content));

You can use any of the above options. There is a subtle difference between auto and minmax(min-content, max-content).

Below is a demonstration with 3 containers containing 1, 2, and more than 3 items respectively:

body {
  margin: 0;
  width: 100%;
  height: 100vh;
}

.demo {
  display: flex;
  justify-content: center;
}

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, minmax(min-content, max-content));
  
  grid-gap: 1rem;
  width: auto;
  max-width: 1250px;
}

.box {
  width: 200px;
  height: 200px;
  background: red;
  border: 1px solid;
}
<p>Grid with one item</p>
<div class="demo">
  <div class="wrapper">
    <div class="box">1</div>
  </div>
</div>
<hr>
<p>Grid with two items</p>
<div class="demo">
  <div class="wrapper">
    <div class="box">1</div>
    <div class="box">2</div>
  </div>
</div>
<hr>
<p>Grid with >3 items</p>
<div class="demo">
  <div class="wrapper">
    <div class="box">1</div>
    <div class="box">2</div>
    <div class="box">3</div>
    <div class="box">4</div>
  </div>
</div>

The 1rem grid-gap will be maintained even if a column has a width of 0. In your setup (grid inside flex), the item in a single-grid container will deviate by 2rem (2 grid-gaps) from the center. If this is acceptable, no changes are needed.
However, if you want exact centering, set grid-gap: 0 and apply spacing inside grid items (.box) like margin: 0.5rem; or padding: 0.5rem to create an artificial grid-gap.

body {
  margin: 0;
  width: 100%;
  height: 100vh;
}

.demo {
  display: flex;
  justify-content: center;
}

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, minmax(min-content, max-content));
  
  width: auto;
  max-width: 1250px;
}

.box {
  width: 200px;
  height: 200px;
  background: red;
  border: 1px solid;
  
  margin: 0.5rem;
}
<p>Grid with one item</p>
<div class="demo">
  <div class="wrapper">
    <div class="box">1</div>
  </div>
</div>
<hr>
<p>Grid with two items</p>
<div class="demo">
  <div class="wrapper">
    <div class="box">1</div>
    <div class="box">2</div>
  </div>
</div>
<hr>
<p>Grid with >3 items</p>
<div class="demo">
  <div class="wrapper">
    <div class="box">1</div>
    <div class="box">2</div>
    <div class="box">3</div>
    <div class="box">4</div>
  </div>
</div>

Answer №3

Replace fr with auto and utilize align-content to resolve the issue at hand.

body {
  display: flex;
  justify-content: center;
  margin: 0
  width: 100%;
  height: 100vh;
}

.wrapper {
  display: grid;
  grid-template-columns: auto auto auto;
  align-content : start;
  /*  grid-gap: 1rem;  */ 
  max-width: 1250px;
}

.box {
  width: 200px;
  height: 200px;
  background: red;
  margin: 1rem ; 
}
<div class="wrapper">
  <div class="box"></div>
<!--   <div class="box"></div>
  <div class="box"></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

Incorrect data for minimal values within Google charts

Currently, I am utilizing a Google chart found at the following link: In my data set, I have significantly high values for the line chart and relatively low values for the bar chart. In order to make both types of data more easily readable, I would like t ...

Angular template not refreshing automatically

Within my controller: $scope.deleteUser = function(user){ $.ajax({ url: "/users/" + user.id.toString(), method: "DELETE", success: function(result){ $scope.users = result["users"]; ...

Repair the navigation bar once it reaches the top of the screen using ReactJS

I have a webpage that contains specific content followed by a bar with tabs. My goal is to have this bar stay fixed at the top of the screen once it reaches that position while scrolling down, and only allow the content below the fixed bar to continue scro ...

Scraping a website where the page source doesn't match what is displayed on the browser

Imagine I'm interested in extracting marathon running time data from a specific website: Upon inspecting the webpage using Google Chrome, I noticed that the desired data is not directly visible in the page source. Although I have successfully scraped ...

Creating a customized display on a webpage using XML and XSL to generate unique

Looking to utilize my xml file for generating various xsl pages. <movies> <movie> <name>Shark tank</name> <movie> <movie> <name>Tank Shark</name> <movie> ...

Angular 5 and Bootstrap card with enhanced double-click functionality

I want to design a Bootstrap card that can trigger two of my custom methods. <div (click)="TEST1()" class="card" style="width: 18rem;"> <div class="card-body"> <h5 class="card-title">Card title</h5> <button (click)="(T ...

Fixing the "Parsing error: Parenthesized pattern" issue using vanilla JavaScript

I'm currently working on a project for a job training program using HTML and JavaScript. The online code editor allows me to execute my code and there is even an "evaluate" button that verifies it against different test cases. My code functions as exp ...

Ways to change the CSS styling of the placeholder attribute within a textarea or input field tag

I am currently working on adjusting the font size of the text within the placeholder attribute of a textarea element. While I have been successful in achieving this using vanilla CSS, I have encountered difficulties when trying to implement the same concep ...

Get rid of the dashed outline surrounding the selected button

One of my divs has a button inside that, when clicked, creates an outline around it. Here is what it looks like: https://i.sstatic.net/pEr53.png **Code: ** .slide-arrow { color: #fff; background-color: #9E9997; border: none; padding: 16px 10px ...

I'm searching for a universal guidebook on creating web page layouts

After 5 years of creating webpages, I have realized that my sites tend to have a nostalgic 1995 internet vibe. Despite being a C# programmer with knowledge in HTML, JavaScript, and CSS, my design skills could use some improvement. Is there a quick referenc ...

What could be causing the unexpected white gap within my div element even though I've adjusted its dimensions to be minimal?

<div style=" height:0; width: 0 ; border: 1px solid black ; "> This code snippet displays a div element with a specified height, width, and border color. However, there seems to be an issue with the rendering as some st ...

What is the process for incorporating a personalized SVG file into the material-ui Icon Component?

For my project, I have a requirement to use custom svg files. To achieve this, I am utilizing <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0865697c6d7a616964257d61483b2631263b">[email protected]</a>. I reviewed ...

What steps should I take to ensure that the buttons on my restaurant website are correctly displaying the overlays?

I'm currently facing an issue with the functionality of the buttons on my React.js-powered restaurant website. These buttons are located within a component called MenuButtons.jsx and are situated at the bottom of a shorter menu section on the homepage ...

how to position one div above another using css

I currently have a page layout with 7 different div elements structured like this; <div id="container"> <div id="head"></div> <div id="A"> <div id="A1">A1</div> <div id="A2"></div> ...

Unselect a radio button

I am currently utilizing the bootstrap radio buttons and I want to implement a feature that allows for deselecting a radio group. I came across an approach in this (Fiddle), which involves using an additional button. Instead of adding a separate button, my ...

Can the unquoted HTML literal string syntax from scalatra be implemented in sinatra?

Is it possible to utilize this style in sinatra? get("/") { <html> <body> <h1>Hello, world!</h1> Say <a href="hello-scalate">hello to Scalate</a>. </body> </html> } I'm unsure i ...

Creating a clear distinction between a logo and accompanying text

I'm working with bootstrap 5 and I want to add a subtle line right after the logo.png below. The line should be directly connected to the logo with no spaces, and also no spaces between the text and the line. <!-- Bootstrap-5 --> <link hre ...

Verify the presence of plain ASCII text

I need to verify if the file uploaded is in ascii plain text format. Can you suggest a method? $("#my_file").change(function(){ //alert if file is not ascii plain text }); <input type="file" name="my_file" id="my_file" /> ...

Issue with Beautiful Soup/Selenium: unable to locate div element or any content within the body

My task involves extracting item names (such as cotton shirt) and their corresponding prices (¥3,600) from within the <div class="items-box-body"> section. <div class="items-box-body"> <h3 class="items-box-name font-2">cotton shirt& ...

The justify-content-between property is failing to align two divs in a row

I have two divs that I want to align, with one on the left and the other on the right (similar to this). I've experimented with self-align-start and self-align-end in each column, but haven't achieved the desired outcome. I also added the class r ...