본문 바로가기

비개발자의 개발 일지

현장 팀장에서 수출 ERP까지 — AI와 함께 시스템을 만든 기록

시리즈 보기
php

반응형 레이아웃 — 가변 그리드 · 가변 폰트 · 가변 이미지 완전 정리

by 왕진 2026. 6. 10.
반응형

 

 

Web Development · Responsive Layout

반응형 레이아웃 완전 정리
가변 그리드 · 가변 폰트 · 가변 이미지

고정 레이아웃 → 가변 레이아웃 → 반응형 이미지까지, 화면 크기에 휘는 웹 만들기
시작 왜 반응형이 필요한가

웹 페이지를 만들 때 width: 960px처럼 고정값으로만 잡으면 PC에서는 멀쩡하지만 스마트폰에서는 가로 스크롤이 생긴다. 반응형 레이아웃은 화면 크기가 달라져도 자연스럽게 늘어나고 줄어드는 웹을 만드는 기술이다. 이번 정리에서는 세 가지 핵심을 다룬다.

① 가변 그리드
② 가변 폰트
③ 가변 이미지

px → % · em · <picture> 로 옮겨가는 흐름


용어 핵심 키워드
고정 레이아웃px 기반 — 화면 작아져도 그대로
가변 레이아웃% 기반 — 화면 따라 늘고 줆
viewport모바일에서 화면 폭을 알리는 메타 태그
em부모 폰트 크기를 1로 둔 비율 단위
% 변환식대상 ÷ 부모 × 100
<picture>화면 폭에 따라 다른 이미지 로드
srcset소스 이미지 후보 목록
media소스를 적용할 화면 조건

1 고정 그리드 레이아웃 — 모든 것의 출발점

가변을 이해하려면 먼저 고정을 봐야 한다. 픽셀 단위로 칸을 짜놓은 가장 단순한 형태의 레이아웃이다.

#wrapper { width: 960px; /* 전체 폭 — 고정 */ margin: 0 auto; /* 가운데 정렬 */ } header { width: 960px; height: 120px; } .content { float: left; width: 600px; padding: 15px; } .right-side{ float: right; width: 300px; padding: 15px; } footer { clear: both; height: 120px; }
실제 모양
Fixed Layout · width:960px
고정 그리드 헤더 (960px)
본문 (600px + padding 15px)
사이드바 (300px)
문제점 — 화면이 960px보다 작아지면 wrapper의 폭이 그대로 유지돼 가로 스크롤이 발생한다. 모바일에서 글씨가 깨알같이 보이거나, 사용자가 좌우로 끌면서 봐야 한다.
※ 고정 레이아웃의 의미
  • 한 번 잡아놓으면 디자인 의도대로 정확히 보임 — 인쇄물 같은 안정감
  • 대신 환경(모바일·태블릿)이 바뀌면 무력함
  • 그래서 % 단위로 옮겨가야 한다

2 가변 그리드 레이아웃 — px를 %로

핵심 아이디어는 단순하다. 모든 px 값을 부모 대비 % 값으로 바꾸는 것. 부모가 줄어들면 자식도 같은 비율로 줄어든다.

📐 변환 공식대상 폭 ÷ 부모 폭 × 100%
예: 부모 960px, 본문 600px → 600 / 960 × 100 = 62.5%
#wrapper { width: 96%; /* 화면 좌우 2%씩 여백 확보 */ margin: 0 auto; } header { width: 100%; height: 120px; } .content { float: left; width: 62.5%; padding: 1.5625%; } .right-side{ float: right; width: 31.25%; padding: 1.5625%; } footer { clear: both; width: 100%; }
변환 과정 한눈에 보기
요소 고정값(px) 계산식 가변값(%)
wrapper 960px 화면 좌우 여백 96%
.content (폭) 600px 600 ÷ 960 × 100 62.5%
.right-side (폭) 300px 300 ÷ 960 × 100 31.25%
padding 15px 15 ÷ 960 × 100 1.5625%
실제 모양 — 창 크기를 줄여보면 같이 줄어든다
Fluid Layout · width:96%
가변 그리드 헤더 (100%)
본문 (62.5%)
사이드바 (31.25%)
viewport 메타가 필수<meta name="viewport" content="width=device-width, initial-scale=1">
이게 없으면 모바일이 임의로 페이지를 980px로 가정하고 축소해서 보여준다 → % 계산이 무의미해짐.

