JSFiddle - React, Tailwind, and code Playground

by Yunus Gaziev

HTML

<div class="view-ctrl">
  <button type="button" data-view="column">Column</button>
  <button type="button" data-view="list">List</button>
</div>
<br>
<div class="view-radio-ctrl">
  <label>
    Column
    <input type="radio" name="viewType" value="column">
  </label>
  <label>
    List
    <input type="radio" name="viewType" value="list">
  </label>
</div>
<br>
<ul class="products-view" data-view="column">
  <li>
    <div class="prod-shinnet">
      <div class="prod-shinnet__img-wrap">
        <img src="https://picsum.photos/320/180/?random">
      </div>
      <div class="prod-shinnet__meta">
        <div class="prod-shinnet__title">Product #1</div>
        <div class="prod-shinnet__descr">
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Maiores, error.</p>
        </div>
        <div class="prod-shinnet__action">
          <button type="button">Buy</button>
        </div>
      </div>
    </div>
  </li>
  <li>
    <div class="prod-shinnet">
      <div class="prod-shinnet__img-wrap">
        <img src="https://picsum.photos/320/180/?random">
      </div>
      <div class="prod-shinnet__meta">
        <div class="prod-shinnet__title">Product #1</div>
        <div class="prod-shinnet__descr">
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Maiores, error.</p>
        </div>
        <div class="prod-shinnet__action">
          <button type="button">Buy</button>
        </div>
      </div>
    </div>
  </li>
  <li>
    <div class="prod-shinnet">
      <div class="prod-shinnet__img-wrap">
        <img src="https://picsum.photos/320/180/?random">
      </div>
      <div class="prod-shinnet__meta">
        <div class="prod-shinnet__title">Product #1</div>
        <div class="prod-shinnet__descr">
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Maiores, error.</p>
        </div>
        <div class="prod-shinnet__action">
          <button type="button">Buy</button>
        </div>
      </div>
   ...

CSS

* {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

body {
  padding: 15px;
  font-family: sans-serif;
}

.products-view {
  display: flex;
  flex-wrap: wrap;
  margin: 0 0 0 -15px;
  padding: 0;
  width: 100%;
}

.products-view li {
  flex: 0 0 33.33%;
  max-width: 33.33%;
  padding: 0 0 15px 15px;
}

.prod-shinnet__img-wrap {
  margin-bottom: 15px;
}

.prod-shinnet img {
  width: 100%;
  height: auto;
  vertical-align: top;
}

.prod-shinnet__title {
  font-size: 18px;
  margin-bottom: 10px;
}

.prod-shinnet__descr {
  font-size: 14px;
  margin-bottom: 15px;
}

.products-view[data-view="list"] {
  display: block;
}

.products-view[data-view="list"] li {
  max-width: 100%;
}

[data-view="list"] .prod-shinnet {
  display: flex;
  align-items: center;
}

[data-view="list"] .prod-shinnet__img-wrap {
  flex: 0 0 254px;
  max-width: 254px;
  margin-right: 15px;
  margin-bottom: 0;
}

[data-view="list"] .prod-shinnet__meta {
  flex: 1;
  max-width: 100%;
}

JavaScript

function chageProductsView($view, type) {
	$view.attr('data-view', type);
  localStorage.setItem('gridView', type);
}


const $productsView = $('.products-view');

$('[data-view]').on('click', function(event) {
	event.preventDefault();
  chageProductsView($productsView, $(this).data('view'));
});


const $radioViewCtrl = $('[name="viewType"]');

$radioViewCtrl.on('change', function() {
	chageProductsView($productsView, $radioViewCtrl.filter(':checked').val());
});


chageProductsView($productsView, localStorage.getItem('gridView') || 'column');