[공유] Vertical-align 파헤치기! – 2부

안녕하세요. 하이브랩 UI개발2팀 도재경, 우현주입니다.
Vertical-align 파헤치기 1부에 이어 2부를 시작하겠습니다!

1부에서 공부한 것을 바탕으로 좀 더 Vertical-align에 깊게 들어가보겠습니다.

‘Vertical-align’은 매우 유용하지만 작업하다보면 가끔씩 뜻대로 되지 않고 난장판이 되어 좌절하게 될 때가 있습니다.
예를 들어 수직 정렬을 위해 변경한 요소는 바뀌지 않고, 엉뚱한 요소가 변경된다던지 말이죠!

2부에서는 왜 ‘vertical-align’이 내 예상과 다른 방식으로 행동했는지 중점적으로 알아볼 것입니다.
‘Vertical-align’과 씨름해봅시다 😀

====================================================​

본문 목차

1. 왜 ‘Vertical-align’이 그런 방식으로 행동했는지

1.1. Line Box’s Baseline의 움직임

1.2. 인라인레벨요소 아래에 있을 수 있는 약간의 Gap(틈)

2. 추가내용​

2.1. Font 관련 참고자료

2.2. 반-행간(half-leading) 값이 소수점일 경우​

====================================================​

본문

1. 왜 ‘Vertical-align’이 그런 방식으로 행동했는지

특정 상황에서의 수직 정렬을 보다 자세히 살펴보겠습니다. 특히, 뭔가 내 생각대로 되지 않는 상황을 다루겠습니다.

본격적으로 들어가기 전에 아래의 설정을 봐주세요.
line_box
세가지 색상의 선이 있습니다. 라인박스의 상단과 하단은 빨간색으로, strut의 상단과 하단은 녹색, baseline은 파란색으로 표시되어 있습니다.
왜 ‘vertical-align’이 그런 방식으로 행동했는지를 알아보기 위해 계속 쓰일 설정이니 기억해주세요! 

 

1.1. Line Box’s Baseline의 움직임​

라인박스의 baseline은 변할 수 있습니다. (★★★★★) 
이것은 ‘vertical-align’을 작업할 때 일반적인 함정이고, 가장 혼란스럽게 하는 부분이기도 합니다.

라인박스 baseline의 위치는 그 라인의 모든 요소로부터 영향을 받습니다. 즉, 모든 요소의 vertical-align 값을 충족하고 라인박스의 높이를 최소화하는 곳에 baseline이 배치됩니다.

라인박스의 baseline이 움직이는 방식으로 한 요소가 정렬된다고 가정해봅시다.
대부분의 수직 정렬 값(top, bottom 제외)은 baseline을 기준으로 움직이기 때문에 해당 라인의 다른 모든 요소의 위치가 조정됩니다.

몇가지 예가 있습니다.

  • 만약 라인에 전체 높이를 꽉 채우는 큰 요소가 있다면, ‘vertical-align’은 이 요소에게 아무런 효과가 없습니다. 큰 요소의 위쪽과 아래쪽에 공간이 없기때문에 라인박스의 baseline을 기준으로 정렬하기위해서 라인박스의 baseline이 움직여야합니다. 작은 박스는 vertical-align:baseline입니다. 그림 왼쪽의 큰박스는 text-bottom으로 정렬되어 있고 오른쪽은 text-top으로 정렬되어 있습니다. 작은 박스와 함께 baseline이 올라가는 것을 볼 수 있습니다. 이런 baseline의 움직임은 큰 요소를 다른 ‘vertical-align’ 값들로 정렬할 때도 동일하게 나타납니다.

moving_linebox

  • ‘vertical-align’을 bottom(왼쪽)이나 top(오른쪽)으로 설정했을 때 조차도 baseline이 움직입니다. 이 때 baseline은 절대 관여해서는 안되는데 이건 좀 이상합니다…

moving_linebox2

  • 두개의 큰 요소를 한 라인에 놓고 수직 정렬하면 두 정렬을 모두 만족하는 곳으로 baseline이 움직입니다. 그런 다음 라인박스의 높이가 조정됩니다(왼쪽). 정렬으로 인해 라인박스의 가장자리를 넘어서지 않는 세 번째 요소를 추가하면, 라인박스의 높이나 baseline의 위치는 영향을 받지 않습니다(가운데). 그런데 만약 이 요소가 라인박스의 가장자리를 넘어선다면, 라인박스의 높이와 baseline이 다시 조정됩니다. 이런 경우에는 처음의 두 박스가 아래로 밀려납니다(오른쪽).
moving_linebox3
 

