Search code examples
csscss-grid

How to restrict width of grid container if there are few items but stretch to fill parent if there are many?


I have a button that adds items to the grid when pressed, it looks like this at the moment:

enter image description here

As you can see, the grid container is stretched full width...but I want it to be the same width as the button and to only get stretched as more items get added, like so:

enter image description here

is this possible with CSS grid?

document.querySelector('#add').addEventListener('click', function() {
	document.querySelector('.grid').insertAdjacentHTML('afterbegin', '<div class="item"></div>');
});
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  grid-gap: 20px;
  
  background: #777;
  padding: 20px;
}

.item {
  height: 100px;
  background: white;
}

#add {
  width: 100px;
  height: 100px;
  
  background: #333;
  color: white;
  font-size: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  border-radius: 50%;
  
}
<div class="grid">
  <div id="add">+</div>
</div>


Solution

  • You can approximate this using flexbox:

    document.querySelector('#add').addEventListener('click', function() {
    	document.querySelector('.grid').insertAdjacentHTML('afterbegin', '<div class="item"></div>');
    });
    .grid {
      display: flex;
      flex-wrap:wrap;
      max-width:max-content; /* This will limit the container */
      
      align-items: center;
      background: #777;
      padding:10px;
    }
    /* This is a hack to limit the grow effect*/
    .grid:after {
      content:"";
      flex-grow:999;
    }
    /**/
    .item {
      height: 100px;
      background: white;
      flex-grow:1;
      width:100px;
      margin:10px;
    }
    
    #add {
      width: 100px;
      height: 100px;
      
      background: #333;
      color: white;
      font-size: 40px;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      border-radius: 50%;
      
    }
    <div class="grid">
      <div id="add">+</div>
    </div>

    Or you consider some JS since you are already using JS:

    var i=1;
    document.querySelector('#add').addEventListener('click', function() {
      document.querySelector('.grid').insertAdjacentHTML('afterbegin', '<div class="item"></div>');
      i++;
      document.querySelector('.grid').style.maxWidth=(i*100 + (i-1)*20)+'px';
    });
    .grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
      grid-gap: 20px;
      background: #777;
      padding: 20px;
      max-width:100px;
    }
    
    .item {
      height: 100px;
      background: white;
    }
    
    #add {
      width: 100px;
      height: 100px;
      background: #333;
      color: white;
      font-size: 40px;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      border-radius: 50%;
    }
    <div class="grid">
      <div id="add">+</div>
    </div>