Is it possible to horizontally center an auto-fill grid using only CSS?

I would like to fill my page horizontally with as many blocks as possible and center the result.

My goal is to have a grid that can resize when the window size changes:

wide window
xxx

small window
xx
x

Is it possible to achieve this without using JavaScript?

.box {
      box-sizing: border-box;
  
      width: 200px;
      height: 150px;
  
      background-color: white;
      border: solid 6px red;
    }

    .box:nth-child(2) {
      background-color: blue
    }

    .grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, 200px);
    }
<div class="center">
      <div class="grid">
        <div class="box"></div>
        <div class="box"></div>
        <div class="box"></div>
      </div>
    </div>

To visually explain the desired centering effect:

Can the yellow highlighted area be evenly distributed on either side? https://i.sstatic.net/T4NZw.png


The desired alignment of boxes: https://i.sstatic.net/gTRwP.png

Answer №1

Issue Specific to Chrome Browser


For the auto-fit and auto-fill functionalities to work properly, a known width is necessary for calculation. This can be achieved by using max-width:100% instead of width to ensure proper centering without stretching or fixed widths.

.box {
  box-sizing: border-box;
  width: 200px;
  height: 150px;
  background-color: white;
  border: solid 6px red;
}

.box:nth-child(2) {
  background-color: blue
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, 200px);
  max-width: 100%;
}

.center {
  display: flex;
  flex-direction: column;
  align-items: center;
}
<div class="center">
  <div class="grid">
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
  </div>
</div>


Note that if the initial viewport is wide and then resized smaller, the grid may not remain centered due to issues with auto-fill.

In cases where there are fewer elements than the container can fit columns due to auto-fill, uneven spacing may occur. Using auto-fit ensures even distribution when an element is missing.

.box {
  box-sizing: border-box;
  width: 200px;
  height: 150px;
  background-color: white;
  border: solid 6px red;
}

.box:nth-child(2) {
  background-color: blue
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, 200px);
  max-width: 100%;
}

.center {
  display: flex;
  flex-direction: column;
  align-items: center;
}
<div class="center">
  <div class="grid">
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
  </div>
</div>


To address spacing inconsistencies upon resizing due to relative units in max-width calculations, triggering a recalculation through animation can solve this issue.

Solution Specifically for Chrome Browser

.center {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.box {
  box-sizing: border-box;
  width: 200px;
  height: 150px;
  background-color: white;
  border: solid 6px red;
}

.box:nth-child(2) {
  background-color: blue
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, 200px);
  max-width: 100%;
  animation: recalc 5s linear infinite;
}

@keyframes recalc {
  to {
    max-width: 99.9%;
  }
}
<div class="center">
  <div class="grid">
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
  </div>
</div>


To ensure compatibility with Firefox and other browsers, consider using viewport units for defining widths.

.box {
  box-sizing: border-box;
  width: 200px;
  height: 150px;
  background-color: white;
  border: solid 6px red;
}

.box:nth-child(2) {
  background-color: blue
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, 200px);
  max-width: 100vw;
  margin:0 auto;
}

.center {
  display: flex;
}
<div class="center">
  <div class="grid">
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
  </div>
</div>

Answer №2

Utilize flexbox for this solution.

.box {
  box-sizing: border-box;
  
  width: 200px;
  height: 150px;
  
  background-color: white;
  border: solid 6px red;
}

.box:nth-child(2) {
  background-color: blue
}

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

@media screen and (max-width: 767px) {
 .grid {
   flex-wrap: wrap;
   justify-content: center;
 }
 .box {
  width: 50%
 }
}
<div class="center">
  <div class="grid">
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
  </div>
</div>

Answer №3

Achieving center alignment for an auto-fill grid with left-aligned items is possible, even in Firefox.

To achieve this, simply add justify-content: center; to the grid container, resulting in the following code:

https://i.sstatic.net/Igz3A.png

An illustrative example and explanation can be found on the MDN documentation page for justify-content

Your implementation would resemble the following:

.box {
  box-sizing: border-box;
  width: 200px;
  height: 150px;
  background-color: white;
  border: solid 6px red;
}

.box:nth-child(2) {
  background-color: blue
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, 200px);
  justify-content: center; /* <-- This is all you need to add */
}
<div class="center">
  <div class="grid">
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
  </div>
</div>

It's important to note that when there is only one row of boxes, they may not be perfectly centered, as the repeat function generates empty columns to fill the row, resulting in a slight left alignment of the actual boxes:

https://i.sstatic.net/tHm4M.png

Answer №4

I suggest utilizing flex instead of grid in this scenario:

*{
  box-sizing:border-box; padding:0; margin:0; font-size:0;
}
html,body{
  width:100%; height:100%; background:#ccc;
}
.box{  
  width:200px; height:150px; background-color:white; border:6px solid red;
}
.box:nth-child(2n+2) {
  background-color:blue;
}
.center,.grid{
  display:flex; align-items:center; justify-content:center; height:100%;
}
.grid{
  min-width:600px; flex-wrap:wrap; align-items:center;
}
<div class='center'>
  <div class='grid'>
    <div class='box'></div>
    <div class='box'></div>
    <div class='box'></div>
    <div class='box'></div>
    <div class='box'></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

