웹 페이지를 만들고 나서 브라우저에 띄웠을 때 뭔가 이상한 느낌이 든 적이 있다.
내용은 다 있는데, 쏠려 있거나, 위아래 여백이 너무 없거나, 아니면 반대로 너무 벌어져 있거나. "디자인을 못 한 건지, 코드가 잘못된 건지" 구분도 안 된다.
결론부터 말하면 대부분은 레이아웃 속성을 제대로 안 잡아서 그렇다.
일단 기본 리셋부터
브라우저마다 기본 스타일이 다르다. <body>에 기본 margin이 붙어 있거나, <h1> 같은 태그에 이미 위아래 여백이 잡혀 있거나 하는 식이다.
그래서 어떤 사이트는 크롬에서 멀쩡한데 사파리에서 이상하게 보이는 일이 생긴다.
이걸 방지하는 가장 쉬운 방법은 CSS 파일 최상단에 이걸 박아두는 거다.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
CSS
복사
*는 모든 요소에 적용된다는 뜻이다. margin: 0; padding: 0으로 브라우저 기본값을 초기화하고, box-sizing: border-box는 나중에 설명하겠지만 padding과 border를 너비 계산에 포함시키는 옵션이다. 이걸 안 하면 나중에 레이아웃이 이상하게 틀리는 경우가 생긴다.
이 세 줄이 없으면 시작부터 삐걱댄다.
margin과 padding의 차이
이 둘을 헷갈리면 레이아웃 잡기가 계속 감이 안 온다.
간단하게 정리하면 이렇다.
•
margin — 요소 바깥쪽 여백. 다른 요소와의 거리를 조절한다.
•
padding — 요소 안쪽 여백. 내용물과 테두리 사이 공간을 조절한다.
.card {
margin: 24px; /* 카드 바깥, 다른 요소랑 24px 띄운다 */
padding: 16px; /* 카드 안쪽, 텍스트와 테두리 사이 16px */
}
CSS
복사
배경색이 있는 박스를 만들었을 때 padding은 배경 안으로 들어오고, margin은 배경 밖이다. 이 차이를 눈으로 보면 바로 이해된다.
콘텐츠 가운데 정렬, max-width 쓰는 이유
화면이 넓은 모니터에서 사이트를 열었을 때 글이 가로로 쭉 다 펼쳐져 있으면 읽기 불편하다. 실제로 대부분의 사이트는 콘텐츠 폭에 제한을 두고 있다.
.container {
max-width: 800px;
margin: 0 auto;
}
CSS
복사
max-width: 800px는 이 요소가 800px보다 넓어지지 않게 막는다. 화면이 800px보다 좁으면 자동으로 화면 너비에 맞춰진다.
margin: 0 auto는 좌우 마진을 자동으로 균등하게 배분하는 거다. 덕분에 콘텐츠가 항상 가운데에 온다. 위아래는 0, 좌우는 auto. 이 조합이 가운데 정렬의 기본이다.
box-sizing이 왜 중요하냐면
예를 들어 width: 300px인 박스에 padding: 20px을 주면 어떻게 될까.
기본값(content-box)에서는 패딩이 너비에 추가된다. 그러니까 실제 박스 크기는 300 + 20*2 = 340px이 된다.
box-sizing: border-box를 쓰면 패딩이 너비 안에 포함된다. 300px 안에 패딩이 들어오는 거라 실제 크기는 여전히 300px이다.
레이아웃을 수치로 계산할 때 border-box가 훨씬 직관적이다. 300px이라고 써놓으면 300px인 게 맞아야 하니까.
실제로 균형 잡는 방법
섹션마다 위아래 여백이 너무 붙어 있거나 너무 없는 경우, 보통 이렇게 잡는다.
section {
padding: 60px 0; /* 위아래 60px, 좌우 0 */
}
.section-inner {
max-width: 960px;
margin: 0 auto;
padding: 0 20px; /* 모바일에서 화면 끝에 안 붙게 좌우 패딩 */
}
CSS
복사
section에 위아래 여백을 주고, 안쪽에 inner 래퍼를 하나 둬서 콘텐츠 너비를 제한하는 패턴이다. 거의 모든 사이트에서 이 구조를 쓴다.
좌우 padding: 0 20px 부분이 중요한데, 모바일에서 화면 가장자리에 텍스트가 딱 붙지 않게 하는 용도다. 이거 없으면 모바일에서 보기 불편하다.
요소 간 간격은 gap으로
Flexbox나 Grid 안에 있는 자식 요소끼리의 간격은 margin 대신 gap을 쓰는 게 낫다.
.card-list {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
CSS
복사
margin으로 간격 주면 마지막 요소나 첫 번째 요소에도 여백이 생겨서 불필요하게 한쪽이 틀리는 경우가 있다. gap은 요소 사이에만 간격을 주기 때문에 훨씬 깔끔하다.
균형이 안 맞는다 싶을 때 체크리스트
뭔가 이상하다 싶으면 순서대로 확인한다.
1.
전체 리셋이 적용돼 있나 (* { margin: 0; padding: 0; box-sizing: border-box; })
2.
콘텐츠에 max-width와 margin: 0 auto 있나
3.
섹션 간 상하 여백 (padding: 60px 0 같은 것) 있나
4.
모바일 좌우 패딩 있나
5.
Flex/Grid 쓰고 있으면 gap으로 간격 처리했나
이 다섯 가지만 챙겨도 화면 균형이 크게 달라진다.
레이아웃은 감이라고 생각했는데, 따지고 보면 결국 숫자 싸움이다. 어디에 얼마나 여백을 주느냐를 의식적으로 결정하면 훨씬 빠르게 잡힌다.
실제 구현 코드 전체
위에서 설명한 리셋, max-width 가운데 정렬, section + inner 래퍼 패턴, gap 간격, box-sizing까지 전부 적용한 페이지다. index.html 파일 하나로 바로 실행된다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>레이아웃 균형 예제</title>
<style>
/* ── 1. 전체 리셋 ── */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* ── 2. 기본 설정 ── */
:root {
--color-primary: #4f46e5;
--color-text: #1f2937;
--color-sub: #6b7280;
--color-bg: #f9fafb;
--color-white: #ffffff;
--color-border: #e5e7eb;
--max-width: 960px;
}
body {
font-family: 'Segoe UI', sans-serif;
background-color: var(--color-bg);
color: var(--color-text);
line-height: 1.75;
}
/* ── 3. 공통 inner 래퍼 ── */
/* max-width + margin: 0 auto 로 항상 가운데 정렬 */
/* padding: 0 20px 로 모바일에서 끝에 안 붙게 */
.inner {
max-width: var(--max-width);
margin: 0 auto;
padding: 0 20px;
}
/* ── 4. 내비게이션 바 ── */
header {
background-color: var(--color-white);
border-bottom: 1px solid var(--color-border);
position: sticky;
top: 0;
z-index: 100;
}
nav {
max-width: var(--max-width);
margin: 0 auto;
padding: 0 20px;
height: 56px;
display: flex;
justify-content: space-between; /* 로고 왼쪽, 메뉴 오른쪽 */
align-items: center;
}
.logo {
font-weight: 700;
font-size: 1.1rem;
color: var(--color-primary);
}
.nav-menu {
display: flex;
gap: 24px; /* margin 대신 gap으로 메뉴 간격 */
list-style: none;
}
.nav-menu a {
text-decoration: none;
font-size: 0.9rem;
color: var(--color-sub);
transition: color 0.2s;
}
.nav-menu a:hover {
color: var(--color-primary);
}
/* ── 5. 히어로 섹션 ── */
/* section 단위로 padding: 80px 0 — 위아래 여백 통일 */
.hero {
background-color: var(--color-white);
border-bottom: 1px solid var(--color-border);
padding: 80px 0;
}
.hero-content {
display: flex;
align-items: center;
gap: 40px; /* flex 자식 요소 사이 간격은 gap */
}
.hero-icon {
width: 120px;
height: 120px;
border-radius: 50%;
background-color: var(--color-primary);
display: flex;
align-items: center;
justify-content: center;
font-size: 2.8rem;
flex-shrink: 0;
}
.hero-text h1 {
font-size: 1.9rem;
font-weight: 800;
margin-bottom: 10px; /* 제목과 본문 사이만 margin */
}
.hero-text p {
color: var(--color-sub);
font-size: 0.95rem;
}
/* ── 6. 개념 카드 섹션 ── */
.concepts {
padding: 80px 0;
}
.concepts h2 {
font-size: 1.4rem;
font-weight: 700;
margin-bottom: 32px;
}
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
gap: 20px; /* grid 칸 사이 간격 */
}
.card {
background-color: var(--color-white);
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 24px; /* 카드 안쪽 여백 — padding */
}
.card-label {
display: inline-block;
font-size: 0.75rem;
font-weight: 700;
color: var(--color-primary);
background-color: #eef2ff;
padding: 3px 10px;
border-radius: 999px;
margin-bottom: 12px;
}
.card h3 {
font-size: 1rem;
font-weight: 700;
margin-bottom: 8px;
}
.card p {
font-size: 0.88rem;
color: var(--color-sub);
}
.card code {
display: block;
margin-top: 14px;
padding: 12px;
background-color: #f3f4f6;
border-radius: 8px;
font-size: 0.82rem;
line-height: 1.8;
white-space: pre;
}
/* ── 7. 체크리스트 섹션 ── */
.checklist {
background-color: var(--color-white);
border-top: 1px solid var(--color-border);
padding: 80px 0;
}
.checklist h2 {
font-size: 1.4rem;
font-weight: 700;
margin-bottom: 28px;
}
.check-items {
display: flex;
flex-direction: column;
gap: 14px; /* 항목 사이 간격 */
}
.check-item {
display: flex;
align-items: flex-start;
gap: 14px;
padding: 18px 22px;
border: 1px solid var(--color-border);
border-radius: 10px;
}
.check-num {
font-size: 0.85rem;
font-weight: 700;
color: var(--color-white);
background-color: var(--color-primary);
width: 26px;
height: 26px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.check-text strong {
display: block;
font-size: 0.95rem;
margin-bottom: 4px;
}
.check-text span {
font-size: 0.85rem;
color: var(--color-sub);
}
/* ── 8. 푸터 ── */
footer {
background-color: #111827;
color: #9ca3af;
text-align: center;
padding: 28px 20px;
font-size: 0.85rem;
}
</style>
</head>
<body>
<!-- 내비게이션 -->
<header>
<nav>
<span class="logo">layout.guide</span>
<ul class="nav-menu">
<li><a href="#concepts">개념</a></li>
<li><a href="#checklist">체크리스트</a></li>
</ul>
</nav>
</header>
<!-- 히어로 -->
<section class="hero">
<div class="inner">
<div class="hero-content">
<div class="hero-icon">📐</div>
<div class="hero-text">
<h1>웹 화면 틀 잡기</h1>
<p>margin, padding, max-width, box-sizing.<br>
이 네 가지를 제대로 알면 레이아웃 균형이 잡힌다.</p>
</div>
</div>
</div>
</section>
<!-- 개념 카드 -->
<section class="concepts" id="concepts">
<div class="inner">
<h2>핵심 개념 정리</h2>
<div class="card-grid">
<div class="card">
<span class="card-label">리셋</span>
<h3>전체 초기화</h3>
<p>브라우저마다 다른 기본값을 없애는 첫 번째 단계다.</p>
<code>* {
margin: 0;
padding: 0;
box-sizing: border-box;
}</code>
</div>
<div class="card">
<span class="card-label">margin</span>
<h3>바깥 여백</h3>
<p>요소와 요소 사이 거리다. 배경색 영역 바깥에 적용된다.</p>
<code>.box {
margin: 24px;
/* 위/아래/좌/우 모두 24px */
}</code>
</div>
<div class="card">
<span class="card-label">padding</span>
<h3>안쪽 여백</h3>
<p>내용물과 테두리 사이 공간이다. 배경색 안쪽에 적용된다.</p>
<code>.box {
padding: 16px 24px;
/* 위아래 16px,
좌우 24px */
}</code>
</div>
<div class="card">
<span class="card-label">가운데 정렬</span>
<h3>max-width + margin auto</h3>
<p>콘텐츠 폭을 제한하고 좌우 마진을 자동으로 균등하게 배분한다.</p>
<code>.inner {
max-width: 960px;
margin: 0 auto;
padding: 0 20px;
}</code>
</div>
<div class="card">
<span class="card-label">box-sizing</span>
<h3>border-box</h3>
<p>padding이 width 안에 포함된다. 300px이라고 쓰면 실제로 300px이다.</p>
<code>.box {
width: 300px;
padding: 20px;
/* 실제 크기 300px
(border-box 기준) */
}</code>
</div>
<div class="card">
<span class="card-label">gap</span>
<h3>요소 간 간격</h3>
<p>Flex/Grid 자식 요소 사이 간격은 margin 대신 gap이 깔끔하다.</p>
<code>.list {
display: flex;
flex-wrap: wrap;
gap: 20px;
}</code>
</div>
</div>
</div>
</section>
<!-- 체크리스트 -->
<section class="checklist" id="checklist">
<div class="inner">
<h2>균형이 안 맞을 때 체크리스트</h2>
<div class="check-items">
<div class="check-item">
<div class="check-num">1</div>
<div class="check-text">
<strong>전체 리셋 적용 여부</strong>
<span>* { margin: 0; padding: 0; box-sizing: border-box; } — 이게 없으면 시작부터 삐걱댄다.</span>
</div>
</div>
<div class="check-item">
<div class="check-num">2</div>
<div class="check-text">
<strong>max-width + margin: 0 auto</strong>
<span>콘텐츠가 화면 가득 펼쳐지면 읽기 불편하다. 폭 제한이 필요하다.</span>
</div>
</div>
<div class="check-item">
<div class="check-num">3</div>
<div class="check-text">
<strong>섹션 위아래 여백</strong>
<span>section { padding: 80px 0; } — 섹션마다 일정한 리듬이 생긴다.</span>
</div>
</div>
<div class="check-item">
<div class="check-num">4</div>
<div class="check-text">
<strong>모바일 좌우 패딩</strong>
<span>padding: 0 20px — 없으면 모바일에서 글이 화면 끝에 딱 붙는다.</span>
</div>
</div>
<div class="check-item">
<div class="check-num">5</div>
<div class="check-text">
<strong>gap으로 간격 처리</strong>
<span>Flex/Grid 안에서는 margin 대신 gap. 훨씬 예측하기 쉽다.</span>
</div>
</div>
</div>
</div>
</section>
<!-- 푸터 -->
<footer>
© 2026 layout.guide · margin과 padding만 알아도 절반은 된다.
</footer>
</body>
</html>
HTML
복사

