JSFiddle - React, Tailwind, and code Playground

by Alexandru Gatea

HTML

<div class="grid">
  <div class="grid-item">
    <div class="grid-item-content">
      <div class="grid-item-content-inner">
        <h2 class="grid-item-header">Cluj-Napoca</h2>
        <h3 class="grid-item-subheader">/ Europe</h3>
        <address>
          <span>Bd. 21 Decembrie 1989, No. 77</span>
          <span>Building E, Ground Floor</span>
          <span>400124 Cluj-Napoca, Romania</span>
          <span>Phone +40 (0) 364 730 191</span>
          <span>Fax +40 (0) 364 730 190</span>
        </address>
      </div>
    </div>
  </div>
  <div class="grid-item">
    <div class="grid-item-content">
      <div class="grid-item-content-inner">
        <h2 class="grid-item-header">Cluj-Napoca</h2>
        <h3 class="grid-item-subheader">/ Europe</h3>
        <address>
          <span>Bd. 21 Decembrie 1989, No. 77</span>
          <span>Building E, Ground Floor</span>
          <span>400124 Cluj-Napoca, Romania</span>
          <span>Phone +40 (0) 364 730 191</span>
          <span>Fax +40 (0) 364 730 190</span>
        </address>
      </div>
    </div>
  </div>
  <div class="grid-item">
    <div class="grid-item-content">
      <div class="grid-item-content-inner">
        <h2 class="grid-item-header">Cluj-Napoca</h2>
        <h3 class="grid-item-subheader">/ Europe</h3>
        <address>
          <span>Bd. 21 Decembrie 1989, No. 77</span>
          <span>Building E, Ground Floor</span>
          <span>400124 Cluj-Napoca, Romania</span>
          <span>Phone +40 (0) 364 730 191</span>
          <span>Fax +40 (0) 364 730 190</span>
        </address>
      </div>
    </div>
  </div>
  <div class="grid-item">
    <div class="grid-item-content">
      <div class="grid-item-content-inner">
        <h2 class="grid-item-header">Cluj-Napoca</h2>
        <h3 class="grid-item-subheader">/ Europe</h3>
        <address>
          <span>Bd. 21 Decembrie 1989, No. 77</span>
          <span>Building E, Ground Floor</span>
          <span>400124 Cluj-Napoca,...

SCSS

* {
  box-sizing: border-box;
  font-family: "Segoe UI", sans-serif;
}

$mq: 768px;

.grid {
  padding: 30px;
  grid-gap: 30px;
  display: grid;
  background: #212121;

  @media (min-width: #{$mq}) {
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
   }

  grid-auto-rows: 1fr;
  max-width: 1200px;
  margin: auto;

  &-item-content {
    position: relative;

    &:hover {
      z-index: 1000;
      box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.4);
      cursor: pointer;
    }

    @media (min-width: #{$mq}) {
      position: relative;
      width: 100%;
      height: 0;
      padding-bottom: 100%;
    }

    &-inner {
      background: #424242;
      padding: 30px;
      color: #fff;

      @media (min-width: #{$mq}) {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        justify-content: space-between;
      }
    }
  }

  &-item {
    &-header {
      font-size:1.375rem;

      @media (min-width: 480px) {
        font-size: calc(1.375rem + ((1vw - 4.8px) * 3.6111));
      }

      @media (min-width: 1200px) {
        font-size: 48px;
      }
    }

    &-subheader {
      flex-grow: 1;
      font-size: 1.25rem;

      @media (min-width: 480px) {
        font-size: calc(1.25rem + ((1vw - 4.8px) * 1.6667));
      }

      @media (min-width: 1200px) {
        font-size: 32px;
      }

      @media (max-width: 767px) {
        margin-bottom: 30px;
      }
    }

    address {
      span {
        display: block;
        margin-bottom: 3px;
        opacity: 0.8;
      }
    }
  }
}

JavaScript

var VanillaTilt = function() {
  "use strict";
  class t {
    constructor(e, i = {}) {
      if (!(e instanceof Node)) throw "Can't initialize VanillaTilt because " + e + " is not a Node.";
      this.width = null, this.height = null, this.clientWidth = null, this.clientHeight = null, this.left = null, this.top = null, this.gammazero = null, this.betazero = null, this.lastgammazero = null, this.lastbetazero = null, this.transitionTimeout = null, this.updateCall = null, this.event = null, this.updateBind = this.update.bind(this), this.resetBind = this.reset.bind(this), this.element = e, this.settings = this.extendSettings(i), this.reverse = this.settings.reverse ? -1 : 1, this.glare = t.isSettingTrue(this.settings.glare), this.glarePrerender = t.isSettingTrue(this.settings["glare-prerender"]), this.fullPageListening = t.isSettingTrue(this.settings["full-page-listening"]), this.gyroscope = t.isSettingTrue(this.settings.gyroscope), this.gyroscopeSamples = this.settings.gyroscopeSamples, this.elementListener = this.getElementListener(), this.glare && this.prepareGlare(), this.fullPageListening && this.updateClientSize(), this.addEventListeners(), this.updateInitialPosition()
    }
    static isSettingTrue(t) {
      return "" === t || !0 === t || 1 === t
    }
    getElementListener() {
      if (this.fullPageListening) return window.document;
      if ("string" == typeof this.settings["mouse-event-element"]) {
        const t = document.querySelector(this.settings["mouse-event-element"]);
        if (t) return t
      }
      return this.settings["mouse-event-element"] instanceof Node ? this.settings["mouse-event-element"] : this.element
    }
    addEventListeners() {
      this.onMouseEnterBind = this.onMouseEnter.bind(this), this.onMouseMoveBind = this.onMouseMove.bind(this), this.onMouseLeaveBind = this.onMouseLeave.bind(this), this.onWindowResizeBind = this.onWindowResize.bind(this), this.onDeviceOrientationBind = this.onDeviceOrientation.bind(this),...