JSFiddle - React, Tailwind, and code Playground

by AldoRomo88

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/masonry/4.2.0/masonry.pkgd.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">

  <button @click="add">
    Add
  </button>

  <div class="grid">
    <div v-for="item in items" @click="toggle(item)" class="grid-item" :class="[{'grid-item--gigante':item.isGigante}, item.size]"></div>

  </div>

</div>

CSS

* {
  box-sizing: border-box;
}

body {
  font-family: sans-serif;
}


/* ---- grid ---- */

.grid {
  background: #EEE;
  max-width: 1200px;
}


/* clearfix */

.grid:after {
  content: '';
  display: block;
  clear: both;
}


/* ---- grid-item ---- */

.grid-item {
  width: 50px;
  height: 50px;
  float: left;
  background: #D26;
  border: 2px solid #333;
  border-color: hsla(0, 0%, 0%, 0.5);
  border-radius: 5px;
}

.grid-item--width2 {
  width: 100px;
}

.grid-item--width3 {
  width: 150px;
}

.grid-item--width4 {
  width: 200px;
}

.grid-item--height2 {
  height: 75px;
}

.grid-item--height3 {
  height: 100px;
}

.grid-item--height4 {
  height: 150px;
}

.grid-item--gigante {
  width: 250px;
  height: 250px;
  z-index: 2;
  /* above other items */
}

.grid-item:hover {
  background: #A2C;
  border-color: white;
  cursor: pointer;
}

JavaScript

let widthClasses = ['', 'grid-item--width2', 'grid-item--width3', 'grid-item--width4'];
let heightClasses = ['', 'grid-item--height2', 'grid-item--height3', 'grid-item--height4'];
let data = [];

for (let x = 0; x < 10; x++) {
  data.push({
    isGigante: false,
    size: '' + widthClasses[Math.floor(Math.random() * widthClasses.length)] + ' ' + heightClasses[Math.floor(Math.random() * heightClasses.length)]
  })
}



new Vue({
  el: '#app',
  data: function() {
    return {
      items: data,
      msnry: null,
    }
  },
  mounted() {
    let grid = document.querySelector('.grid');
    this.msnry = new Masonry(grid, {
      columnWidth: 25
    });
  },
  methods: {
    toggle(item) {
      item.isGigante = !item.isGigante;
      Vue.nextTick(() => {
        // DOM updated
        this.msnry.layout();
      });
    },
    add() {
      this.items.push({
        isGigante: false,
        size: '' + widthClasses[Math.floor(Math.random() * widthClasses.length)] + ' ' + heightClasses[Math.floor(Math.random() * heightClasses.length)]
      });
      Vue.nextTick(() => {
        // DOM updated
        this.msnry.reloadItems();
        this.msnry.layout();
      });
    }
  }
})