가까이 있는 것끼리 한패로 읽힌다는 규칙 하나만 손에 쥐어도 화면 정리가 훨씬 수월해집니다. 선을 긋거나 상자를 두르기 전에 여백의 거리만으로 묶고 나누는 방법을, CSS 코드로 하나씩 만져 보겠습니다.
07.1 거리로 관계를 말하기
제목과 설명이 한 덩어리인데도 간격이 똑같으면 어디까지가 한 묶음인지 흐려집니다. 관련된 것은 바짝, 남남인 것은 넉넉히 벌리는 것이 기본입니다.
.card {
display: flex;
flex-direction: column;
gap: 16px;
}
모든 줄이 16px로 똑같이 벌어지면 제목과 설명이 각자 놀게 됩니다. 안쪽은 좁히고 묶음 사이만 벌립니다.
.group {
display: flex;
flex-direction: column;
gap: 4px;
}
.group + .group {
margin-top: 20px;
}
같은 묶음 안은 4px로 붙고 묶음끼리는 20px로 떨어집니다. 눈은 이 간격 차이만 보고도 경계를 알아챕니다.
07.2 폼 필드를 라벨과 한 몸으로
입력 폼에서 라벨이 위 칸에도 아래 칸에도 똑같은 거리로 떠 있으면, 이 라벨이 누구 것인지 헷갈립니다. 라벨은 자기 입력칸에 붙이고 필드끼리는 벌립니다.
.form {
display: flex;
flex-direction: column;
gap: 20px;
}
.field {
display: flex;
flex-direction: column;
gap: 6px;
}
라벨과 입력칸은 6px로 딱 붙고 필드 사이는 20px로 벌어집니다. 라벨이 아래 칸을 향해 기울어 보이니 짝이 분명해집니다.
<div class="field">
<label for="email">이메일</label>
<input id="email" type="email">
</div>
마크업도 라벨과 입력을 같은 상자에 넣어 두면, 스타일과 구조가 같은 이야기를 하게 됩니다.
07.3 카드 안팎의 간격을 분리하기
여러 카드를 늘어놓을 때 카드 안 여백과 카드 사이 간격이 뒤섞이면 리듬이 무너집니다. 안쪽 패딩과 바깥 간격을 따로 잡습니다.
.list {
display: flex;
flex-direction: column;
gap: 12px;
}
.card {
padding: 20px;
border-radius: 10px;
background: #fff;
}
카드 사이는 gap이 12px로 관리하고 카드 속 숨통은 패딩 20px가 맡습니다. 두 값을 나눠 두면 한쪽을 손봐도 다른 쪽이 흔들리지 않습니다.
07.4 grid로 묶음을 격자에 앉히기
가로로 흩어진 항목들도 격자에 올리면 행과 열이 각각 하나의 흐름으로 읽힙니다. 그리드의 gap이 근접성을 대신 관리해 줍니다.
.tiles {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
세 열이 같은 폭으로 서고 칸 사이가 고르게 16px로 벌어집니다. 항목마다 margin을 따로 줄 필요 없이 격자가 거리를 통일합니다.
@media (max-width: 600px) {
.tiles {
grid-template-columns: 1fr;
}
}
좁은 화면에서는 한 열로 접혀 세로로 쌓입니다. 간격 규칙은 그대로 두고 열 수만 바꾸면 됩니다.
07.5 구분선 대신 여백으로 나누기
영역을 나눌 때 선부터 긋고 싶어지지만, 여백만으로 충분한 경우가 많습니다. 선이 줄면 화면은 그만큼 조용해집니다.
.section + .section {
margin-top: 40px;
}
.section h2 {
margin-bottom: 12px;
}
섹션 사이를 40px로 크게 벌리면 굳이 줄을 긋지 않아도 문단이 갈립니다. 제목과 본문은 12px로 붙여 한 묶음임을 알려 줍니다.
07.6 메뉴 항목을 무리 짓기
내비게이션에 항목이 많으면 성격이 다른 것끼리 거리를 벌려 자연스럽게 무리를 만듭니다. 로그인 같은 별개 동작은 본 메뉴에서 떼어 놓습니다.
.nav {
display: flex;
align-items: center;
gap: 24px;
}
.nav .login {
margin-left: auto;
}
메뉴 항목은 24px로 나란히 서고 로그인은 margin-left auto로 반대편 끝으로 밀려납니다. 거리가 벌어진 순간 이건 다른 무리라고 읽힙니다.
07.7 여백 토큰으로 리듬 통일하기
간격 값을 매번 손으로 정하면 4px, 5px, 6px처럼 미묘하게 어긋난 값이 섞입니다. 몇 개의 정해진 값만 쓰도록 변수로 묶습니다.
:root {
--space-1: 4px;
--space-2: 8px;
--space-4: 16px;
--space-6: 24px;
}
.field {
gap: var(--space-1);
}
.form {
gap: var(--space-6);
}
모든 간격이 이 네 값 안에서만 골라 쓰이니 화면 전체의 리듬이 한 박자로 맞습니다. 나중에 촘촘함을 조절할 때도 변수 하나만 바꾸면 됩니다.
07.8 목록에 얇은 선 하나만 얹기
여백만으로 부족할 때는 아주 얇은 선을 더합니다. 다만 항목마다 상자를 두르지 말고, 사이에만 실선 하나를 긋습니다.
.menu li {
padding: 12px 16px;
}
.menu li + li {
border-top: 1px solid #e5e7eb;
}
인접 형제 선택자로 두 번째 항목부터만 위에 선을 그으니, 첫 항목 위와 마지막 항목 아래에는 불필요한 선이 남지 않습니다. 여백이 리듬을 잡고 얇은 선이 경계를 살짝 거들 뿐입니다.
07.9 관계를 정렬로 한 번 더 묶기
같은 무리는 시작선이 같아야 한 덩어리로 읽힙니다. 아이콘과 텍스트가 짝일 때 세로 중심을 맞춰 하나로 붙입니다.
.item {
display: flex;
align-items: center;
gap: 8px;
}
.item .label {
flex: 1;
}
아이콘과 라벨이 8px 간격으로 붙어 한 쌍이 되고, 라벨이 남는 폭을 채워 여러 줄의 시작선이 한 세로선에 모입니다. 거리와 정렬이 함께 작동하면 묶음이 더 또렷해집니다.
07.10 한 화면에 모아 보기
지금까지의 거리 규칙을 프로필 카드 하나에 얹으면 이렇게 정리됩니다. 선 하나 없이 여백만으로 두 묶음이 갈립니다.
<div class="card">
<div class="group">
<h3>김서연</h3>
<p>프로덕트 디자이너</p>
</div>
<div class="group">
<p>서울, 대한민국</p>
<p>가입 2년차</p>
</div>
</div>
이름과 직함이 한 묶음, 지역과 연차가 또 한 묶음으로 붙고 두 묶음 사이만 벌어집니다. 읽는 사람은 어디까지가 한 정보인지 애써 구분하지 않아도 됩니다.
07.11 정리
근접성은 거리로 관계를 말하는 문법입니다. 붙이면 한패, 떼면 남남이라는 단순한 신호가 선이나 상자보다 먼저 읽힙니다. 간격 값을 몇 개로 묶어 두고 안쪽은 좁게 바깥은 넓게만 지켜도, 화면은 저절로 정돈됩니다.