코딩하는 김딸기
네거티브마진 본문
네거티브 마진 negative margins
margin 속성은 CSS에서 요소의 외부 여백을 제어하는 강력한 도구입니다. 이 속성의 특별한 점은 요소의 시각적 표현과 실제 차지하는 공간을 독립적으로 조작할 수 있다는 것입니다. 특히 네거티브 마진(음수 마진)을 사용하면 요소의 레이아웃을 더 유연하게 조정할 수 있습니다.
마진은 실제요소가 실제로 차지하는 공간과 눈에 보여지는 부분을 별도로 관리할수 있게 하는 속성
실제 차지하는 공간은 증가했지만 이미지의 보이는 영역은 증가하지 않았다
실제 차지하는 부분이 깎인것이라고 브라우저를 속임
-그러나 이미지의 보여지는 부분은 그대로이므로 마치 이미지가 위로 올라간것처럼 보이게 한다. 실제
로 이미지의 위치이동은 없다
-위아래 마진을 음수로 하면 위아래 이미지가 차지하는 공간은 50만큼깍인 것이지만 외관상 이미지는 깍이지 않으므로 이미지는 위아래 기준으로 50씩 삐져나간 것으로
보인다
-삐져나간 영역은 시각적으로 보이기는 하지만 차지하는 영역은 없는것으로 한다
-차지하는 공간이 변할뿐 보이는 부분은 그대로이다
-왼쪽 기준 차지하는 공간은 증가하지만 실제로 이미지의 보이는 영역은 증가하지 않는다
-> 이때문에 (증가한 차지영역-보이는 이미지 영역) 만큼이 여백으로 보인다
-왼쪽 기준 차지하는 공간은 감소하지만 실제로 이미지의 보이는 영역은 감소하지 않는다
-> 이때문에 (보이는 이미지 영역- 증가한 차지영역 ) 만큼이 왼쪽으로 삐져나간것처럼 보인다
positive 마진의 특징
- 공간 확장: 마진은 요소가 차지하는 실제 공간을 확장합니다.
- 위치 불변: 요소의 원래 위치(좌표)는 변하지 않습니다.
- 시각적 이동 효과: 확장된 공간으로 인해 시각적으로 이동한 것처럼 보입니다.
negative 마진의 특징
- 공간 축소: 네거티브 마진은 요소가 차지하는 실제 공간을 축소시킵니다.
- 위치 불변: 요소의 원래 위치(좌표)는 변하지 않습니다.
- 시각적 이동 효과: 축소된 공간으로 인해 시각적으로 이동한 것처럼 보입니다.
이제 margin-left뿐 아니라 margin-top, margin-bottom, margin-right 속성도 이 네거티브 마진을 적용해보고 어떤 일이 일어나는지 파악 해보시기 바랍니다. 결과는 다르지만, 그 원리는 동일합니다.
텍스트창에 마우스를 올리면 텍스트 창 테두리밖에 검은 그림자가 생기며 좌우가 100px만큼 튀어나가 보이는 효과
마진의 %단위 사용 margin % unit
margin속성에 대한 값을 %단위로 지정하는 기법
margin속성 값을 %단위로 지정하면 컨테이닝 블록의 너비를 기준으로 백분율 계산됨
margin-top, margin-bottom과 같이 상하단 여백을 설정 할때에도 %단위를 사용하면 언제나 컨테이닝 블록의 너비를 기준에서의 백분율이 됨
-부모자식간의 마진도 겹침
마진 병합 margin collapsing
마진 병합: 인접한 블록 레벨 요소의 수직 마진을 합쳐 더 큰 마진 하나만 적용하는 CSS 규칙
이 규칙은 요소 간의 중복된 공간을 제거하여 레이아웃을 최적화 하고 시각적인 안정성을 제공
->요소간의 간격이 자연스럽게 생성될 수 있도록 의도된 동작
마진 병합이 일어나는 조건
- 인접한 블록 레벨 요소들 사이에서 발생
- 수직 방향(top과 bottom)의 마진에서만 발생
형제간 마진 병합 현상
<div class="parent">
<div class="child a">A</div>
<div class="child b">B</div>
</div>
.child {
display: block; /* 블럭 레벨 요소 */
background-color: orange;
}
.child.a {
margin-bottom: 40px;
}
.child.b {
margin-top: 20px;
}
.child.a의 margin-bottom: 40px과 .child.b의 margin-top: 20px이 만나, 값이 누적되면서 총 60px의 요소간 간격이 형성 될것이라 생각할 수 있다.
하지만 실제 동작은 다름.-> 마진 병합의 규칙에 의해 해당 요소간 사이 마진은 40px
( 형제 간 마진 병합 현상 발생)
.child를 의도적으로 인라인 레벨 요소로 변경하여 마진 병합의 조건에 들어가지 않게 조작 가능
.child {
display: inline-block; /* 블럭 레벨 요소가 아니게 변경 */
background-color: orange;
}
.child.a {
margin-bottom: 40px;
}
.child.b {
margin-top: 20px;
}
부모와 자식 간의 마진 병합
마진 병합이 일어나는 조건에 의해, 부모 요소와 첫 번째 또는 마지막 자식 요소 간에도 마진 병합이 발생할 수 있습니다.
<div class="parent">
<div class="child a">A</div>
<div class="child b">B</div>
</div>
body {
background-color: #ddd;
}
.parent {
background-color: white;
display: block; /* 블럭 레벨 요소 */
margin-top: 0;
margin-bottom: 0;
}
.child {
display: block; /* 블럭 레벨 요소 */
background-color: orange;
}
.child.a {
margin-top: 60px;
margin-bottom: 60px;
}
.child.b {
margin-top: 60px;
margin-bottom: 60px;
}
.child.a의 상단 마진과 부모 요소인 .parent의 상단 마진이 병합되어, 큰 쪽의 마진인 60px로 적용 됨을 확인 할 수 있습니다. 조건에 의해 마진 병합 규칙대로 동작이 된 것이지만, 해당 결과는 부자연스럽게 느껴지기도 합니다.
일반적으로 형제간 마진병합은 굳이 해결해야하는 문제가 아니지만 부모와 자식간의 마진 병합 현상은 해결 해야하는 문제로 바라 보기도 합니다.
문제 해결 방법
조건을 깨기
- 부모 요소 또는 자식 요소중 어느 하나라도 블록 레벨 요소가 아니라면 마진 병합 현상은 발생되지 않습니다.
- 부모 요소에게 border, padding등의 실제 공간을 차지하는 경계면을 만들어 낸다면 부모 요소와 자식 요소가 해당 경계면을 기준으로 명확히 구분되게 됩니다. 즉, 부모와 자식간 마진 병합 현상은 발생되지 않습니다.
- 부모 요소와 자식 요소 사이에 table요소를 넣어 마진 병합이 일어나지 않게 방해합니다. table요소는 내부에 아무런 콘텐츠를 넣지 않아도 활성화 되기 때문에 마진 병합을 방해하는 트릭으로 쓰입니다. 보통 실제 table요소를 HTML상에 직접 작성하지는 않고 아래와 같은 기법을 활용합니다.
.clearfix::before,
.clearfix::after {
content: ' ';
display: table
}
부모 요소에게 적용하는 클래스입니다. 가상 요소중 콘텐츠를 생성할 수 있는 ::before, ::after를 이용하여 부모 요소의 시작과 끝에 빈 table요소를 넣습니다. 테이블 요소는 일반적인 블록 레벨 요소와는 독립적인 박스 모델을 가집니다. table요소는 자체적인 레이아웃 알고리즘을 사용하며, 마진 병합을 방해하는 용도로 쓰인 케이스입니다. 이는 오래된 방식으로서 현 시점에 주된 해결 방법은 아닙니다.
블록 포맷팅 컨텍스트 이용 (추천)
부모 요소에 display: flow-root를 적용하여 마진 병합 문제를 해결 할 수 있습니다. display: flow-root도 블록 레벨 요소라고 볼 수 있지만, 새로운 블록 포맷팅 컨텍스트를 만들어 낸다는 차이가 있습니다.
자식 요소의 마진을 부모 요소의 내부로 온전히 포함하는 요소를 만드는 개념입니다.
부모와 자식간 마진 병합을 의도적으로 해결가능
-h1의 margin top이 div에 들어가 의도치 않은 결과를 낳을 수 있음
블록 포맷팅 컨텍스트는 다른 방법으로도 생성 가능-> 대표적인 방법으로 부모 요소에게 overflow: hidden을 지정
overflow를 초기값 visible이 아닌 값으로 설정하게 되면, 부모 요소의 바깥과 부모 요소의 내부를 확실히 격리 시키는 개념으로 만들어지게 됩니다. 이 방법으로도 마진 병합 현상이 해결 되지만, overflow: hidden의 원래 용도인, 넘처 흐른 자식 콘텐츠를 잘라내는 효과가 나올 수 있어 주의가 필요합니다.
display: flow-root가 존재하지 않는경우-> 상하 마진 병합 발생