Setting session expiration for an HTML page in MVC with JavaScript - A step-by-step guide

I'm working on a HTML page within an MVC framework that includes a button click function. I'm trying to figure out how to redirect the user to the login page if the page remains idle for 30 minutes. I've attempted using the code snippet belo ...

Receiving a blank array from the firestore database

I have written a code for the LeftBar Component where I am trying to retrieve data stored in the "contacts" document in Firebase. However, I am getting an empty array and I'm not sure why this is happening. Additionally, I would like to know how to ac ...

Using VueJS to dynamically manipulate URL parameters with v-model

Hello, I am new to coding. I am working on calling an API where I need to adjust parts of the querystring for different results. To explain briefly: <template> <div> <input type="text" v-model="param" /> ...

vue.js libs requiring "new ..." are being scolded by eslint for their misspelling

When working with Vue libraries, such as Swiper, that require the use of 'new …' in the script section, I encounter ESlint errors no matter how I try to write it. Even though 'new ...' works perfectly fine in the frontend, ESlint cont ...

Skip nodes in Polymer 1.0 by using ExcludeLocalNames

I recently attempted to transition from Polymer version 0.5 to 1.0 and came across a particular question: Is there a way to exclude certain nodes inside a paper-menu? In the previous version (0.5), you could use the attribute excludedLocalNames to achieve ...

Make the textarea larger and bring it to the forefront when it is selected

I would like to make a textarea expand (increase its height) when it is in focus. The expanded textarea should not push the content down, but rather be displayed above other content. Currently, this is the code I am using (check out the example here): $( ...

Manipulating arrays in JavaScript through HTML processing

I'm encountering an issue while trying to send an array to a JavaScript function. Here's what I have so far: Within the controller: @data = [{date: '2014-08-17'}, {date: '2014-08-20'}].to_json In the view: <%= content_t ...

Nodemailer fails to display an error message when the email is not successfully sent

I am currently working on implementing nodemailer for sending emails. However, I noticed that if the email address in the "to" field is incorrect, the email is not sent as expected. The issue is that there is no error displayed and the function still resol ...

What is preventing me from being able to manipulate the data retrieved from this ajax request?

I've been attempting to make an ajax call to my json server on localhost:3000 in order to retrieve an object that I can manipulate and display on a webpage. However, no matter what I try, I just can't seem to console log the (data) so that I can ...

CSS: Turn off the custom styling for radio buttons

My dilemma lies in the custom radio button I've created using CSS. The issue is that while I can select the radio button, I cannot deselect it. Here is a snippet of the CSS code I used to create the custom radio button: input[type="radio"]:checked:be ...

Leveraging a JSON file as a data repository for chart.js

I am struggling to incorporate JSON values into a bar chart. I have successfully logged the JSON data in the console, but I'm unsure how to include it in the data property for the chart. Below is the source JSON... {time: "2016-07-03T21:29:57.987Z" ...

Enhance the database with partial updates using the patch method in Django Rest Framework

I have a model called CustomUser that extends the AbstractUser class. class CustomUser(AbstractUser): detail = models.JSONField(default=dict) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=Tr ...

Tips for concealing a div when the mouse is moved off it?

My goal is to create a simple hover effect where hovering over an image within a view filled with images displays an additional div. This part works as expected. However, I'm facing issues when trying to hide the same div when the user moves out of t ...

Tips for configuring CakePHP to trigger the second submit button when the enter key is pressed

My form includes two submit buttons: "cancel" and "find." While both buttons work correctly when clicked, pressing the enter key always triggers the submission of "cancel." I don't want to change the button order in the form. To address this issue, I ...

Exploring ReactJS: Utilizing the useEffect Hook for Retrieving Various Data Sources

I have recently started working with react and currently have a function that fetches data in my useEffect hook. I am using a loading state to handle component rendering, and then populating my state component with the fetched data successfully. However, ...

Rotate object within HTML table

I have a simple data structure as shown below: [ { "ClientId": 512, "ProductId": 7779, "Date": "2019-01-01", "Quantity": 20.5, "Value": 10.5 }, { "ClientId": 512, "ProductId": ...

How can you ensure that it selects a random number to retrieve items from an array?

I am experiencing an issue with some code I wrote. Instead of displaying a random object from the array as intended, it is showing the random number used to try and display an object. <html> <body> <h1>HTML random objects< ...

What could be causing my select value to stay unchanged? Issue with the "selected" attribute or property

var original_role = $('option:selected', '#user_role').val(); $('#role_cancel').click(function() { //console.log(original_role); $('option:selected', '#user_role').removeAttr('selected'); //des ...

Assign tags using a variable within a loop

Consider the scenario where I need to generate a list of li elements: {map(listItems, (obj,i) => <li key={i}> <a target="_blank" href={obj.itemName === 'view_detail' ? `event/${id}` : ''} > <i c ...

Using React JS to iterate over an array and generate a new div for every 3 items

It's a bit challenging for me to articulate my goal effectively. I have a JSON payload that looks like this: { "user": { "id": 4, "username": "3nematix2", "profile_pic": &qu ...