반응형
3 가변 폰트 — px를 em으로

레이아웃은 %로 줄였는데 폰트가 40px로 고정되어 있으면, 작은 화면에서 글자가 박스를 뚫고 나간다. 폰트도 비율 단위(em)로 바꿔야 한다.

px (절대 단위)
  • 화면이나 부모와 무관한 고정 크기
  • 모바일에서도 동일
  • 예: font-size: 40px;
em (상대 단위)
  • 부모의 font-size가 1em
  • 부모가 줄면 같이 줄어듦
  • 예: font-size: 2em;
em 계산법
🧮 em 변환 공식원하는 px ÷ 부모 px = em 값
부모가 16px일 때 32px → 32 / 16 = 2em
부모가 12px일 때 18px → 18 / 12 = 1.5em
#wrapper { width: 96%; font-size: 12px; /* 기준 폰트 = 12px */ } .header-text { font-size: 2em; /* 12 × 2 = 24px */ } .fluid-text { font-size: 1.5em; /* 12 × 1.5 = 18px */ }
실제 결과
font-size: 12px (부모) · 2em / 1.5em (자식)
기준 1em (12px)
가변 그리드 레이아웃 (2em)
가변 폰트 (1.5em)
※ em이 좋은 이유
  • 부모 폰트만 바꾸면 자식 폰트가 자동으로 비율 유지
  • 미디어 쿼리에서 html { font-size: 14px }처럼 한 줄만 바꿔도 전체 폰트 사이즈가 출렁이게 만들 수 있음
  • 접근성 — 사용자가 브라우저 글씨 크기를 키워도 비율이 깨지지 않음
em의 함정 — 중첩 시 누적된다
부모 1.5em → 자식 1.5em이면 자식의 실제 크기는 1.5 × 1.5 = 2.25em이 된다. 깊게 중첩되면 예측이 어려워서, 누적이 싫다면 rem(루트 기준)을 쓰는 게 안전하다.

4 가변 이미지 — 큰 이미지가 박스를 뚫는다

이번엔 이미지를 추가했다고 해보자. 본문 박스(.content)는 62.5%로 가변인데, 그 안에 들어간 <img>는 원래 폭 그대로다.

<section class="content"> <h4>본문</h4> <img src="images/fireworks.png"> <!-- 폭 800px 짜리 이미지 --> </section>
실제 모습 — 이미지가 부모를 뚫고 나간다
img가 .content(62.5%)를 무시하고 원본 크기로 표시
 

원본 800px 이미지 → 부모가 600px이든 300px이든 그대로 800px

왜 이런 일이?<img>는 기본적으로 자기 원본 크기를 갖는다. 부모가 줄어든다고 자동으로 따라 줄지 않는다.
해결책 — 단 한 줄
img { max-width: 100%; /* 부모를 절대 넘지 않음 */ height: auto; /* 비율 유지 */ }
속성 의미 왜 필요한가
max-width: 100% 부모보다 작을 때만 원본대로, 크면 부모에 맞춰 축소 이미지가 박스 뚫는 걸 막음
width: 100% (대안) 항상 부모 폭 100%로 채움 작은 이미지가 강제로 늘어나는 단점
height: auto 가로 비율에 맞춰 세로 자동 조정 이미지가 찌그러지지 않게

5 <picture> — 화면 크기별로 다른 이미지 로드

max-width: 100%로 축소만 하면 되는 게 아니다. 모바일 사용자가 4K 짜리 큰 이미지를 다운받아 와서 화면에서 작게 줄이는 것은 데이터 낭비다. <picture>처음부터 화면 크기에 맞는 이미지만 다운로드하게 한다.

