Andre M
Andre M

Reputation: 7546

Force wrapping an inline-block with CSS, after 'n' elements?

I am trying to display a list of divs as a grid, using purely CSS, but I can't get it to behave properly. I had looked at white-space: wrap, but that is meant to be applied to the parent element, so that isn't useable. I also tried clear, but no luck either. Can anyone suggest an approach, that would work for any value of elements per row. The code below is intended to be three elements per line.

The reason I want this in CSS, is that code that this is part of is intended to allow the user to display the entries horizontally, vertically or as a grid (of n elements wide). The value of 'n', for the elements per row of the grid is based on a configurable value.

Intended display, for the grid view (where n=3):

Entry 1 | Entry 2 | Entry 3
--------+---------+--------
Entry 4 | Entry 5 | Entry 6
--------+---------+--------
Entry 7 | Entry 8 | Entry 9

#results.grid {
  padding-top: 40px;
}
#results.grid .entry {
  display: inline-block;
}
#results.grid .entry:nth-child(3n+1) {
  background-color: yellow;
  display: block;
}
<div id="results" class="results grid">

  <div class="entry">Entry 1</div>
  <div class="entry">Entry 2</div>
  <div class="entry">Entry 3</div>

  <div class="entry">Entry 4</div>
  <div class="entry">Entry 5</div>
  <div class="entry">Entry 6</div>

  <div class="entry">Entry 7</div>
  <div class="entry">Entry 8</div>
  <div class="entry">Entry 9</div>
</div>

As a JSFiddle: https://jsfiddle.net/rn05gns1/

Upvotes: 2

Views: 1612

Answers (2)

Marc Audet
Marc Audet

Reputation: 46795

Here is one way that might work depending on your layout and other factors such as responsiveness.

Instead of inline-blocks, float your .entry elements to the left and apply overflow: auto to the parent container to contain the floated elements. This prevents the floated .entry elements from interacting with other elements outside of #results.

The trick is to clear the floats every n-th element. To do this, define one or more classes like .n3, .n4 and so on, and use the nth-child selected to apply the clear:left property to the first element of the row.

Any extra elements will simply give you a partially filled row.

As long at the page is wide enough, your rows will work as expected. On smaller screens, the elements will wrap. How you want to deal with this remains to be specified depending on your layout.

.entry {
  width: 100px;
  height: 75px;
  border: solid 1px black;
  margin: 5px;
}
#results.grid {
  border: 1px dotted gray;
  overflow: auto;
}
#results.grid .entry {
  float: left;
}
#results.grid.n3 .entry:nth-child(3n+1) {
  background-color: yellow;
  clear: left;
}
#results.grid.n4 .entry:nth-child(4n+1) {
  background-color: green;
  clear: left;
}
<h3>Exampel 1: n=3</h3>
<div id="results" class="results grid n3">

  <div class="entry">Entry 1</div>
  <div class="entry">Entry 2</div>
  <div class="entry">Entry 3</div>

  <div class="entry">Entry 4</div>
  <div class="entry">Entry 5</div>
  <div class="entry">Entry 6</div>

  <div class="entry">Entry 7</div>
  <div class="entry">Entry 8</div>
  <div class="entry">Entry 9</div>
</div>

<h3>Exampel 2: n=4</h3>
<div id="results" class="results grid n4">

  <div class="entry">Entry 1</div>
  <div class="entry">Entry 2</div>
  <div class="entry">Entry 3</div>

  <div class="entry">Entry 4</div>
  <div class="entry">Entry 5</div>
  <div class="entry">Entry 6</div>

  <div class="entry">Entry 7</div>
  <div class="entry">Entry 8</div>
  <div class="entry">Entry 9</div>
</div>

Upvotes: 1

dNitro
dNitro

Reputation: 5355

Instead of inline block use floats:

#results.grid .entry {
   float: left;
}

#results.grid .entry:nth-child(3n+1){
   background-color: yellow;
   clear: left;
}

$(document).ready(function() {
  $('#mode').change(function() {
    $('#results').removeClass();
    $('#results').addClass($(this).val());
  })
})
#controls {
  position: fixed;
  z-index: 4;
  background-color: white;
  width: 100%;
  padding: 4px
}
.entry {
  width: 200px;
  height: 150px;
  border: solid 1px black;
  margin: 5px;
}
#results.horizontal {
  overflow-x: scroll;
  overflow-y: hidden;
  width: 100%;
  white-space: nowrap;
  padding-top: 40px;
}
#results.horizontal .entry {
  display: inline-block;
}
#results.vertical {
  position: absolute;
  top: 40px;
  bottom: 0;
  overflow-y: scroll;
  overflow-x: hidden;
}
#results.grid .entry.vertical {
  display: block;
}
#results.grid {
  padding-top: 40px;
}
#results.grid .entry {
  float: left;
}
#results.grid .entry:nth-child(3n+1) {
  clear: left;
  background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="results" class="results grid">

  <div class="entry">Entry 1</div>
  <div class="entry">Entry 2</div>
  <div class="entry">Entry 3</div>

  <div class="entry">Entry 4</div>
  <div class="entry">Entry 5</div>
  <div class="entry">Entry 6</div>

  <div class="entry">Entry 7</div>
  <div class="entry">Entry 8</div>
  <div class="entry">Entry 9</div>
</div>

Upvotes: 3

Related Questions