WEB LAB
HTML/CSS 4.7 · 4부. 반응형과 움직임

실습 — 반응형 카드 목록

4부에서 배운 것을 하나씩 얹어 카드 목록을 완성합니다.

예상 학습 시간 20분 예제를 고치면 화면이 그대로 다시 그려집니다 난이도 중급
개념 설명

4부를 한 번에 사용합니다

카드 목록은 웹에서 가장 자주 만드는 것입니다. 상품 목록, 글 목록, 사진첩이 모두 같은 모양입니다.

4부에서 배운 것을 하나씩 얹어 완성합니다.

  1. 격자로 놓기(3.4)
  2. 폭에 따라 열 수 바꾸기(3.4 · 4.1)
  3. 그림 자리 정하기(4.3)
  4. 색과 간격에 이름 붙이기(4.4)
  5. 마우스를 올렸을 때(4.5)
최소 예제 · 편집 가능

완성본

브라우저 창을 좁히면 열 수가 바뀝니다. 카드에 마우스를 올려 보십시오.

<div class="cards">
  <article class="card">
    <img class="thumb" src="/learn/htmlcss/sample-logo.png" alt="">
    <div class="body">
      <span class="tag">공지</span>
      <h4>휴관 안내</h4>
      <p>다음 주 월요일은 쉽니다.</p>
    </div>
  </article>

  <article class="card">
    <img class="thumb" src="/learn/htmlcss/sample-logo.png" alt="">
    <div class="body">
      <span class="tag">안내</span>
      <h4>대출 방법</h4>
      <p>한 번에 다섯 권까지 빌릴 수 있습니다.</p>
    </div>
  </article>

  <article class="card">
    <img class="thumb" src="/learn/htmlcss/sample-logo.png" alt="">
    <div class="body">
      <span class="tag">시설</span>
      <h4>열람실 이용</h4>
      <p>3층에 있습니다.</p>
    </div>
  </article>
</div>
* { box-sizing: border-box; }

/* ④ 되풀이되는 값에 이름을 붙입니다 */
:root {
  --brand: #6e56cf;
  --line: #e5e0f5;
  --gap: 14px;
  --radius: 10px;
}

/* ①② 격자 — 폭에 따라 열 수가 바뀝니다 */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--gap);
}

.card {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;   /* 그림이 모서리를 넘지 않게 */
  background: #fff;

  /* ⑤ 마우스를 올렸을 때 */
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.card:hover, .card:focus-within {
  transform: translateY(-4px);
  box-shadow: 0 6px 16px rgb(0 0 0 / 0.12);
}

/* ③ 그림 자리를 정합니다 */
.thumb {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: #f4f2fb;
  display: block;
}

.body { padding: var(--gap); }

.tag {
  display: inline-block;
  background: #f4f2fb;
  color: var(--brand);
  font-size: 12px;
  padding: 2px 8px;
  border-radius: 10px;
}

.card h4 { margin: 8px 0 4px; font-size: 1rem; }
.card p  { margin: 0; color: #5b6272; font-size: 0.9rem; line-height: 1.7; }

@media (prefers-reduced-motion: reduce) {
  .card { transition: none; }
}
상세 사용법

여기서 고른 것들

자리고른 것까닭
목록auto-fit + minmax미디어 쿼리 없이 열 수가 바뀝니다.
카드overflow: hidden그림이 둥근 모서리를 넘지 않게 잘라 냅니다.
그림display: block기본이 inline 이라 아래에 빈틈이 생깁니다.
움직임:focus-within 함께키보드로 카드 안에 들어와도 같은 표시가 납니다.

img 아래의 빈틈은 자주 걸리는 자리입니다. inline 요소라 글자 아래 여백만큼 자리가 생깁니다. display: block 이면 사라집니다.

흔한 실수

세 가지

  • 카드 높이를 고정합니다. 글이 길면 넘칩니다. 높이는 내용이 정하게 두고, 줄을 맞춰야 하면 3.2 의 stretch 를 쓰십시오.
  • 그림 아래 빈틈이 생깁니다. display: block 을 주면 없어집니다.
  • minmax 의 최소를 너무 크게 잡습니다. 좁은 화면에서 그 값보다 좁아질 수 없어 가로로 넘칩니다. 320px 화면에서 확인해 보십시오.
실습 문제

4부 마무리

1. 좁은 화면에서 가로 카드로 바꾸기 난이도 상

화면이 480px 아래면 카드를 그림이 왼쪽, 글이 오른쪽인 가로 모양으로 바꾸십시오. 그림 폭은 100px 로 둡니다.

카드 안을 가로로 놓는 것은 Flexbox 입니다. 그림이 줄어들지 않게 flex-shrink: 0 이 필요합니다.
@media (max-width: 479px) { .card { display: flex; } .thumb { width: 100px; flex-shrink: 0; aspect-ratio: 1 / 1; } .body { flex: 1; min-width: 0; } }
요약

정리

  • 카드 목록은 auto-fit + minmax 하나로 반응형이 됩니다.
  • 둥근 모서리 안의 그림은 overflow: hidden 으로 잘라 냅니다.
  • img 아래 빈틈은 display: block 으로 없앱니다.
  • 여기까지가 4부입니다. 5부에서 접근성과 실무 규약을 다룹니다.