다다의 개발일지 6v6

[CSS] Learn CSS Flexbox by Building a Photo Gallery - flexbox 뽀시기 본문

Frontend/HTML, CSS

[CSS] Learn CSS Flexbox by Building a Photo Gallery - flexbox 뽀시기

dev6v6 2025. 2. 16. 21:12

https://www.freecodecamp.org/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-1

 

https://www.freecodecamp.org/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-1

 

www.freecodecamp.org

 

이번 과정은 귀여운 고양이 사진 9장으로 된 갤러리 만들기

 

box-sizing 속성 정리

기본적으로 CSS 박스 모델에서는 요소의 크기를 결정할 때 content-box 모델이 사용된다. (기본값)

 

content-box 모델의 특징

  • width 값은 오직 콘텐츠의 너비만을 의미함.
  • 패딩(padding)과 테두리(border)는 별도로 추가되므로, 요소의 실제 크기가 커짐.
  • 예를 들어, width: 200px;인 요소에 padding: 20px; border: 10px;이 있으면, 전체 크기(총 너비)는 260px이 됨.

-> box-sizing: border-box; 이용하면 레이아웃을 더 쉽게 조절할 수 있다.

 * {
  box-sizing: border-box;
}
  • border-box → width에 패딩·테두리까지 포함, 요소 크기가 유지됨.

-> 근데 또 마진은 추가 안됨..ㅎ 그래서 레이아웃 계산할 때 마진까지 고려해야 예상한 크기가 나온다.

 

Flexbox 정리

Flexbox(플렉스 박스)는 1차원(가로 또는 세로 한 방향) 레이아웃을 조정하는 CSS 속성이다.
컨테이너 안에서 아이템들의 정렬, 간격, 배치 등을 쉽게 조절할 수 있어!

  1. 컨테이너(Container) → display: flex;를 적용한 부모 요소
  2. 아이템(Items) → 컨테이너 안에 있는 자식 요소들

정렬 (Alignment) → 가로/세로 방향으로 요소 배치 조절
공간 분배 (Spacing) → 요소 간 간격을 자동 조절
반응형 디자인 (Responsiveness) → 화면 크기에 따라 유동적인 레이아웃 가능

 

🔹 1. Flexbox의 축(Axis) 개념

  • 메인 축(Main Axis) → flex-direction 속성으로 결정됨.
  • 교차 축(Cross Axis) → 메인 축과 수직 방향
row (기본값) 가로 (왼쪽 → 오른쪽) 기본 정렬
row-reverse 가로 (오른쪽 → 왼쪽) 반대 정렬
column 세로 (위 → 아래) 위에서 아래로 배치
column-reverse 세로 (아래 → 위) 반대 정렬

 

🔹 2. flex-wrap: 요소가 컨테이너보다 클 때 줄바꿈 여부

  • nowrap (기본값) → 줄바꿈 없음 (컨테이너가 작아지면 아이템이 자동으로 축소됨)
  • wrap줄바꿈 허용 (공간이 부족하면 다음 줄 또는 열로 넘어감)

 

🔹 3. justify-content: 메인 축에서의 아이템 정렬

 

flex-start (기본값) 왼쪽(위) 정렬
flex-end 오른쪽(아래) 정렬
center 중앙 정렬
space-between 첫 번째와 마지막 요소를 양 끝에 배치하고, 나머지는 균등 배치
space-around 요소들 사이에 같은 간격을 배치
space-evenly 요소들 사이 및 양 끝에 동일한 간격을 배치

 

🔹 4. align-items: 교차 ( 메인의 수직 ) 축에서의 아이템 정렬

flex-start 교차 축의 시작 부분 정렬
flex-end 교차 축의 끝부분 정렬
center 교차 축 중앙 정렬
stretch (기본값) 아이템을 컨테이너 높이에 맞게 늘림
baseline 텍스트 기준선(Baseline)에 맞춰 정렬

 

https://flexboxfroggy.com/#ko

 

Flexbox Froggy

A game for learning CSS flexbox

flexboxfroggy.com

위 링크: flexbox 게임으로 배우는 유명한 사이트!! 완주했음 ^-

 

gap이란?

  • gap 속성은 행(row)과 열(column) 사이의 간격을 설정하는 CSS 속성이다.
  • Flexbox, Grid, 다중 컬럼(multi-column) 레이아웃에서 사용할 수 있음.
  • 컨테이너 요소에 적용하며, 자식 요소 간의 간격을 조절함.

줄여서 사용할 수도 있다

.container {
  gap: 20px 10px; /* row-gap: 20px; column-gap: 10px; 와 동일 */
}

 

gap vs margin 차이점

gap 부모 컨테이너 자식 요소들 사이에 간격 추가 ✅ 중첩 없음
margin 개별 요소 요소의 바깥쪽 간격 조절 ❌ 중첩 가능 (margin-collapse 발생)

 

gap은 부모 컨테이너에서 한 번에 간격을 조절할 수 있어 더 깔끔한 방식!

 

 

중첩 문제(Margin Collapse)란?