1.2. 인라인레벨요소 아래에 있을 수 있는 약간의 Gap(틈)

밑의 설정을 한번 봐주시길 바랍니다. 목록의 li 요소를 수직 정렬하려고 했을 때 일반적으로 볼 수 있는 것입니다.​inline_gap보시다시피 li 요소는 baseline을 기준으로 수직정렬 되어있습니다. baseline 아래에는 글자의 descenders*를 위한 약간의 공간이 있습니다. 이 것이 gap을 유발합니다.
(* descenders : 아래 나오는 2.1 Font 관련 참고자료 참조)
해결책은 그저 baseline을 비키게 하면 됩니다. 예를 들어 li 요소를 vertical-align:middle로 정렬하는 것처럼 말이죠.​

inline_gap2

text content가 있는 인라인블럭의 경우에는 이미 baseline이 움직였기 때문에 이런 gap이 발생하지 않습니다.
1부 vertical-align 속성값에 설명이 되어있지만 좀 더 명확한 이해를 위해 설명을 덧붙이겠습니다.

■ Inline-Block 요소의 baseline
다시 아래의 설정을 봐주세요.
margin의 경계는 빨간색 선으로 표시되고, border는 노란색 영역, padding은 초록색 영역, content영역은 파란색 영역으로 표시됩니다. 각 인라인블럭요소의 baseline은 파란색 선으로 표시됩니다.​ (Inline-block 요소의 라인박스 상단과 하단은 margin의 경계입니다)

inline-block_baseline

왼쪽부터 순서대로 text content(“c”)가 있는 인라인블럭요소, text content가 있고 overflow:visible이 아닌 인라인블럭요소, 그리고 text content가 없는(그러나 content 영역이 높이를 가지고 있는) 인라인블럭요소입니다.

Inline-block 요소의 baseline은 text content가 있는지 여부에 따라 다릅니다.

  • (사진의 왼쪽) text content가 있는 경우, 인라인블럭요소의 baseline은 normal flow에서 마지막 컨텐츠 요소의 baseline입니다. 마지막 요소의 baseline은 자체 규칙에 따라 결정됩니다.
  • (가운데) text content가 있지만 overflow 속성이 visible이 아닌 경우, baseline은 margin-box의 하단입니다. 그래서 인라인블럭요소의 하단과 같습니다.
  • (오른쪽) text content가 없는 경우, baseline은 위의 경우와 마찬가지로 margin-box의 하단입니다.

 

■ ​결론

일단 규칙을 알게되면 그리 어렵지 않습니다. 만약 ‘vertical-align’이 생각처럼 작동하지 않는다면, 아래의 질문들을 던져보세요.

  • 라인박스의 baseline과 상단 및 하단이 어디에 있는지
  • 인라인레벨요소의 baseline과 상단 및 하단이 어디에 있는지

이 질문들이 문제의 해결책을 찾는데 도움을 줄 것입니다. 😀 

====================================================​
‘Vertical-align’을 스터디 하는동안 많은 도움을 받은 사이트가 있습니다.
사이트에 들어가보시면 직접 vertical-align 값을 수정하며 움직임을 확인할 수 있습니다. 직접 움직임을 확인하며 본다면 이해가 더 쉬울 것입니다. 😀
* URL : http://christopheraue.net/2014/03/05/vertical-align/
====================================================​

 

2. 추가내용

2.1. Font 관련 참고자료

baseline

# baseline : 글자가 “앉아”있는 선​
# x-height : 소문자 x의 높이   (1부 vertical-align 속성값 중 middle을 설명할 때에 나온 ex는 x-height의 단위입니다.)
# ascender : x자 높이보다 위로 나오는 부분 또는 그것이 있는 활자 b, d, f, h 등​
# descender : x자 높이보다 아래로로 나오는 부분 또는 그것이 있는 활자 g, p, y 등​​

각기 다른 글꼴에 같은 font-size를 줘도 글꼴마다 font의 content 영역은 다르고, 같은 글꼴, 같은 font-size여도 브라우저마다 font의 content 영역이 약간씩 다릅니다. 
또한 baseline은 글꼴에 따라 각기 다르게 구현될 수 있습니다.​
그러나! 글꼴마다 정해진 baseline 등을 기준으로 vertical-align이 적용되는 메카니즘은 동일합니다 😀

 

2.2. 반-행간(half-leading) 값이 소수점일 경우

■​ 두 값중 하나를 홀수로 선언
line-height와 font-size 값이 둘 다 자연수라고 했을 시(line-height > font-size)​, (line-height – font-size) / 2 = 반-행간(half-leading) 값은 x나 x.5의 형태로 나오게 됩니다.
정수인 x로 떨어졌을 때에는 half-leading 값이 위 아래 균등하게 주어집니다. 

