



WithCodeMedia-1-pc
WithCodeMedia-2-pc
WithCodeMedia-3-pc
WithCodeMedia-4-pc




WithCodeMedia-1-sp
WithCodeMedia-2-sp
WithCodeMedia-3-sp
WithCodeMedia-4-sp









生徒記事一覧や実績紹介のカードが、なんだか野暮ったく見えてしまいます…。何を変えればいいですか?
ペン博士カードは影・余白・角丸・ホバーの4点で印象が決まるよ。今日はベースの作り方から、そのまま使えるデザイン20種類まで一気に渡すね。
記事一覧、実績紹介、料金プラン、スタッフ紹介。Webサイトで最も多く登場するパーツがカードです。使用頻度が高いぶん、少しの粗が全体の印象を下げます。
逆に言えば、カードの完成度を上げるだけでサイト全体が引き締まります。ポイントは装飾を足すことではなく、余白・影・角丸・ホバーの4要素を整えることです。
この記事では、崩れないカードの土台作りから、シャドウ系・ボーダー系・画像付き・横並びなど20種類のデザインを紹介します。すべてコピペで動く形にしてあります。

まずは土台です。カード単体のスタイルと、並べるためのグリッドを分けて考えると再利用しやすくなります。
<div class="cards">
<article class="card">
<h3 class="card__title">カードのタイトル</h3>
<p class="card__text">説明文がここに入ります。2〜3行を想定した長さです。</p>
<a class="card__link" href="#">詳しく見る</a>
</article>
<article class="card"><!-- 以下同じ構造 --></article>
<article class="card"><!-- 以下同じ構造 --></article>
</div>/* 並べる側(グリッド) */
.cards {
display: grid;
gap: 24px;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
/* カード単体 */
.card {
display: flex;
flex-direction: column;
padding: 24px;
border-radius: 14px;
background-color: #fff;
box-sizing: border-box;
}repeat(auto-fit, minmax(280px, 1fr))を使うと、画面幅に応じて列数が自動で変わります。メディアクエリを書かずに1列〜4列まで対応できるため、まずこの形を覚えておくと応用が利きます。

カードで最も多い相談が「文章量が違うとボタンの位置がバラバラになる」です。Flexboxで解決します。
.card {
display: flex;
flex-direction: column;
height: 100%; /* グリッドの行いっぱいに伸ばす */
}
.card__text {
flex-grow: 1; /* 余った高さを本文が吸収する */
margin-bottom: 16px;
}
.card__link {
margin-top: auto; /* リンクを常に最下部へ */
align-self: flex-start;
}flex-grow: 1を本文に、margin-top: autoをリンクに付けるのが定石です。これでテキスト量が違ってもボタンの高さが揃います。
画像付きカードでは、画像の比率も固定しておくと安定します。aspect-ratioとobject-fitの組み合わせが確実です。
.card__img {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover; /* 比率を保って枠を埋める */
border-radius: 10px;
}影は「浮かせる高さ」で意味が変わります。用途に合わせて選んでください。
.card-soft {
background-color: #fff;
border-radius: 14px;
padding: 24px;
box-shadow: 0 2px 8px rgba(15, 23, 42, .08);
}.card-layered {
background-color: #fff;
border-radius: 14px;
padding: 24px;
/* 近い影+遠い影を重ねると現実の影に近づく */
box-shadow:
0 1px 2px rgba(15, 23, 42, .10),
0 8px 24px rgba(15, 23, 42, .08);
}.card-lift {
background-color: #fff;
border-radius: 14px;
padding: 24px;
box-shadow: 0 2px 8px rgba(15, 23, 42, .08);
transition: transform .25s ease, box-shadow .25s ease;
}
.card-lift:hover {
transform: translateY(-6px);
box-shadow: 0 12px 28px rgba(15, 23, 42, .14);
}.card-tinted {
background-color: #fff;
border-radius: 14px;
padding: 24px;
box-shadow: 0 10px 24px rgba(14, 165, 233, .22);
}.card-flat {
background-color: #fff;
border: 1px solid #e5e7eb;
border-radius: 14px;
padding: 24px;
transition: border-color .2s, background-color .2s;
}
.card-flat:hover {
border-color: #0ea5e9;
background-color: #f8fafc;
}影は薄く・広くが基本です。rgbaの透明度は0.08〜0.15程度に収めると、上品な浮き方になります。真っ黒な影は安っぽく見えます。
色帯やアイコンで分類を示したいときに使う形です。カテゴリ別の記事一覧などに向きます。
.card-bar {
background-color: #fff;
border-radius: 12px;
border-left: 6px solid #0ea5e9;
padding: 20px 24px;
box-shadow: 0 2px 8px rgba(15, 23, 42, .06);
}.card-top {
background-color: #fff;
border-radius: 12px;
border-top: 5px solid #8b5cf6;
padding: 22px;
}.card-outline {
position: relative;
background-color: #fff;
border-radius: 12px;
padding: 24px;
border: 2px solid #e5e7eb;
}
.card-outline::after {
content: "";
position: absolute;
left: 0;
bottom: -2px;
width: 0;
height: 4px;
background-color: #0ea5e9;
transition: width .3s ease;
}
.card-outline:hover::after {
width: 100%;
}.card-gradient-border {
border-radius: 14px;
padding: 2px; /* 縁の太さ */
background-image: linear-gradient(135deg, #0ea5e9, #8b5cf6);
}
.card-gradient-border > .inner {
border-radius: 12px;
background-color: #fff;
padding: 22px;
height: 100%;
}.card-num {
position: relative;
background-color: #fff;
border-radius: 14px;
padding: 32px 24px 24px;
box-shadow: 0 2px 10px rgba(15, 23, 42, .08);
}
.card-num::before {
content: attr(data-num); /* HTMLのdata-num属性を表示 */
position: absolute;
top: -18px;
left: 20px;
width: 40px;
height: 40px;
display: grid;
place-items: center;
border-radius: 50%;
background-color: #0ea5e9;
color: #fff;
font-weight: 800;
}attr()を使うと、HTML側のdata-num="01"をそのまま表示できます。番号をCSSで持たないので、順番の入れ替えに強い作りです。
サムネイル付きのカードは、画像の扱いで印象が決まります。ホバー演出は画像側に付けると自然です。
.card-zoom {
border-radius: 14px;
overflow: hidden; /* はみ出しを切る */
background-color: #fff;
box-shadow: 0 2px 10px rgba(15, 23, 42, .08);
}
.card-zoom img {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
transition: transform .4s ease;
}
.card-zoom:hover img {
transform: scale(1.06);
}.card-overlay {
position: relative;
border-radius: 14px;
overflow: hidden;
}
.card-overlay img {
width: 100%;
aspect-ratio: 4 / 3;
object-fit: cover;
display: block;
}
.card-overlay__body {
position: absolute;
inset: auto 0 0 0;
padding: 20px;
color: #fff;
background-image: linear-gradient(to top, rgba(15, 23, 42, .85), transparent);
}.card-reveal {
position: relative;
border-radius: 14px;
overflow: hidden;
}
.card-reveal__text {
position: absolute;
inset: 0;
display: grid;
place-items: center;
padding: 20px;
color: #fff;
background-color: rgba(14, 165, 233, .92);
opacity: 0;
transition: opacity .3s ease;
}
.card-reveal:hover .card-reveal__text,
.card-reveal:focus-within .card-reveal__text {
opacity: 1;
}.card-person {
text-align: center;
padding: 28px 20px;
border-radius: 14px;
background-color: #fff;
box-shadow: 0 2px 10px rgba(15, 23, 42, .08);
}
.card-person img {
width: 96px;
height: 96px;
border-radius: 50%;
object-fit: cover;
margin-bottom: 14px;
}.card-badge {
position: relative;
border-radius: 14px;
overflow: hidden;
background-color: #fff;
}
.card-badge__label {
position: absolute;
top: 12px;
left: 12px;
padding: 4px 12px;
border-radius: 999px;
background-color: #ef4444;
color: #fff;
font-size: 0.8em;
font-weight: 700;
}13番の:focus-withinは忘れやすい指定です。これを入れておくと、キーボード操作でも説明文が出ます。ホバーだけに頼ると、タッチ端末とキーボード利用者が置き去りになります。
一覧性を優先する場面では、横並びのカードが読みやすくなります。
.card-row {
display: grid;
grid-template-columns: 200px 1fr;
gap: 20px;
align-items: center;
padding: 16px;
border-radius: 14px;
background-color: #fff;
box-shadow: 0 2px 8px rgba(15, 23, 42, .07);
}
.card-row img {
width: 100%;
aspect-ratio: 4 / 3;
object-fit: cover;
border-radius: 10px;
}
@media (max-width: 640px) {
.card-row {
grid-template-columns: 1fr; /* スマホは縦積み */
}
}.card-list > * + * {
border-top: 1px solid #e5e7eb;
}
.card-list__item {
display: flex;
gap: 16px;
padding: 18px 4px;
transition: background-color .2s;
}
.card-list__item:hover {
background-color: #f8fafc;
}.card-plan {
border: 2px solid #e5e7eb;
border-radius: 16px;
padding: 28px 24px;
background-color: #fff;
text-align: center;
}
.card-plan.-recommend {
border-color: #0ea5e9;
box-shadow: 0 12px 30px rgba(14, 165, 233, .18);
transform: scale(1.03); /* 推奨プランだけ少し大きく */
}.card-feature {
display: grid;
grid-template-columns: 56px 1fr;
gap: 16px;
padding: 22px;
border-radius: 14px;
background-color: #f8fafc;
}
.card-feature__icon {
display: grid;
place-items: center;
width: 56px;
height: 56px;
border-radius: 14px;
background-color: #e0f2fe;
}.card-link {
position: relative;
border-radius: 14px;
padding: 24px;
background-color: #fff;
box-shadow: 0 2px 8px rgba(15, 23, 42, .08);
}
/* タイトルのリンクをカード全面に広げる */
.card-link__title a::after {
content: "";
position: absolute;
inset: 0;
}
.card-link:hover {
background-color: #f8fafc;
}20番の手法なら、カード全体を押せるのにリンクは1つだけという理想的な形になります。カード全体をaタグで囲むと、読み上げ時に長い文章が1つのリンク名になってしまうため避けたい実装です。

演出は「押せることが伝わる」ことが目的です。派手さより一貫性を優先します。
| 演出 | 書き方 | 向く場面 |
|---|---|---|
| 浮き上がる | translateY(-6px)+影 | 記事一覧・実績 |
| 少し拡大 | scale(1.02) | 画像主体のカード |
| 背景が変わる | background-color | リスト型・管理画面 |
| 枠線が伸びる | 擬似要素のwidth | ブランド感を出したい時 |
| 画像だけズーム | img にscale | サムネイル付き |
/* 動きを抑える設定の人には演出を止める */
@media (prefers-reduced-motion: reduce) {
.card-lift,
.card-zoom img {
transition: none;
}
.card-lift:hover {
transform: none;
}
}カードは背景色と影で成立しているため、ダークモードでは影がほとんど見えません。境界の作り方を変えます。
:root {
--card-bg: #ffffff;
--card-border: #e5e7eb;
--card-shadow: 0 2px 10px rgba(15, 23, 42, .08);
}
@media (prefers-color-scheme: dark) {
:root {
--card-bg: #1e293b;
--card-border: #334155;
--card-shadow: none; /* 影の代わりに境界線で分ける */
}
}
.card {
background-color: var(--card-bg);
border: 1px solid var(--card-border);
box-shadow: var(--card-shadow);
}暗い背景では影が沈むので、境界線と背景の明度差でカードを浮かせます。変数にしておけば切り替えは数行で済みます。

最後に、カードでつまずきやすい点をまとめます。
| 症状 | 原因 | 対処 |
|---|---|---|
| 高さがバラバラ | flexの指定がない | 本文にflex-grow: 1 |
| ボタンの位置がずれる | 下端に寄せていない | margin-top: auto |
| 画像の比率が崩れる | 高さ指定がない | aspect-ratio+object-fit |
| 角丸から画像がはみ出す | 親に切り抜き指定がない | overflow: hidden |
| 影が切れて見える | 親のoverflow | 影を持つ要素を外に出す |
| スマホで文字が詰まる | paddingが固定値 | 余白を相対値に変える |
どれも装飾ではなく構造側の指定です。土台のカードクラスに最初から入れておけば、個別対応はほとんど不要になります。
装飾より効くのが余白と文字の設計です。迷ったときの基準を置いておきます。
| 項目 | 推奨値 | 理由 |
|---|---|---|
| カード内側の余白 | 20〜28px | 文字と枠が近いと窮屈に見える |
| カード同士の間隔 | 20〜32px | 隣接カードとの境界を明確にする |
| タイトル | 1.15〜1.3rem・行間1.4 | 2行までに収まる長さが理想 |
| 本文 | 0.95rem・行間1.7 | 3行前後で切ると一覧性が保てる |
| 角丸 | 12〜16px | 画像の角丸と数値を揃える |
特に効くのがタイトルの行数を揃えることです。1行と3行のカードが混ざると、どれだけ影や角丸を整えても不揃いに見えます。文字数の上限を決め、超える場合は省略表示にします。
/* タイトルは2行、本文は3行で省略する */
.card__title {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
line-height: 1.4;
}
.card__text {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
line-height: 1.7;
}行数を固定すると、文章量に関わらずカードの見た目が安定します。CMSで運用するサイトでは特に効果があります。
公開前に次の6点を確認してください。ここを通せば、ほとんどの崩れは事前に潰せます。
チェックは実データの最長・最短で行うのが鉄則です。ダミーテキストだけで確認すると、公開後に必ず崩れます。
カードは影・余白・角丸・ホバーの4要素で印象が決まります。グリッドはrepeat(auto-fit, minmax(280px, 1fr))で列数を自動化し、カード内部はFlexboxで本文にflex-grow: 1、リンクにmargin-top: autoを当てれば高さが揃います。影は薄く広く、ホバーは0.25秒前後の控えめな動きに留めるのが上品です。画像はaspect-ratioとobject-fit: coverで比率を固定し、カード全体をリンクにするときは擬似要素を広げる方法を選んでください。
カードをdisplay: flex; flex-direction: column;にして、本文にflex-grow: 1、最下部のボタンにmargin-top: autoを指定します。グリッドの各セルはもともと同じ高さに伸びるため、この2行でボタン位置まで揃います。
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))と書けば、画面幅に応じて自動で列数が変わります。メディアクエリは不要です。最小幅の値を変えると、折り返すタイミングを調整できます。
タイトル内のリンクに::afterを作り、position: absolute; inset: 0;でカード全面へ広げます。カード自体をaタグで囲む方法は、読み上げ時にカード内の全テキストが1つのリンク名として読まれるため推奨されません。
タッチ端末にホバー状態はないため、演出は基本的に発火しません。重要な情報をホバーでしか出さない設計は避け、常時表示にしてください。:focus-withinを併記しておくと、キーボード操作にも対応できます。
rgbaの透明度を0.08〜0.15の範囲で調整してください。単一の濃い影より、近い影と遠い影を重ねる二重シャドウのほうが自然に見えます。ダークモードでは影が機能しないため、境界線で代替します。
CSSの実装テクニックを「レイアウト・装飾・アニメーション・基礎・トラブル解決」の目的別に探せる総まとめページを用意しています。実装で迷ったときの索引としてどうぞ。

目的に合わせて選べる「AI副業」「AI転職」「AI活用」の3コースを用意。副収入・キャリアチェンジ・日常の生産性アップまで、あなたのゴールに合わせてAIを学べます。
会員登録はカンタン30秒で完了します。まずは公式LINEから、無料でAI学習をスタートしましょう!
WithCodeでWeb制作を習得後、フリーランスエンジニアとして活動。HTML/CSS・JavaScript・WordPress案件を中心に年間20件以上の制作実績を持つ。「難しい技術をわかりやすく」をモットーに、初心者〜中級者向けの技術記事を執筆。副業・フリーランス独立を目指す方に向けた情報発信に注力している。
公式サイト より
今すぐ
無料カウンセリング
を予約!