여백은 비어 있는 곳이 아니라 요소들의 관계를 말해 주는 언어입니다. 붙일 것은 붙이고 뗄 것은 떼는 규칙을 CSS로 잡으면 선을 긋지 않아도 화면이 저절로 묶입니다. 아래 코드는 그대로 복사해 확인할 수 있습니다.
03.1 가까운 것끼리 묶기
제목과 설명이 카드끼리의 간격과 똑같이 벌어져 있으면 무엇이 한 덩어리인지 알 수 없습니다. 안쪽은 좁히고 바깥은 넓힙니다.
.card {
display: flex;
flex-direction: column;
gap: 4px;
padding: 20px;
}
.card + .card {
margin-top: 24px;
}
제목과 설명은 4px로 바짝 붙이고 카드끼리는 24px로 벌리면, 좁은 간격이 이건 한 식구라고 말하고 넓은 간격이 여기서부터 다른 이야기라고 말합니다. 여백만으로 그룹이 읽힙니다.
03.2 간격에 리듬 만들기
간격을 그때그때 눈대중으로 정하면 화면이 미묘하게 어수선해집니다. 몇 배씩 커지는 값을 변수로 정해 두고 골라 씁니다.
:root {
--space-1: 4px;
--space-2: 8px;
--space-3: 16px;
--space-4: 32px;
}
.stack > * + * {
margin-top: var(--space-3);
}
4, 8, 16, 32처럼 배수로 오르는 값만 쓰면 간격끼리 조화가 생깁니다. stack 안의 형제 사이에만 위 여백을 주는 이 방식은 첫 요소엔 군더더기 여백을 남기지 않습니다.
03.3 안쪽 여백으로 숨통 틔우기
글자가 상자 벽에 딱 붙으면 답답하고 눌린 느낌이 납니다. 버튼이든 카드든 안쪽에 여백을 둬야 편안해집니다.
.btn {
padding: 10px 18px;
border-radius: 8px;
}
.tag {
padding: 2px 8px;
border-radius: 999px;
}
버튼은 세로보다 가로 여백을 넉넉히 줘야 눌리는 판처럼 보이고, 작은 태그는 여백을 촘촘히 줘야 아담하게 붙습니다. 같은 padding이라도 요소 성격에 맞춰 비율을 달리하는 게 핵심입니다.
03.4 본문에 읽는 여백 주기
글이 좌우 끝까지 꽉 차면 한 줄이 너무 길어 눈이 다음 줄을 놓칩니다. 폭을 제한하고 줄 간격을 벌립니다.
.prose {
max-width: 65ch;
line-height: 1.7;
margin: 0 auto;
}
.prose p + p {
margin-top: 1em;
}
max-width를 65ch로 두면 한 줄이 약 예순 자 안팎에서 끊겨 읽기 좋은 길이가 됩니다. line-height 1.7은 줄 사이를 벌려 눈이 윗줄과 아랫줄을 헷갈리지 않게 합니다. 여백은 문단 안에도 필요합니다.
03.5 여백으로 시선 모으기
중요한 안내 하나를 강조하고 싶을 때 색이나 테두리부터 손대기 쉽지만, 주변을 비우는 것만으로도 충분할 때가 많습니다.
.callout {
margin: 40px 0;
padding: 24px;
background: #f9fafb;
}
위아래로 40px씩 넉넉히 비우면 그 요소만 섬처럼 떠올라 시선을 붙듭니다. 빽빽한 화면에서 한 곳만 여백을 크게 두면 거기가 곧 주인공이 됩니다. 비움이 곧 강조인 셈입니다.
03.6 겹치는 세로 여백 다스리기
위 요소의 아래 마진과 아래 요소의 위 마진이 만나면 둘 중 큰 값 하나로 합쳐집니다. 이 겹침을 모르면 여백이 예상과 어긋납니다.
.section {
padding-top: 32px;
}
.section > :first-child {
margin-top: 0;
}
마진 대신 부모의 padding으로 위 여백을 주면 겹침이 일어나지 않아 값이 그대로 유지됩니다. 첫 자식의 위 마진을 0으로 지워 두면 padding과 마진이 이중으로 쌓이는 사고도 막습니다.
03.7 반응형으로 여백 조절
넓은 화면에 맞춰 큼직하게 둔 여백은 폰에서 화면을 잡아먹습니다. 화면이 좁아지면 여백도 함께 줄입니다.
.wrap {
padding: 64px;
}
@media (max-width: 600px) {
.wrap {
padding: 24px 16px;
}
}
데스크톱은 64px로 시원하게 두되 좁은 화면은 좌우 16px까지 좁혀 콘텐츠 폭을 지킵니다. 요즘은 clamp로 이 조절을 한 줄에 담기도 합니다.
.wrap {
padding: clamp(24px, 5vw, 64px);
}
clamp는 최소 24px, 최대 64px 사이에서 화면 폭에 비례해 여백을 매끄럽게 늘리고 줄입니다. 가운데 5vw가 화면 폭의 5퍼센트를 뜻하니, 창을 넓히면 여백도 따라 넓어지다가 64px에서 멈춥니다. 미디어쿼리 없이도 기기 크기에 맞춰 숨 쉬듯 변합니다.
03.8 아이콘과 글자 사이 틈
아이콘 옆에 글자를 붙일 때 마진을 하나하나 주면 방향이 바뀔 때마다 손이 갑니다. 부모에 gap 하나면 끝납니다.
.chip {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 10px;
}
inline-flex와 gap을 함께 쓰면 아이콘과 글자 사이가 6px로 일정하게 벌어집니다. 아이콘을 왼쪽에 두든 오른쪽에 두든 gap이 알아서 틈을 챙기니 방향에 따라 마진을 바꿔 줄 필요가 없습니다.
03.9 목록 항목 사이 숨쉬기
목록 항목이 다닥다닥 붙으면 어디까지가 한 줄인지 눈이 헷갈립니다. 항목마다 안쪽 여백을 주고 옅은 선으로 나눕니다.
.menu li {
padding: 12px 16px;
}
.menu li + li {
border-top: 1px solid #f0f0f0;
}
항목마다 위아래 12px 여백을 주면 손가락으로 누를 판이 넉넉해지고, 첫 항목을 뺀 나머지에만 얇은 윗선을 그으면 구분선이 위아래로 겹치지 않습니다. 여백이 먼저고 선은 거들 뿐입니다. 간격이 충분하면 선 없이도 항목이 구분되는 경우가 많아, 선은 정말 필요할 때만 얹는 편이 화면을 가볍게 유지합니다.
03.10 여백을 하나로 모으기
지금까지의 규칙을 한 화면에 얹으면 이렇게 맞물립니다. 값은 전부 변수에서 꺼내 쓰니 나중에 한 곳만 고치면 전체가 따라옵니다.
<section class="wrap">
<div class="callout">
<h3>안내</h3>
<p>여백이 관계를 말합니다.</p>
</div>
</section>
.callout {
display: flex;
flex-direction: column;
gap: var(--space-1);
padding: var(--space-3);
}
안쪽 gap이 제목과 설명을 묶고, 바깥 padding이 상자에 숨통을 틔우고, callout의 위아래 마진이 그 덩어리를 화면에서 도드라지게 합니다. 세 겹의 여백이 각자 다른 말을 하는 셈입니다. 여백은 남는 공간이 아니라 관계를 그리는 붓입니다. 어디를 비울지 정하는 일이 곧 무엇을 묶고 무엇을 강조할지 정하는 일과 같습니다. 값을 변수로 빼 두면 나중에 --space-3 하나만 바꿔도 화면 전체의 리듬이 한꺼번에 조율됩니다.