Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <h1>
  Implementing Masonry layout with just display grid
</h1>
<p>
  It is possible to implement a masonry layout with existing grid layout as long as one constraint is satisfied.
</p>
<p>
  <strong>
    We need to know the height of each element in the layout in advance.
  </strong>
</p>
<p>
  In practice this means that either the heights of the cards are static regardless of the width of the cards. OR. the width of the columns is static and so the height of the cards is static and known ahead of time as well.
</p>
<p>
  Pinterest meets both these requirements. They have an adaptive number of columns, but the width of the columns is fixed. Also, they must
  know the dimensions of the images they render ahead of time.
</p>
<p>
  The idea is simply that the rows in the grid are defined to be an arbitrary height using "grid-auto-rows". In this example, I chose 10px, which means that every card can have a height which is a multiple of 20px, but it is possible to use any level accuracy needed. We could use 1px instead of 20.
</p>
<p>
  Next, when setting the height of the cards, we also set "grid-row: span (number)" where the number is chosen based on the height of the card PLUS whatever margin you need below the card. Gap would be applied between all rows and would mess up the math, so it is important to keep row-gap to 0. Finally, some negative margin at the bottom fixes up the gaps.
</p>
<p>
  The result is an adaptive masonry layout that automatically fills gaps and rearranges as needed. The cards are not rearranged too much are generally in left-to-right and top-to-bottom order.
</p>




<div class="grid">
  <div class="item" style="--s: 17">1</div>
  <div class="item" style="--s: 12">2</div>
  <div class="item" style="--s: 6">3</div>
  <div class="item" style="--s: 18">4</div>
  <div class="item" style="--s: 8">5</div>
  <div class="item" style="--s: 12">6</div>
  <div class="item" style="--s: 24">7</div>
  <div class="item" style="--s: 4">8</div>
  <div class="item" style="--s: 8">9</div>
  <div class="item" style="--s: 8">10</div>
  <div class="item" style="--s: 7">11</div>
  <div class="item" style="--s: 17">12</div>
  <div class="item" style="--s: 5">13</div>
  <div class="item" style="--s: 6">14</div>
  <div class="item" style="--s: 13">15</div>
  <div class="item" style="--s: 12">16</div>
  <div class="item" style="--s: 12">17</div>
  <div class="item" style="--s: 6">18</div>
  <div class="item" style="--s: 22">19</div>
  <div class="item" style="--s: 20">20</div>
  <div class="item" style="--s: 15">21</div>
  <div class="item" style="--s: 24">22</div>
  <div class="item" style="--s: 15">23</div>
  <div class="item" style="--s: 17">24</div>
  <div class="item" style="--s: 10">25</div>
  <div class="item" style="--s: 13">26</div>
  <div class="item" style="--s: 16">27</div>
  <div class="item" style="--s: 9">28</div>
  <div class="item" style="--s: 4">29</div>
  <div class="item" style="--s: 10">30</div>
  <div class="item" style="--s: 23">31</div>
  <div class="item" style="--s: 13">32</div>
  <div class="item" style="--s: 4">33</div>
  <div class="item" style="--s: 15">34</div>
  <div class="item" style="--s: 8">35</div>
  <div class="item" style="--s: 14">36</div>
  <div class="item" style="--s: 17">37</div>
  <div class="item" style="--s: 24">38</div>
  <div class="item" style="--s: 6">39</div>
  <div class="item" style="--s: 9">40</div>
  <div class="item" style="--s: 5">41</div>
  <div class="item" style="--s: 6">42</div>
  <div class="item" style="--s: 17">43</div>
  <div class="item" style="--s: 4">44</div>
  <div class="item" style="--s: 12">45</div>
  <div class="item" style="--s: 6">46</div>
  <div class="item" style="--s: 10">47</div>
  <div class="item" style="--s: 7">48</div>
</div>
              
            
!

CSS

              
                .grid {
  display: grid;
  /*
    NOTE: This example uses a granularity of 20px.
    i.e. each card can only be a multiple 20px tall.
    However, we can increase the granularily by decreasing this value
    to as low as 1px.
    I assume, using 20x the grid rows of 1px height each would
    create some performance issues, and so I think it's best to
    choose the largest number you can get away with.
  */
  grid-auto-rows: 20px;
  grid-template-columns: repeat(auto-fill, 160px);
  /*
    NOTE: although row-gap is not usable, column-gap is.
  */
  column-gap: 20px;
  justify-content: center;
  margin-bottom: -20px;
  margin-top: 100px;
}

.item {
  background-color: red;
  width: 100%;
  height: calc(var(--s) * 20px);
  /* 
    NOTE: Notice the +1
    That leaves 1 row (i.e. 20px) of extra space below each card.
    (The height is --s rows tall, but it takes up --s + 1 rows of space)
      
    This is used instead of `row-gap` as having row gaps would
    mess up the `span` math.
  */
  grid-row: span calc(var(--s) + 1);
  border-radius: 8px;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: system-ui;
  font-size: 2rem;
  /* Just some random colors for the cards */
  &:nth-child(12n + 1) { background-color: red; }
  &:nth-child(12n + 2) { background-color: hotpink; }
  &:nth-child(12n + 3) { background-color: rebeccapurple; }
  &:nth-child(12n + 4) { background-color: orange; }
  &:nth-child(12n + 5) { background-color: green; }
  &:nth-child(12n + 6) { background-color: lime; color: black; }
  &:nth-child(12n + 7) { background-color: aqua; color: black; }
  &:nth-child(12n + 8) { background-color: yellow; color: black; }
  &:nth-child(12n + 9) { background-color: grey; }
  &:nth-child(12n + 10) { background-color: black; }
  &:nth-child(12n + 11) { background-color: blue; }
  &:nth-child(12n + 12) { background-color: brown; }
}

h1, p {
  font-family: system-ui;
  max-width: 60rem;
  padding-inline: 2rem;
  margin-inline: auto;
}
              
            
!

JS

              
                
              
            
!
999px

Console