Как отфильтровать элементы по клику?

У меня есть контейнер с набором разных элементов. Все элементы отличаются по цветам. Всего три цвета. Каждому элементу присвоено имя стилевого класса (class), которое позволяет связать каждый элемент с нужным для него стилевым оформлением. Элементы в общем контейнере не сгруппированы по цветам, и по факту находятся в нем вразброс. Визуально это выглядит так:

Все элементы

Вот html и css код:

body {overflow: hidden; width: 100%; margin: 0; text-align: center;}

.container {width: 100%; margin: 0 auto;}

.filter {
  float: left; cursor: pointer; width: 23%;
  margin: 0.5%; margin-bottom: 10px; padding: 0.5%;
  background: white; text-align: center; color: black;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.2);
}

.item {
  float: left; width: 23%; height: 20px; line-height: 20px;
  margin: 0.5%; padding: 0.5%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.2);
  transition: all 1s;
}

.blue {background: deepskyblue;}
.red {background: orangered;}
.green {background: limegreen;}
<div class="container">
  <div class="filter">Синий</div>
  <div class="filter">Красный</div>
  <div class="filter">Зеленый</div>
  <div class="filter">Показать все</div>

  <div class="item blue">1</div>
  <div class="item red">2</div>
  <div class="item blue">3</div>
  <div class="item green">4</div>
  <div class="item blue">5</div>
  <div class="item red">6</div>
  <div class="item red">7</div>
  <div class="item green">8</div>
  <div class="item blue">9</div>
  <div class="item green">10</div>
  <div class="item red">11</div>
  <div class="item green">12</div>
  <div class="item blue">13</div>
  <div class="item blue">14</div>
  <div class="item green">15</div>
  <div class="item red">16</div>
</div>

Вопрос: Как при клике на название цвета отфильтровать все элементы таким образом, чтобы показать только элементы выбранного цвета, а все остальные спрятать? Например, при клике на "Красный" должно получится так:

Выбранные элементы

Интересует реализация любыми средствами и технологиями, указанными в метках вопроса. Это может быть: CSS, jQuery, Native Script.


Ответы (4 шт):

Автор решения: Sevastopol'

Вариант CSS:

body {overflow: hidden; width: 100%; margin: 0; text-align: center;}

.container {width: 100%; margin: 0 auto;}

input[type="radio"] {display: none;}
label {
  float: left; cursor: pointer; width: 23%;
  margin: 0.5%; margin-bottom: 10px; padding: 0.5%;
  background: white; text-align: center; color: black;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.2);
}

.blue, #blue:checked+label {background: deepskyblue;}
.red, #red:checked+label {background: orangered;}
.green, #green:checked+label {background: limegreen;}

.item {
  float: left; width: 23%; height: 20px; line-height: 20px;
  margin: 0.5%; padding: 0.5%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.2);
  transition: all 1s;
}

#blue:checked~.item:not(.blue),
#red:checked~.item:not(.red),
#green:checked~.item:not(.green) {
  width: 0; height: 0;
  margin: 0; padding: 0;
  opacity: 0;
}
<div class="container">
  <input type="radio" id="blue" name="color">
  <label for="blue">Синий</label>
  <input type="radio" id="red" name="color">
  <label for="red">Красный</label>
  <input type="radio" id="green" name="color">
  <label for="green">Зеленый</label>
  <input type="radio" id="reset" name="color">
  <label for="reset">Показать все</label>

  <div class="item blue">1</div>
  <div class="item red">2</div>
  <div class="item blue">3</div>
  <div class="item green">4</div>
  <div class="item blue">5</div>
  <div class="item red">6</div>
  <div class="item red">7</div>
  <div class="item green">8</div>
  <div class="item blue">9</div>
  <div class="item green">10</div>
  <div class="item red">11</div>
  <div class="item green">12</div>
  <div class="item blue">13</div>
  <div class="item blue">14</div>
  <div class="item green">15</div>
  <div class="item red">16</div>
</div>

→ Ссылка
Автор решения: Sevastopol'

Вариант jQuery:

$(".f__blue").click(function() {
  $(".f__red").removeClass("red__active");
  $(".f__green").removeClass("green__active");
  $(this).addClass("blue__active");
  $(".blue").removeClass("hide");
  $(".red, .green").addClass("hide");
});
$(".f__red").click(function() {
  $(".f__blue").removeClass("blue__active");
  $(".f__green").removeClass("green__active");
  $(this).addClass("red__active");
  $(".red").removeClass("hide");
  $(".blue, .green").addClass("hide");
});
$(".f__green").click(function() {
  $(".f__blue").removeClass("blue__active");
  $(".f__red").removeClass("red__active");
  $(this).addClass("green__active");
  $(".green").removeClass("hide");
  $(".blue, .red").addClass("hide");
});
$(".reset").click(function() {
  $(".f__blue").removeClass("blue__active");
  $(".f__red").removeClass("red__active");
  $(".f__green").removeClass("green__active");
  $(".blue, .red, .green").removeClass("hide");
});
body {overflow: hidden; width: 100%; margin: 0; text-align: center;}

.container {width: 100%; margin: 0 auto;}

.item {
  float: left; width: 23%; height: 20px; line-height: 20px;
  margin: 0.5%; padding: 0.5%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.2);
  transition: all 1s;
}

.hide {
  width: 0; height: 0;
  margin: 0; padding: 0;
  opacity: 0;
}

.filter {
  float: left; cursor: pointer; width: 23%;
  margin: 0.5%; margin-bottom: 10px; padding: 0.5%;
  background: white; text-align: center; color: black;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.2);
}

.blue, .blue__active {background: deepskyblue;}
.red, .red__active {background: orangered;}
.green, .green__active {background: limegreen;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="container">
  <div class="filter f__blue">Синий</div>
  <div class="filter f__red">Красный</div>
  <div class="filter f__green">Зеленый</div>
  <div class="filter reset">Показать все</div>

  <div class="item blue">1</div>
  <div class="item red">2</div>
  <div class="item blue">3</div>
  <div class="item green">4</div>
  <div class="item blue">5</div>
  <div class="item red">6</div>
  <div class="item red">7</div>
  <div class="item green">8</div>
  <div class="item blue">9</div>
  <div class="item green">10</div>
  <div class="item red">11</div>
  <div class="item green">12</div>
  <div class="item blue">13</div>
  <div class="item blue">14</div>
  <div class="item green">15</div>
  <div class="item red">16</div>
</div>

→ Ссылка
Автор решения: Sevastopol'

Вариант JavaScript:

const fb = document.querySelector('.f__blue');
const fr = document.querySelector('.f__red');
const fg = document.querySelector('.f__green');
const reset = document.querySelector('.reset');
const all = document.querySelectorAll('.item');
const blue = document.querySelectorAll('.blue');
const red = document.querySelectorAll('.red');
const green = document.querySelectorAll('.green');

fb.onclick = function(){
  fr.classList.remove("red__active");
  fg.classList.remove("green__active");
  this.classList.add("blue__active");
  for(var i = 0; i < all.length; i++){
  all[i].classList.add("hide");
  }
  for(var i = 0; i < blue.length; i++){
  blue[i].classList.remove("hide");
  }
}

fr.onclick = function(){
  fb.classList.remove("blue__active");
  fg.classList.remove("green__active");
  this.classList.add("red__active");
  for(var i = 0; i < all.length; i++){
  all[i].classList.add("hide");
  }
  for(var i = 0; i < red.length; i++){
  red[i].classList.remove("hide");
  }
}

fg.onclick = function(){
  fb.classList.remove("blue__active");
  fr.classList.remove("red__active");
  this.classList.add("green__active");
  for(var i = 0; i < all.length; i++){
  all[i].classList.add("hide");
  }
  for(var i = 0; i < green.length; i++){
  green[i].classList.remove("hide");
  }
}

reset.onclick = function(){
  fb.classList.remove("blue__active");
  fr.classList.remove("red__active");
  fg.classList.remove("green__active");
  for(var i = 0; i < all.length; i++){
  all[i].classList.remove("hide");
  }
}
body {overflow: hidden; width: 100%; margin: 0; text-align: center;}

.container {width: 100%; margin: 0 auto;}

.item {
  float: left; width: 23%; height: 20px; line-height: 20px;
  margin: 0.5%; padding: 0.5%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.2);
  transition: all 1s;
}