그러나 x.5의 형태로 나올 때에는 브라우저마다 적용방법이 다릅니다.

Chrome, Window Safari, Opera – 상단의 half-leading은 소수점을 내림하고, 하단의 half-leading은 소수점을 올림한 값이 주어집니다.
ex) half-leading 값이 3.5일 때 상단의 half-leading은 3, 하단의 half-leading은 4로 설정됩니다.
half-leading_Chrome

FireFox – 상단의 half-leading은 소수점을 올림하고, 하단의 half-leading은 소수점을 내림한 값이 주어집니다.
ex) half-leading 값이 3.5일 때 상단의 half-leading은 4, 하단의 half-leading은 3로 설정됩니다.

half-leading_FF

IE – 위 아래 half-leading이 내림한 값으로 균등하게 주어지는 대신 font의 content 영역을 1px 늘립니다.
ex) half-leading 값이 3.5일 때 위 아래 균등하게 half-leding은 3로 설정됩니다. 그리고 font의 content 영역이 1px 늘어납니다.
half-leading_IE

그런데! IE가 간혹 Chrome처럼 처리되는 경우도 있습니다. 
font-size를 1px 늘릴때 font의 content 영역도 1px이 늘어날 것 같지만 그렇지 않습니다. 1px 또는 2px씩 늘어납니다.
이 때 font-size를 1px 늘렸을 때 font의 content 영역이 2px 늘어난 바로 그 font-size에서 half-leading 처리방식이 Chrome과 동일합니다.
ex) font-size를 14px->15px으로 늘렸을 때 font의 content 영역이 2px 늘어났다면 font-size가 15px에서 처리방식이 Chrome과 동일합니다.

 

■ 두 값중 font-size만 선언했고, 크기에 따른 line-height가 적용되었는데 결과가 홀수
두 값중 font-size만 선언하고 크기에 따른 line-height가 적용되었을 때, line-height값이 소수점이 나올 수 있습니다.

Chrome, Window Safari, Opera – line-height값이 소수점이 나올 경우 소수점을 내림합니다. 그 후의 처리방식은 위와 동일합니다.

FireFox – line-height값이 소수점이 나올 경우 소수점을 반올합니다. 그 후의 처리방식은 위와 동일합니다.​

IE – line-height값이 소수점이 나올 경우 소수점을 반올림합니다. 그 후의 처리방식은 위와 동일합니다.
그런데! 또 font-size를 1px 늘렸을 때 font의 content 영역이 2px 늘어난 그 font-size에서는 line-height의 소수점을 내림합니다. 
소수점을 내림한 line-height를 적용하여 half-leading 값이 홀수가 나오면, FireFox의 처리방식처럼 상단의 소수점을 올림하고, 하단의 half-leading은 소수점을 내림한 값이 주어집니다.

IE는 간혹 규칙에 맞지 않는 결과가 나오기도 합니다. 제가 찾지 못한 규칙이 있는 걸까요.. IE는 주의가 필요합니다…

추가내용과 함께 보면 좋을 url입니다. 😀  
http://iamvdo.me/en/blog/css-font-metrics-line-height-and-vertical-align

====================================================

마치며

이상으로 vertical-align에 대한 Study였습니다. 
vertical-align에 대한 궁금증이 많이 해소되셨나요? 저는 baseline의 움직임을 이해하는데 조금 애를 먹었습니다. :'(
vertical-align에 가장 중요한 요소 baseline, line box, strut 을 꼭 기억해주세요!!! 

vertical-align 적용 중에 문제가 생길 시
라인박스 인라인레벨요소의 baseline과 상단하단이 어디에 있는지를 먼저 살펴보시면 좋을 듯 합니다.
라인박스의 baseline이 어디인지 모르겠다면 baseline을 눈에 보이게 하기 위해서 문제의 라인 시작에 글자[ex)”x”]를 추가해보세요. (1부의 익명 텍스트, 2부의 첫사진 참고) 글자가 아무런 정렬이 되어 있지 않다면, 기본적으로 baseline에 위치하게 됩니다! ​

긴 글 읽어주셔서 감사합니다. 😀 

====================================================

참고자료:
– ​https://www.w3.org/TR/CSS22/visudet.html#propdef-vertical-align
– ​http://christopheraue.net/2014/03/05/vertical-align
– https://en.wikipedia.org/wiki/Baseline_(typography)
– http://iamvdo.me/en/blog/css-font-metrics-line-height-and-vertical-align