CSS 여백에 대해 알아야 할 모든 것

게시 됨: 2022-03-10
빠른 요약 ↬ CSS의 여백은 언뜻 보기에는 간단해 보입니다. 요소에 적용하면 요소 주위에 공간을 형성하여 다른 요소를 밀어냅니다. 그러나 생각보다 한계가 있습니다.

CSS를 배울 때 대부분의 사람들이 가장 먼저 배운 것 중 하나는 CSS 상자 모델로 설명되는 CSS 상자의 다양한 부분에 대한 세부 정보였습니다. 상자 모델의 요소 중 하나는 상자 주변의 투명한 영역인 여백으로, 상자 내용에서 다른 요소를 밀어냅니다. margin-top , margin-right , margin-bottommargin-left 속성은 한 번에 네 가지 속성을 모두 설정하기 위한 약식 margin 과 함께 CSS1에서 바로 설명되었습니다.

여백은 상당히 복잡하지 않은 것처럼 보이지만 이 기사에서는 여백 사용과 관련하여 사람들을 혼란스럽게 만드는 몇 가지 사항을 살펴보겠습니다. 특히, 여백이 서로 어떻게 상호 작용하는지, 여백 축소가 실제로 어떻게 작동하는지 살펴볼 것입니다.

CSS 상자 모델

CSS 상자 모델의 일부에 대한 모든 기사와 마찬가지로 우리는 그것이 의미하는 바와 모델이 CSS 버전을 통해 어떻게 명확해졌는지 정의해야 합니다. 상자 모델 은 내용, 패딩, 테두리 및 여백과 같은 상자의 다양한 부분이 어떻게 배치되고 서로 상호 작용하는지 나타냅니다. CSS1에서 Box Model은 아래 이미지와 같은 ASCII 아트 다이어그램으로 자세히 설명되어 있습니다.

상자 모델의 아스키 아트 드로잉
CSS1의 CSS 상자 모델 묘사

상자의 각 면에 대한 4개의 여백 속성과 margin 약칭은 모두 CSS1에서 정의되었습니다.

CSS2.1 사양에는 상자 모델을 설명하는 그림이 있으며 다양한 상자를 설명하는 데 여전히 사용하는 용어도 정의합니다. 사양은 content box , padding box , border boxmargin box 를 설명하며, 각각 콘텐츠의 가장자리, 패딩, 테두리 및 여백으로 정의됩니다.

CSS 상자 모델 다이어그램
CSS2에서 CSS 상자 모델에 대한 디펙션

이제 작업 초안으로 레벨 3 상자 모델 사양이 있습니다. 이 사양은 상자 모델 및 여백의 정의에 대해 CSS2를 다시 참조하므로 이 문서의 대부분에서 사용할 CSS2 정의입니다.

점프 후 더! 아래에서 계속 읽기 ↓

여백 축소

여백을 정의한 CSS1 사양은 수직 여백도 축소 되도록 정의했습니다. 이 무너지는 행동은 그 이후로 마진과 관련된 좌절의 근원이었습니다. 초기에 CSS가 문서화 형식 언어로 사용되었다는 점을 고려하면 여백 축소가 의미가 있습니다. 여백 축소는 하단 여백이 있는 제목 다음에 상단 여백이 있는 단락이 올 때 해당 항목 사이에 큰 간격이 생기지 않는다는 것을 의미합니다.

여백이 축소되면 두 요소 사이의 공간이 두 여백 중 더 커지도록 결합됩니다. 더 작은 마진은 본질적으로 더 큰 마진 안에 들어갑니다.

여백은 다음과 같은 상황에서 무너집니다.

  • 인접 형제
  • 완전히 빈 상자
  • 상위 및 첫 번째 또는 마지막 하위 요소

이러한 시나리오에서 여백이 축소되는 것을 방지하는 항목을 살펴보기 전에 이러한 각 시나리오를 차례로 살펴보겠습니다.

인접 형제자매

여백 축소에 대한 나의 초기 설명은 인접한 형제 사이의 여백이 어떻게 축소되는지를 보여주는 것입니다. 아래에 언급된 상황을 제외하고 정상적인 흐름에서 두 개의 요소가 차례로 표시되는 경우 첫 번째 요소의 아래쪽 여백은 다음 요소의 위쪽 여백과 함께 축소됩니다.

아래 CodePen 예제에는 세 개의 div 요소가 있습니다. 첫 번째는 위쪽 및 아래쪽 여백이 50픽셀입니다. 두 번째는 상단 및 하단 여백이 20px입니다. 세 번째는 위쪽 및 아래쪽 여백이 3em입니다. 작은 위쪽 여백이 큰 아래쪽 여백과 결합되므로 처음 두 요소 사이의 여백은 50픽셀입니다. 3em은 두 번째 요소 하단의 20픽셀보다 크기 때문에 3em의 두 번째 두 요소 사이의 여백입니다.