<picture> <source srcset="images/shop-large.jpg" media="(min-width:1024px)"> <source srcset="images/shop-medium.jpg" media="(min-width:768px)"> <source srcset="images/shop-small.jpg" media="(min-width:320px)"> <img src="images/shop.jpg" alt="fill with coffee" style="width:100%;"> </picture>
동작 흐름
브라우저 로드
화면 폭 확인
매칭되는 source 선택
해당 이미지만 다운로드
화면 폭별로 어떤 이미지가 뜨나
화면 폭 적용되는 source 로드되는 이미지
1024px 이상 min-width: 1024px shop-large.jpg
768px ~ 1023px min-width: 768px shop-medium.jpg
320px ~ 767px min-width: 320px shop-small.jpg
320px 미만 / 미지원 브라우저 전부 매칭 안 됨 shop.jpg (img의 src 사용)
SMALL
~767px
MEDIUM
768~1023px
LARGE
1024px~
📌 source 순서가 중요하다 — 브라우저는 위에서부터 매칭되는 첫 번째 source를 선택한다. 큰 화면용을 먼저 두는 게 관례.
왜 마지막에 <img>가 또 있을까?

<picture> 안의 <img>는 두 가지 역할을 한다.

  • 대체(fallback)<picture>를 지원하지 않는 구식 브라우저(IE 등)에서 표시할 기본 이미지
  • 실제 렌더링 대상 — 모든 source가 매칭 안 됐을 때, 또는 spec상 img는 항상 있어야 한다
※ <picture> vs <img srcset>
  • <picture>아트 디렉션: 화면별로 완전히 다른 이미지를 보여주고 싶을 때 (모바일은 인물 클로즈업, 데스크톱은 풍경)
  • <img srcset>해상도 대응: 같은 이미지의 1x/2x/3x 버전 자동 선택

6 고정 vs 가변 — 한눈에 보기
항목 고정 (Fixed) 가변 (Fluid)
레이아웃 단위 px % (또는 vw)
폰트 단위 px em / rem
이미지 원본 크기 max-width: 100% + <picture>
모바일 대응 가로 스크롤 발생 자연스럽게 줄어듦
viewport 메타 거의 의미 없음 필수
예상 가능성 매우 높음 (정확함) 비율로 사고해야 함

7 자주 하는 실수
증상 원인 해결
모바일에서 페이지가 작게 축소됨 viewport 메타 없음 <meta name="viewport" content="width=device-width, initial-scale=1"> 추가
이미지가 박스를 뚫고 나감 img에 max-width 미설정 img { max-width: 100%; height: auto; }
폰트가 모바일에서도 그대로 큼 font-size를 px로 고정 em / rem / clamp() 사용
em이 예상보다 너무 큼/작음 중첩으로 누적 발생 rem(루트 기준) 사용
<picture>에서 큰 이미지가 안 뜸 source 순서가 작은 것부터 정렬됨 큰 화면용을 위에 배치
모든 화면에서 같은 이미지 다운로드 img 하나만 사용 <picture> + media로 분기

8 핵심 한 줄 요약

RESPONSIVE LAYOUT — KEY POINTS

고정 → 가변 변환대상 ÷ 부모 × 100 = %
폰트 단위px → em / rem (부모 또는 루트 기준 비율)
이미지 기본img { max-width: 100%; height: auto; }
화면별 다른 이미지<picture> + <source media> (큰 화면용을 먼저)
모바일 필수<meta name="viewport" content="width=device-width, initial-scale=1">
반응형 3대 축가변 그리드 + 가변 폰트 + 가변 이미지

Tags

#반응형레이아웃 #가변그리드 #가변폰트 #가변이미지 #em단위 #picture #srcset #viewport #maxwidth #fluidlayout #CSS3 #티스토리
▼ 티스토리 태그 입력란 복사용
반응형레이아웃, 가변그리드, 가변폰트, 가변이미지, em단위, picture, srcset, viewport, maxwidth, fluidlayout, CSS3, 티스토리
반응형

댓글