.hide {
  width: 0; height: 0;
  margin: 0; padding: 0;
  opacity: 0;
}

.filter {
  float: left; cursor: pointer; width: 23%;
  margin: 0.5%; margin-bottom: 10px; padding: 0.5%;
  background: white; text-align: center; color: black;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.2);
}

.blue, .blue__active {background: deepskyblue;}
.red, .red__active {background: orangered;}
.green, .green__active {background: limegreen;}
<div class="container">
  <div class="filter f__blue">Синий</div>
  <div class="filter f__red">Красный</div>
  <div class="filter f__green">Зеленый</div>
  <div class="filter reset">Показать все</div>

  <div class="item blue">1</div>
  <div class="item red">2</div>
  <div class="item blue">3</div>
  <div class="item green">4</div>
  <div class="item blue">5</div>
  <div class="item red">6</div>
  <div class="item red">7</div>
  <div class="item green">8</div>
  <div class="item blue">9</div>
  <div class="item green">10</div>
  <div class="item red">11</div>
  <div class="item green">12</div>
  <div class="item blue">13</div>
  <div class="item blue">14</div>
  <div class="item green">15</div>
  <div class="item red">16</div>
</div>

→ Ссылка
Автор решения: Alexander Lonberg

Варианты с JS, лучше делать более универсальными - не зависящими от кол-ва цветов.

const btsFilter = Array.from(document.querySelectorAll('[data-filter]'))

const colors = ['blue', 'green', 'red' /*, .... */]
const map = colors.reduce((a, e) => {
  const bt = btsFilter.find((btel) => btel.dataset.filter === e)
  const els = Array.from(document.querySelectorAll(`.item.${e}`))
  let hide = false
  a.set(e, (fl, reset) => {
    if (fl) {
      reset || bt.classList.add('selected')
      if (!hide) return
      hide = false
      els.forEach((e) => e.classList.remove('hide'))
    } else {
      bt.classList.remove('selected')
      if (hide) return
      hide = true
      els.forEach((e) => e.classList.add('hide'))
    }
  })
  return a
}, new Map())
map.set('reset', (fl) => fl && colors.forEach((e) => map.get(e)(fl, true)))

btsFilter.forEach((i) => i.addEventListener('click', ({ target: { dataset: { filter } } }) => {
  for (let [key, show] of map.entries()) {
    show(filter === key)
  }
}))
body {
  overflow: hidden;
  width: 100%;
  margin: 0;
  text-align: center;
}

.container {
  width: 100%;
  margin: 0 auto;
}

.item {
  float: left;
  width: 23%;
  height: 20px;
  line-height: 20px;
  margin: 0.5%;
  padding: 0.5%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.2);
  transition: all 1s;
}

.hide {
  width: 0;
  height: 0;
  margin: 0;
  padding: 0;
  opacity: 0;
}

.filter {
  float: left;
  cursor: pointer;
  width: 23%;
  margin: 0.5%;
  margin-bottom: 10px;
  padding: 0.5%;
  background: white;
  text-align: center;
  color: black;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.2);
}

.blue,
.filter.selected[data-filter="blue"] {
  background: deepskyblue;
}

.red,
.filter.selected[data-filter="red"] {
  background: orangered;
}

.green,
.filter.selected[data-filter="green"] {
  background: limegreen;
}
<div class="filter" data-filter="blue">Синий</div>
<div class="filter" data-filter="red">Красный</div>
<div class="filter" data-filter="green">Зеленый</div>
<div class="filter" data-filter="reset">Показать все</div>

<div class="item blue">1</div>
<div class="item red">2</div>
<div class="item blue">3</div>
<div class="item green">4</div>
<div class="item blue">5</div>
<div class="item red">6</div>
<div class="item red">7</div>
<div class="item green">8</div>
<div class="item blue">9</div>
<div class="item green">10</div>
<div class="item red">11</div>
<div class="item green">12</div>
<div class="item blue">13</div>
<div class="item blue">14</div>
<div class="item green">15</div>
<div class="item red">16</div>

→ Ссылка