今回はこのようなカードの作り方について解説していきます。
完成形のコード
See the Pen card by ゆき | Web制作 (@yukimum22) on CodePen.
一般的なカード型レイアウトと違うところ
今回のカードの場合、以下3つがクリック要素となります。
- 記事詳細へのリンク(画像とタイトル:ホバーアクション付き)
- お気に入り登録のためのボタン(クリップのアイコン)
- 絞り込みのためのタグ(#⚪︎⚪︎の部分)
一般的にカード型レイアウトの1つのカードを作る時、カード全体をaタグで囲む場合が多いと思います。
カード全体をリンクにする際には問題ありませんが、今回のようにカードの中に複数クリック要素がある場合、基本的にaタグの中にaタグは入れられないので、少し工夫が必要です。
コード解説
HTML
<div class="columnItem">
<div class="columnItem__link">
<a href=""></a>
<div class="columnItem__img"><img src="画像パス" alt=""><button class="clip-btn"></button></div>
<p class="columnItem__title">タイトル</p>
</div>
<div class="columnItem__tags">
<a href="">#タグ</a>
<a href="">#タグ</a>
<a href="">#タグ</a>
</div>
</div>
画像(columnItem__img)とタイトル(columnItem__title)をまとめてリンクにしたいので、columnItem__linkで囲います。
columnItem__linkの直下に空のaタグを仕込みます。
カード全体をaタグで囲ってしまうと、bottonタグやcolumnItem__tags内のaタグが効きません!
リンクにしたい要素がカード全体の場合は、columnItem__linkは要りません。columnItem直下にaタグを仕込みます。(下の図で青枠がなくなると考えてください。)
カード全体をaタグで挟まなければ、bottonタグやcolumnItem__tags内のaタグも効きます!
CSS
.columnItem {
width:300px;
display: flex;
flex-direction: column;
}
.columnItem__link {
position: relative;
}
.columnItem__link a {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.columnItem__img {
padding-top: 57%;
position: relative;
margin-bottom: 16px;
border-radius: 20px;
border: 3px solid #6aaabf;
overflow: hidden;
}
.columnItem__img img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
transition: all 0.2s ease;
}
.columnItem__link a:hover ~ .columnItem__img img {
transform: scale(1.1);
}
.columnItem .clip-btn {
position: absolute;
bottom: 12px;
right: 14px;
z-index: 1;
}
.columnItem__title {
font-size: 18px;
line-height: 1.5;
min-height: 55px;
transition: all 0.2s ease;
}
.columnItem__link a:hover ~ .columnItem__title {
color: #6aaabf;
}
.columnItem__tags a {
font-size: 12px;
line-height: 1.5;
letter-spacing: 0.05em;
display: inline-block;
color: #a3c5d9;
margin-right: 0.5em;
text-decoration: none;
}
/* クリップのボタン*/
.clip-btn {
display: block;
width: 35px;
height: 35px;
border-radius: 50%;
position: relative;
background-color: #fff;
border: 1px solid #6aaabf;
cursor: pointer;
}
.clip-btn.clicked {
background-color: #6aaabf;
border: 1px solid #fff;
}
.clip-btn::after {
content: "";
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 22px;
height: 20px;
background: no-repeat center/contain url(画像URL);
}
.clip-btn.clicked::after {
background: no-repeat center/contain url(画像URL);
}
各要素のスタイルについては説明を省略します。ポイントとしては、7行〜18行(色の変わった部分)で、columnItem__linkにposition:relativeを指定し、その直下のaタグ(columnItem__link > a)にposition:absoluteを指定してcolumnItem__linkに被せるところです。
aタグを被せることで、columnItem__link全体がリンクとなります。
JavaScript
//クリップボタンの切り替え
$(function () {
var buttons = document.querySelectorAll(".clip-btn");
buttons.forEach(function (button) {
button.addEventListener("click", function () {
button.classList.toggle("clicked");
});
});
});
なぜaタグの中のaタグはダメ?
リンク要素の中にリンク要素を入れてしまうと、単純にどちらに遷移するかわからない状態になってしまうので、基本的に入れ子にはできません。
HTMLのタグは6種類のカテゴリーに分かれており、属するカテゴリーにより「そのタグがどのカテゴリーの要素を入れて良いか」という入れ子のルール(コンテンツモデル)が存在します。
ちなみにaタグは「インタラクティブ・コンテンツ」に分類されます。インタラクティブ・コンテンツには他にもbutton、input、iframeなどがあり、ユーザーが操作可能なコンテンツとされています。
入れ子のルールはたくさんあるので、その都度確認しましょう。
入れ子のルールに関しては、こちらのチートシートが便利です!
以上になります。