CSS에서 margin을 사용할 때, 두 개의 요소가 맞닿으면 margin 값이 합쳐지지 않고 하나만 적용되는 현상이 발생할 수 있다. => 마진 중첩!

 

더보기

마진 중첩이 발생하는 경우

 

(1) 상하 마진이 겹칠 때

.box1 {
  margin-bottom: 30px;
  background: lightblue;
}

.box2 {
  margin-top: 20px;
  background: lightcoral;
}

 

👉 30px + 20px = 50px이 아니라, 큰 값인 30px만 적용됨!

 실제 적용된 마진: 30px


(2) 부모와 자식 요소의 마진이 겹칠 때

.parent {
  margin-top: 20px;
  background: lightgray;
}

.child {
  margin-top: 30px;
  background: lightgreen;
}

 

👉 30px만 적용됨 (큰 값이 우선 적용됨)

 실제 적용된 마진: 30px

 부모-자식 간에도 중첩 현상이 발생할 수 있다.


중첩을 방지하는 방법

 방법 1: padding을 사용하기
➡ padding은 중첩되지 않음!

.parent {
  padding-top: 20px; /* margin 대신 padding 사용 */
}

 

 방법 2: gap을 사용하기
➡ gap 속성은 중첩 없이 간격을 설정할 수 있음!

.container {
  display: flex;
  flex-direction: column;
  gap: 20px; /* 요소 간 간격 20px */
}

 

 방법 3: overflow: hidden; 적용하기
➡ 부모 요소에 overflow: hidden;을 설정하면 margin 중첩을 방지할 수 있다!

.parent {
  overflow: hidden;
}

 

::after 가상 요소란?

  • 선택한 요소의 마지막 자식 요소로 추가되는 가상 요소
  • HTML에 직접 존재하지 않지만, CSS에서 스타일을 적용할 수 있음
  • 주로 장식적 요소, 추가적인 스타일링, 레이아웃 조정 등에 사용

::after를 이용해서 이미지 정렬을 조정해보자

  • 갤러리가 있고, display: flex; justify-content: center;로 정렬된 상태
  • 마지막 이미지가 중앙에 위치함 (홀수 개라서 한 줄에 하나 남게 됨)
  • 이를 해결하기 위해 ::after를 사용하여 빈 요소를 추가하고, 공간을 차지하도록 만듦

현재 코드

.gallery {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center; /* 가운데 정렬 */
  align-items: center;
  gap: 16px;
  max-width: 1400px;
  margin: 0 auto;
  padding: 20px 10px;
}

.gallery img {
  width: 100%;
  max-width: 350px;
  height: 300px;
  object-fit: cover;
  border-radius: 10px;
}

.gallery::after {
  content: ""; /* 내용 없는 가상 요소 */
  width: 350px /* 이미지와 같은 너비 */
}

 

✔ content: "";을 사용해 빈 요소를 만들 수 있음

✔ ::after가 이미지와 동일한 크기의 빈 요소를 생성
✔ 이 빈 요소가 마지막 줄에서 공간을 차지하여 마지막 이미지를 왼쪽으로 밀어줌!! (이걸 위해 씀)

 

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Photo Gallery</title>
    <link rel="stylesheet" href="./styles.css">
  </head>
  <body>
    <header class="header">
      <h1>css flexbox photo gallery</h1>
    </header>
    <div class="gallery">
      <img src="https://cdn.freecodecamp.org/curriculum/css-photo-gallery/1.jpg" alt="자고 있는 고양이">
      <img src="https://cdn.freecodecamp.org/curriculum/css-photo-gallery/2.jpg" alt="뒤로 누워 있는 고양이">
      <img src="https://cdn.freecodecamp.org/curriculum/css-photo-gallery/3.jpg" alt="응시하는 고양이">
      <img src="https://cdn.freecodecamp.org/curriculum/css-photo-gallery/4.jpg" alt="짱귀여운 고양이">
      <img src="https://cdn.freecodecamp.org/curriculum/css-photo-gallery/5.jpg" alt="새하얀 파란 눈 고양이">
      <img src="https://cdn.freecodecamp.org/curriculum/css-photo-gallery/6.jpg" alt="두 마리 고양이">
      <img src="https://cdn.freecodecamp.org/curriculum/css-photo-gallery/7.jpg" alt="담요 속 고양이">
      <img src="https://cdn.freecodecamp.org/curriculum/css-photo-gallery/8.jpg" alt="놀란 고양이">
      <img src="https://cdn.freecodecamp.org/curriculum/css-photo-gallery/9.jpg" alt="퍼질러진 두 고양이">
    </div>
  </body>
</html>

styles.css

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: sans-serif;
  background: #f5f6f7;
}

.header {
  text-align: center;
  text-transform: uppercase;
  padding: 32px;
  background-color: #0a0a23;
  color: #fff;
  border-bottom: 4px solid #fdb347;
}

.gallery {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 16px;
  max-width: 1400px;
  margin: 0 auto;
  padding: 20px 10px;
}

.gallery img {
  width: 100%;
  max-width: 350px;
  height: 300px;
  object-fit: cover;
  border-radius: 10px;
}

.gallery::after {
  content: "";
  width: 350px;
}