HMTL
<section class="gallery">
<div class="container">
<input type="radio" id="All" name="categories" value="All" checked>
<input type="radio" id="cat-a" name="categories" value="cat-a">
<input type="radio" id="cat-b" name="categories" value="cat-b">
<input type="radio" id="cat-c" name="categories" value="cat-c">
<input type="radio" id="cat-d" name="categories" value="cat-d">
<input type="radio" id="cat-e" name="categories" value="cat-e">
<input type="radio" id="cat-f" name="categories" value="cat-f">
<ol class="filters">
<li><label for="All">All</label></li>
<li><label for="cat-a">カテゴリA</label></li>
<li><label for="cat-b">カテゴリB</label></li>
<li><label for="cat-c">カテゴリC</label></li>
<li><label for="cat-d">カテゴリD</label></li>
<li><label for="cat-e">カテゴリE</label></li>
<li><label for="cat-f">カテゴリF</label></li>
</ol>
<ol class="targets">
<li class="target" data-category="cat-a cat-b">
<figure> <a href="#"> <img src="images/001.jpg" alt=""> </a>
<h2 class="target-title"> <a href="#">Title 1</a> </h2>
<ol class="target-categories">
<li> <a href="#">カテゴリA</a> </li>
<li> <a href="#">カテゴリB</a> </li>
</ol>
<figcaption>キャプション1</figcaption>
</figure>
</li>
<li class="target" data-category="cat-a cat-c">
<figure> <a href="#"> <img src="images/002.jpg" alt=""> </a>
<h2 class="target-title"> <a href="#">Title 2</a> </h2>
<ol class="target-categories">
<li> <a href="#">カテゴリA</a> </li>
<li> <a href="#">カテゴリC</a> </li>
</ol>
<figcaption>キャプション2</figcaption>
</figure>
</li>
・・・中略・・・
<li class="target" data-category="cat-e cat-a">
<figure> <a href="#"> <img src="images/012.jpg" alt=""> </a>
<h2 class="target-title"> <a href="#">Title 12</a> </h2>
<ol class="target-categories">
<li> <a href="#">カテゴリE</a> </li>
<li> <a href="#">カテゴリA</a> </li>
</ol>
<figcaption>キャプション12</figcaption>
</figure>
</li>
</ol>
</div>
</section>
CSS
* {
margin: 0 auto;
padding: 0;
}
img {
display: block;
max-width: 100%;
height: auto;
}
ol {
list-style: none;
}
a {
text-decoration: none;
color: inherit;
}
body {
margin: 50px auto;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
input[type="radio"] {
position: absolute;
left: -9999px;
}
.filters {
text-align: center;
margin-bottom: 2rem;
}
.filters * {
display: inline-block;
}
.filters label {
text-align: center;
padding: 0.25rem 0.5rem;
margin-bottom: 0.25rem;
min-width: 50px;
line-height: normal;
cursor: pointer;
transition: all 0.2s;
color: #999;
}
.filters label:hover {
background: #994B8A;
color: #fff;
}
.targets {
display: grid;
grid-gap: 1.5rem;
grid-template-columns: repeat(4, 1fr);
}
.targets .target {
background: #fafafa;
border: 1px solid rgba(0, 0, 0, 0.1);
}
.targets .target-title {
font-size: 1.2rem;
margin: 1rem 0 1rem 0.25rem;
color: #999;
}
.targets .target-title:hover {
text-decoration: underline;
}
.targets figcaption {
padding: 0.5rem;
font-size: 0.75rem;
}
.targets .target-categories {
margin-bottom: 0.75rem;
font-size: 0.75rem;
}
.targets .target-categories * {
display: inline-block;
}
.targets .target-categories li {
margin-bottom: 0.2rem;
}
.targets .target-categories a {
padding: 0.2rem 0.5rem;
transition: all 0.1s;
color: #994B8A;
}
.targets .target-categories a:hover {
background: #994B8A;
color: #fff;
}
[value="All"]:checked ~ .filters [for="All"],
[value="cat-a"]:checked ~ .filters [for="cat-a"],
[value="cat-b"]:checked ~ .filters [for="cat-b"],
[value="cat-c"]:checked ~ .filters [for="cat-c"],
[value="cat-d"]:checked ~ .filters [for="cat-d"],
[value="cat-e"]:checked ~ .filters [for="cat-e"],
[value="cat-f"]:checked ~ .filters [for="cat-f"] {
background: #994B8A;
color: #fff;
}
/* メディアクエリ */
@media screen and (max-width: 900px) {
.targets {
grid-template-columns: repeat(3, 1fr);
}
}
@media screen and (max-width: 650px) {
html {
font-size: 14px;
}
.targets {
grid-template-columns: repeat(2, 1fr);
}
}
/* アニメーション */
.checked_animation {
animation: checked_animation 0.4s ease-in-out both;
}
@keyframes checked_animation {
0% {
transform: translate(0, 300px);
opacity: 0;
}
100% {
transform: translate(0, 0);
opacity: 1;
}
}
JavaScript
window.addEventListener('DOMContentLoaded', function(){
const input_categories = document.querySelectorAll("input[name=categories]");
const targets = document.querySelectorAll(".target");
for(let target of targets) {
//animationend イベントを追加
target.addEventListener('animationend', () => {
// アニメーション終了後にクラスを削除
target.classList.remove('checked_animation');
});
}
for(let input_category of input_categories) {
input_category.addEventListener('change',function(){
for(let target of targets) {
target.style.setProperty('display', 'block');
//全ての要素からアニメーションのクラスを削除
target.classList.remove('checked_animation');
}
if( this.checked ) {
if(this.value !== 'All') {
const not_checked_categories = document.querySelectorAll('.target:not([data-category~=' + '"' + this.value + '"])');
for(let not_checked_category of not_checked_categories) {
not_checked_category.style.setProperty('display', 'none');
}
//data-category に選択されたラジオボタンの value 属性の値が含まれる .target の要素にアニメーションのクラスを追加
const checked_categories = document.querySelectorAll('.target[data-category~=' + '"' + this.value + '"]');
for(let checked_category of checked_categories) {
checked_category.classList.add('checked_animation');
}
}else{
//選択されたラジオボタンの value 属性の値が All の場合は全ての .target の要素にアニメーションのクラスを追加
for(let target of targets) {
target.classList.add('checked_animation');
}
}
}
});
}
});