Rachel Andrew의 펜 [마진: 인접 형제](https://codepen.io/rachelandrew/pen/OevMPo)를 참조하십시오.

펜 여백: Rachel Andrew의 인접 형제를 참조하십시오.

완전히 빈 상자

상자가 비어 있으면 위쪽 여백과 아래쪽 여백이 서로 접힐 수 있습니다. 다음 CodePen 예제에서 클래스가 비어 있는 요소의 위쪽 및 아래쪽 여백은 50픽셀이지만 첫 번째 항목과 세 번째 항목 사이의 간격은 100픽셀이 아니라 50픽셀입니다. 이는 두 개의 여백이 축소되기 때문입니다. 해당 상자에 무엇이든 추가하면(패딩 포함) 위쪽 및 아래쪽 여백이 사용되며 축소되지 않습니다.

Rachel Andrew의 펜 [여백: 빈 상자](https://codepen.io/rachelandrew/pen/JQLGMr)를 참조하십시오.

펜 여백: Rachel Andrew의 빈 상자를 참조하십시오.

상위 및 첫 번째 또는 마지막 하위 요소

이것은 특히 직관적으로 보이지 않기 때문에 사람들을 가장 자주 잡는 마진 붕괴 시나리오입니다. 다음 CodePen에는 래퍼 클래스가 있는 div 가 있으며 해당 div 에 빨간색으로 outline 을 지정하여 위치를 확인할 수 있습니다. 세 개의 자식 요소는 모두 50픽셀의 여백을 갖습니다. 그러나 첫 번째 항목과 마지막 항목은 래퍼의 가장자리와 같은 높이입니다. 요소와 래퍼 사이에 50픽셀의 여백이 없습니다.

Rachel Andrew의 펜 [여백: 첫째 및 마지막 자식의 여백](https://codepen.io/rachelandrew/pen/BgrKGp)를 참조하십시오.

펜 여백: Rachel Andrew의 첫 번째 및 마지막 자식의 여백을 참조하세요.

이는 자식의 여백이 부모의 여백과 함께 축소되어 부모 외부에서 끝나기 때문입니다. DevTools를 사용하여 첫 번째 자식을 검사하면 이것을 볼 수 있습니다. 강조 표시된 노란색 영역은 여백입니다.

상위 항목 외부에 표시되는 노란색으로 강조 표시된 여백이 있는 항목
DepvTools는 마진이 끝나는 곳을 확인하는 데 도움이 될 수 있습니다.

블록 여백만 축소

마지막 예는 여백 축소에 대해서도 강조합니다. CSS2에서는 세로 여백만 축소되도록 지정됩니다. 즉, 가로 쓰기 모드에 있는 경우 요소의 위쪽 및 아래쪽 여백입니다. 따라서 위의 왼쪽 및 오른쪽 여백이 축소되지 않고 래퍼 외부로 종료됩니다.

참고 : 여백은 단락 사이와 같이 블록 방향으로만 축소된다는 점을 기억할 가치가 있습니다.

여백 붕괴를 방지하는 것들

항목에 절대 위치가 있거나 떠 있는 경우 여백이 축소되지 않습니다. 그러나 위에서 설명한 여백이 무너지는 곳 중 하나를 만났다고 가정하면 이러한 여백이 무너지는 것을 어떻게 멈출 수 있습니까?

붕괴를 멈추는 첫 번째 것은 문제의 요소 사이에 무언가가 있는 상황입니다.

예를 들어, 내용이 완전히 비어 있는 상자는 테두리 또는 패딩이 적용된 경우 위쪽 및 아래쪽 여백을 축소하지 않습니다. 아래 예에서는 상자에 1px의 패딩을 추가했습니다. 이제 상자 위와 아래에 50픽셀의 여백이 있습니다.

Rachel Andrew의 펜 [여백: 패딩이 있는 빈 상자가 접히지 않음](https://codepen.io/rachelandrew/pen/gNeMpg)을 참조하십시오.

펜 여백 참조: Rachel Andrew의 패딩이 있는 빈 상자는 축소되지 않습니다.

여기에는 논리가 있습니다. 상자가 테두리나 패딩 없이 완전히 비어 있으면 본질적으로 보이지 않습니다. CMS에서 마크업에 삽입한 빈 단락 요소일 수 있습니다. CMS가 중복 단락 요소를 추가하는 경우 여백이 존중되기 때문에 다른 단락 사이에 큰 간격이 생기는 것을 원하지 않을 것입니다. 상자에 무엇이든 추가하면 이러한 간격이 생깁니다.

부모를 통해 축소되는 첫 번째 또는 마지막 자식의 여백에서도 유사한 동작을 볼 수 있습니다. 부모에 테두리를 추가하면 자식의 여백은 내부에 유지됩니다.

Rachel Andrew의 Pen [여백: 부모에게 테두리가 있는 경우 첫 번째 및 마지막 자식의 여백이 축소되지 않음](https://codepen.io/rachelandrew/pen/vqRKKX)을 참조하십시오.

펜 여백 참조: 부모에게 Rachel Andrew의 테두리가 있는 경우 첫 번째 및 마지막 자식의 여백이 축소되지 않습니다.

다시 한 번, 행동에는 몇 가지 논리가 있습니다. 시각적으로 표시되지 않는 의미론적 목적을 위한 래핑 요소가 있는 경우 표시에 큰 간격이 생기는 것을 원하지 않을 것입니다. 웹이 대부분 텍스트였을 때 이것은 많은 의미가 있었습니다. 디자인을 배치하기 위해 요소를 사용할 때 동작으로 덜 유용합니다.

블록 형식 컨텍스트 작성

새로운 BFC(Block Formatting Context)도 포함하는 요소를 통한 여백 축소를 방지합니다. 첫 번째와 마지막 자식의 예를 다시 살펴보고 여백이 래퍼 외부에 있고 래퍼에 display: flow-root 를 지정하여 새 BFC를 생성하면 여백이 내부에 유지됩니다.

Rachel Andrew의 Pen [Margins: a new Block Formatting Context contains margins](https://codepen.io/rachelandrew/pen/VJXjEp)를 참조하십시오.

펜 여백 보기: 새로운 블록 서식 컨텍스트에는 Rachel Andrew의 여백이 포함되어 있습니다.

display: flow-root 에 대해 자세히 알아보려면 내 기사 "CSS 레이아웃 및 블록 서식 컨텍스트 이해"를 읽어보세요. overflow 속성의 값을 auto 로 변경하면 동일한 효과를 얻을 수 있습니다. 이렇게 하면 새 BFC도 생성되기 때문입니다. 하지만 일부 시나리오에서는 원하지 않는 스크롤 막대가 생성될 수도 있습니다.

플렉스 및 그리드 컨테이너

Flex 및 Grid 컨테이너는 자식에 대한 Flex 및 Grid 서식 컨텍스트 를 설정하므로 블록 레이아웃에 대해 서로 다른 동작이 있습니다. 이러한 차이점 중 하나는 여백이 축소되지 않는다는 것입니다.

“플렉스 컨테이너는 콘텐츠에 대한 새로운 플렉스 형식화 컨텍스트를 설정합니다. 이것은 블록 레이아웃 대신 플렉스 레이아웃이 사용된다는 점을 제외하고는 블록 서식 컨텍스트를 설정하는 것과 같습니다. 예를 들어, float는 플렉스 컨테이너에 침입하지 않으며 플렉스 컨테이너의 여백은 콘텐츠 여백과 함께 축소되지 않습니다.”

— 플렉스박스 레벨 1

위의 예를 사용하여 래퍼를 플렉스 컨테이너로 만들고 flex-direction: column 항목을 표시하면 여백이 래퍼에 포함된 것을 볼 수 있습니다. 또한 인접한 플렉스 항목 사이의 여백은 서로 축소되지 않으므로 플렉스 항목 사이에 100픽셀, 항목의 상단과 하단에 총 50픽셀이 생깁니다.

Rachel Andrew의 펜 [여백: 플렉스 항목의 여백이 축소되지 않음](https://codepen.io/rachelandrew/pen/mZxreL)을 참조하십시오.

펜 여백 참조: Rachel Andrew가 플렉스 항목의 여백을 축소하지 않습니다.

귀하의 사이트에 대한 마진 전략

여백 축소로 인해 사이트의 여백을 일관된 방식으로 처리하는 것이 좋습니다. 가장 간단한 방법은 요소의 상단 또는 하단에만 여백을 정의하는 것입니다. 그런 식으로 여백이 있는 쪽이 항상 여백이 없는 쪽과 인접하게 되므로 여백 축소 문제가 너무 자주 발생해서는 안 됩니다.

참고 : Harry Roberts는 여백을 한 방향으로만 설정하는 것이 좋은 생각이며, 여백 축소 문제를 해결하기 위한 것이 아니라 이유를 자세히 설명하는 훌륭한 게시물을 가지고 있습니다.

이 솔루션은 부모를 통해 축소되는 자식의 여백으로 인해 발생할 수 있는 문제를 해결하지 못합니다. 그 특정 문제는 덜 일반적이며 문제가 발생하는 이유 를 알면 솔루션을 찾는 데 도움이 될 수 있습니다. 이에 대한 이상적인 솔루션은 display: flow-root 를 제공하는 것입니다. 이전 브라우저에 대한 폴백으로 overflow 로를 사용하여 BFC를 만들거나 부모를 플렉스 컨테이너로 바꾸거나 단일 픽셀의 패딩을 도입할 수도 있습니다. 기능 쿼리를 사용하여 display: flow-root 지원을 감지할 수 있다는 것을 잊지 마십시오. 따라서 이전 브라우저만 덜 최적의 수정을 받을 수 있습니다.

대부분의 경우 여백이 축소(또는 축소)되지 않은 이유를 아는 것이 핵심이라는 것을 알았습니다. 그런 다음 사례별로 처리하는 방법을 알아낼 수 있습니다. 무엇을 선택하든 해당 정보를 팀과 공유하십시오. 꽤 자주 마진 붕괴는 약간 미스터리하므로 이에 대응하기 위해 일을 하는 이유가 분명하지 않을 수 있습니다! 코드의 주석은 많은 도움이 됩니다. 이 기사에 링크하고 여백 축소 지식을 공유하는 데 도움을 줄 수도 있습니다.

나는 이 기사를 마진과 관련된 몇 가지 다른 정보로 마무리 지을 것이라고 생각했습니다.

백분율 여백

CSS에서 백분율을 사용할 때는 어떤 것의 백분율이어야 합니다. 백분율을 사용하여 설정된 여백(및 패딩)은 항상 상위 인라인 크기(가로 쓰기 모드의 너비)의 백분율입니다. 이것은 백분율을 사용할 때 요소 전체에 동일한 크기의 패딩이 있음을 의미합니다.

아래 CodePen 예에서 너비가 200픽셀인 래퍼가 있고 내부에 10% 여백이 있는 상자가 있고 여백은 모든 면에서 20픽셀(200의 10%)입니다.

Rachel Andrew의 펜 [여백: 백분율 여백](https://codepen.io/rachelandrew/pen/orqzrP)을 참조하십시오.

펜 여백: Rachel Andrew의 백분율 여백을 참조하십시오.

흐름 기준 세계의 여백

우리는 이 기사 전체에서 수직 여백에 대해 이야기했지만 현대 CSS는 물리적인 방식보다는 상대적인 흐름으로 사물을 생각하는 경향이 있습니다. 따라서 수직 여백에 대해 이야기할 때 실제로는 블록 차원의 여백에 대해 이야기하는 것입니다. 이 여백은 가로 쓰기 모드에서는 위쪽과 아래쪽이지만 왼쪽에서 오른쪽으로 쓰는 세로 쓰기 모드에서는 오른쪽과 왼쪽이 됩니다.

논리적인 흐름 상대 방향으로 작업하면 상단과 하단보다 블록 시작과 블록 끝을 이야기하는 것이 더 쉬워집니다. 이를 쉽게 하기 위해 CSS는 논리적 속성 및 값 사양을 도입했습니다. 이것은 흐름 상대 속성을 물리적 속성에 매핑합니다.

여백의 경우 다음 매핑을 제공합니다(영어 또는 왼쪽에서 오른쪽 텍스트 방향의 다른 가로 쓰기 모드로 작업하는 경우).

  • margin-top = margin-block-start
  • margin-right = margin-inline-end
  • margin-bottom = margin-block-end
  • margin-left = margin-inline-start

또한 한 번에 두 블록 또는 두 블록을 모두 인라인으로 설정할 수 있는 두 개의 새로운 속기가 있습니다.

  • margin-block
  • margin-inline

다음 CodePen 예제에서는 이러한 흐름 상대 키워드를 사용한 다음 상자의 쓰기 모드를 변경했습니다. 여백이 물리적인 위쪽, 오른쪽, 아래쪽 및 왼쪽에 묶이지 않고 텍스트 방향을 따르는 방식을 볼 수 있습니다.

Rachel Andrew의 펜 [여백: 흐름 상대 여백](https://codepen.io/rachelandrew/pen/BgrQRj)를 참조하십시오.

Rachel Andrew의 Pen Margins: flow relative margins를 참조하십시오.

MDN의 논리적 속성 및 값에 대한 자세한 내용이나 Smashing Magazine의 "논리적 속성 및 값 이해" 기사에서 읽을 수 있습니다.

마무리하자면

이제 마진에 대해 알아야 할 대부분의 내용을 알게 되었습니다! 간단히 말해서:

  • 마진 붕괴는 일입니다. 왜 발생하고 언제 발생하지 않는지 이해하면 발생할 수 있는 문제를 해결하는 데 도움이 됩니다.
  • 한 방향으로 여백을 설정하면 많은 여백 관련 골칫거리만 해결됩니다.
  • CSS의 모든 것과 마찬가지로 결정한 사항을 팀과 공유하고 코드에 주석을 추가하세요.
  • 웹이 쓰기 모드에 구애받지 않는 방향으로 이동함에 따라 물리적인 상단, 오른쪽, 하단 및 왼쪽이 아닌 블록 및 인라인 치수를 생각하는 것이 도움이 될 것입니다.