display: flow-root가 존재하는경우-> 마진 병합 발생하지 않음

네거티브 마진과 마진 병합
네거티브 마진은 마진 병합 현상과 결합될 때 두 가지 주요 효과를 동시에 일으킵니다.
- 네거티브 마진이 적용된 요소의 공간 축소.
- 마진 병합 규칙에 의해 큰 쪽의 마진 하나가 요소간 간격으로 적용됨.
가상 요소 셀렉터
pseudo element selector
다른이름: 의사 요소, 유사 요소, 슈도 요소
가상이라는 단어가 보통 Virtual이라는 영어 단어의 뜻으로 많이 쓰이지만, CSS에서의 가상이라는 단어는 사실 Pseudo 영어 단어를 뜻합니다.
실제 HTML 요소가 아니라 CSS를 통해 선택되거나 생성되는 '진짜인척 하는 가짜 요소'임을 뜻합니다. 실제 HTML 문서 트리에 존재하지 않습니다. 실제 존재하고 있는 특정 HTML 요소 자체를 선택하는 가상 클래스 셀렉터와는 목적성이 다릅니다.
가상 요소는 :: 콜론 두개로 시작 됩니다.
- 선택의 용도로 활용
마크업을 변경하지 않고도 문서의 특정 부분만을 선택하여 스타일을 적용할 수 있습니다. 주요 가상 요소는 다음과 같습니다.
- ::first-line : 텍스트의 첫 번째 줄을 선택합니다.
- ::first-letter : 텍스트 블록의 첫 번째 글자를 선택합니다.
- ::selection : 사용자가 커서로 선택한 문서의 부분을 나타냅니다.
적용 가능한 CSS 속성에 제한이 있는 경우가 많습니다. 일반적인 방법으로 선택하기 어려운 부분도 이 가상 요소로 선택할 수 있는 방법을 제공해주어 스타일을 수정 할 수 있게 도움을 주는 경우가 존재합니다.
- 생성의 용도로 활용
마크업을 변경하지 않고도 문서의 특정 부분에 새로운 요소를 생성 할 수 있습니다. ::before, ::after 두가지 가상 요소가 제공됩니다.
<div class="wow">
CONTENTS
</div>
/* ::before
내부 콘텐츠 이전에 새로운 가상 요소를 추가할 수 있습니다.
(.wow 요소의 첫 자식으로 생성)
*/
.wow::before {
content: 'BEFORE | ';
}
/* ::after
내부 콘텐츠 이후에 새로운 가상 요소를 추가할 수 있습니다.
(.wow 요소의 마지막 자식으로 생성)
*/
.wow::after {
content: ' | AFTER';
}
이렇게 작성하면,
<div class="wow">
<!-- 내부 콘텐츠 이전(before) 위치인 이 라인에 'BEFORE | '라는 콘텐츠가 생성됩니다. -->
CONTENTS
<!-- 내부 콘텐츠 이후(before) 위치인 이 라인에 ' | AFTER'라는 콘텐츠가 생성됩니다. -->
</div>
즉 BEFORE | CONTENTS | AFTER 이 완성되게 됩니다.
이렇게 만들어진 가상 요소는 다음과 같은 주의 사항이 있습니다.
생성되는 가상 요소 ::before, ::after의 사례
- 인용 부호 추가: 텍스트 콘텐츠에 시각적 강조를 줍니다.
- 툴팁 만들기: 추가 정보를 제공하는 인터랙티브 요소를 만듭니다.
- 아이콘 추가: 텍스트에 작은 아이콘을 쉽게 추가할 수 있습니다.
- 카운터 사용: 자동 번호 매기기 기능을 구현합니다.
- 장식적 요소 추가: 불필요한 마크업을 늘리지 않고 시각적 장식을 더합니다.
이러한 기법들은 HTML 구조를 변경하지 않고도 다양한 시각적, 기능적 요소를 추가할 수 있게 해줍니다. 이는 코드의 유지보수성을 높이고, 디자인과 기능을 분리하는 데 도움이 됩니다. 또한, 이러한 방식으로 추가된 요소들은 대부분 순수하게 장식적이거나 부가적인 정보를 제공하므로, 접근성이나 검색엔진 최적화에 부정적인 영향을 주지 않습니다. 마크업 구조가 깔끔하게 유지됨으로 유지보수성도 높아지게 됩니다. 시멘틱한 마크업 구조로 발전 시키기 위해 꼭 필요한 기법입니다.