CSS 수직/수평 가운데 정렬 구현

HTML 페이지에서 요소의 정렬은 가장 간단하게는 텍스트의 왼쪽, 가운데, 오른쪽 정렬부터, HTML 페이지 내용 전체를 가운데 배치하는 것 까지 다양합니다.

그 중에서 조금 더 까다로운 방법은 수직으로 가운데 정렬을 하는 것입니다. 기본적으로 웹 컨텐츠의 흐름이 가로를 기준으로 배치가 되기 때문에 수직 방향의 가운데 정렬은 여러가지 제약이 있습니다.

정렬 방법은 어떤 요소와 위치 속성을 기준으로 하느냐에 따라 달라지며, 특성에 따라 적절한 정렬 방법을 사용해야 합니다.

수직 정렬

1. vertical-align 속성으로 정렬

요소에 수직 정렬 속성을 사용할 수 있는 태그는 "vertical-align" 속성 값을 "middle" 로 지정해 수직으로 가운데 정렬을 할수 있습니다.

대표적인 "vertical-align" 을 지원하는 태그는 테이블 태그의 셀 태그인 "<td>" 태그입니다.

"<td>" 태그에 속성으로 "vertical-align: middle;" 을 추가하면 테이블 셀 안의 내용들이 수직 가운데 정렬이 됩니다.

다만 테이블 태그는 레이아웃을 만드는 용도로는 사용하면 안되기 때문에 레이아웃의 수직 정렬을 구현하기 위해 테이블 태그를 사용하는 것은 피해야 합니다.

테이블 셀 수직 정렬

인라인 속성을 가진 요소에 "vertical-align" 속성을 사용할 경우, "line-height" 높이 범위 안에서 수직 정렬 위치를 지정합니다.

인라인 요소에 사용할 수 있는 "vertical-align" 정렬 속성 값은 "top", "middle", "bottom", "baseline", "sub", "super", "text-top", "text-bottom" 입니다.

인라인 요소의 수직 정렬 속성인 "vertical-align" 은 다음과 같이 적용됩니다.

속성 값에 따라 수직으로 가운데 정렬을 하는 기준선이 다르기 때문에 인라인 요소를 수직으로 정렬할 때는 주의해야 합니다.

인라인 수직 정렬 속성 값

글자 크기는 0.875em(14px), 인라인 행 높이는 테두리 선을 포함해 20px 입니다. 인라인으로 정렬되는 이미지는 30x30px 크기로 인라인 크기보다 약간 크기해서 수직 정렬이 미치는 영향을 확인할 수 있도록 했습니다.

  • "top", "middle", "bottom", "baseline"은 베이스 라인을 기준으로 정렬됩니다.
  • "sub", "super", "text-top", "text-bottom" 은 인라인 영역 상단과 하단(테두리 선 제외한 "line-height" 높이 영역의 상단과 하단)을 기준으로 정렬됩니다.

참고로 테이블 셀에 적용하는 속성 값은 "top", "middle", "bottom" 만이 적용 가능하며, 나머지 수직 정렬 속성 값은 인라인 요소에만 적용됩니다.

2. line-height 속성으로 정렬

"display" 속성이 "block", "inline-block" 으로 지정된 박스 블록 요소에는 "line-height" 속성을 적용해  박스 안에 있는 인라인 요소, 또는 인라인 태그에 행 높이를 적용할 수 있습니다.

행의 높이는 인라인으로 배치된 텍스트의 크기, 또는 요소의 크기와는 무관하게 행 단위의 높이 값으로 정해지며, 행 높이 보다 큰 텍스트, 또는 요소는 행 들 사이가 겹쳐지게 됩니다.

요소를 배치할 때 부모 요소의 높이만큼 행 높이를 "line-height" 값으로 지정하면 인라인 속성인 요소가 수직으로 가운데 정렬이 됩니다.

다음과 같은 블록 요소에 

<div class="inlineblock">
  <span>line-height 수직 정렬</span>
  <img class="inlineimg vtextbottom" src="./backup/773/img/noimage.svg">
</div>

"line-height" 로 수직 정렬이 되도록 다음과 같이 클래스를 적용하면

.inlineblock{
    display: inline-block;
    position: relative;
    width: 200px;
    height: 200px;
    background-color: #a88;
    line-height: 200px;
}

다음과 같이 수직 가운데 정렬이 됩니다.

line-height 속성으로 블록 요소 안의 인라인 요소에 수직 정렬을 적용

단, 내부 인라인 요소가 2줄 이상으로 표시되는 경우, 2번째 줄 이후의 내용이 부모 요소의 바깥에 표시되는 문제가 있으므로, 짧은 인라인 요소를 수직으로 가운데 정렬할 때만 제한적으로 사용해야 합니다.

2줄 이상 인라인 요소에 line-height를 잘못 적용한 예

3. table 속성으로 정렬

"display" 속성 중 table 속성은 부모 요소의 자식 요소들이 테이블 셀 처럼 그리드 구조로 배치되도록 합니다.

table 속성을 가진 요소의 자식 요소들에는 "display" 속성으로 "table-cell" 속성을 부여할 수 있으며, 테이블의 셀 태그와 같은 특징을 가지도록 할 수 있습니다.

테이블 셀 태그의 수직 정렬 속성인 "vertical-align" 속성 또한 사용 가능하기 때문에 테이블 형태의 그리드 레이아웃을 만들 때 수직 정렬을 구현하는 용도로 사용할 수 있습니다.

또한 테이블 셀 태그(<td>)와 마찬가지로 각각의 셀은 높이 값을 가지는 블록 요소의 특성을 가지게 됩니다.

다음과 같은 HTML 블록 요소 안에 있는 내용을 수직 정렬하려면

<div class="table">
  <div>
    <span>테이블 셀 태그와 마찬가지로 각각의 셀은 높이 값을 가지는 블록 요소의 특성을 가지게 됩니다.</span>
    <img class="inlineimg vtextbottom" src="./backup/773/img/noimage.svg">
  </div>
</div>    

CSS를 다음과 같이 작성해야 합니다. "table" 속성을 사용하면, 내부에 셀 역할을 하는 블록 요소가 최소 1개는 있어야 하므로 셀 역할을 하는 블록 요소인 "<div>" 가 추가로 있게 됩니다.

.table{
    display: table;
}
.table > div{
    display: table-cell;
    width: 200px;
    height: 200px;
    vertical-align: middle;
    background-color: #88a;
}

수직 정렬이 적용된 블록 요소는 다음과 같이 보이게 됩니다.

수직 정렬이 적용된 블록 요소

4. top, transform 속성으로 정렬

"position" 속성을 "absolute"로 사용한 요소는 절대값 좌표를 사용하기 때문에 "vertical-align", "line-height" 과 같은 속성으로 수직 정렬을 하는 것이 불가능합니다.

"position" 속성을 "absolute"로 사용한 요소는 부모 요소의 "position" 속성이 "relative" 여야 부모 요소의 안쪽에 가운데 수직 정렬을 할 수 있으므로 "position" 속성이 "absolute" 인 요소를 가운데 정렬할 때는 부모 요소의 "position" 속성 값에 꼭 주의해야 합니다.

다음과 같이 수직 정렬을 하는 클래스를 하나 정의합니다.

.vcenter{
    display: inline-block;
    position: relative;
    width: 200px;
    height: 200px;
    background-color: #8a8;
}
.vcenter > div{
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 100%;
    height: auto;
}

"vcenter" 클래스가 정의된 요소는 "position"이 "relative" 여야 합니다. CSS를 적용한 HTML 코드를 다음과 같이 만들면

<div class="vcenter">
  <div>
    <span>테이블 셀 태그와 마찬가지로 각각의 셀은 높이 값을 가지는 블록 요소의 특성을 가지게 됩니다.</span>
    <img class="inlineimg vtextbottom" src="./backup/773/img/noimage.svg">
  </div>
</div>

이렇게 수직 정렬이 됩니다.

"absolute" 속성 요소를 수직 가운데 정렬

절대 좌표를 가지는 요소의 수직 정렬은 초보자에게는 이해하기가 다소 어려울 수 있습니다.

"display: absolute;" 속성을 가진 요소가 수직으로 가운데 정렬이 되는 원리는 다음과 같습니다. 특히 변형(transform) 속성이 적용되는 높이 값에 주의해야 합니다.

수평 정렬

1. text-align 속성으로 텍스트 가운데 정렬

블록 특성을 가진 텍스트 요소는 "text-align" 속성으로 가운데 정렬을 할 수 있습니다. 대표적인 텍스트 태그로 "<p>"가 있습니다.

"<span>" 태그는 인라인(inline) 요소로 "text-align" 속성이 적용 되지 않으므로 주의해야 합니다. "<span>" 태그에 "text-align" 속성을 사용하려면 "display: inline-block;" 과 같이 블록 속성을 추가해 블록 특성을 가지도록 해야 합니다.

text-align 가운데 정렬

인라인 요소인 "<span>"에 "display: block;" 속성을 부여할 경우, 인라인 속성이 사라지면서 인라인으로 배치된 레이아웃에 영향을 줄 수 있으므로 주의해야 합니다.

<span> 태그에 "display: block;" 속성을 부여해 인라인 블록으로 나열한 부모 요소의 레이아웃에 영향을 준 화면

블록 요소에 "text-align" 속성을 부여하면 내부의 요소들은CSS의 특징인 속성 상속을 받아 요소들도 부모 요소의 정렬 속성을 따라가게 됩니다. 블록 요소 안의 인라인 요소들 또한 정렬 속성이 적용됩니다.

2. margin 속성으로 정렬

너비 값을 가진 블록 태그, 또는 "display" 속성이 "block" 인 요소는 "margin" 속성을 사용해 가운데 정렬을 할 수 있습니다.

margin 값을 정할 때 좌우 여백 값으로 auto를 사용하면, 좌우 여백을 동일하게 자동으로 부여해서 요소가 가운데 위치하도록 합니다. 예를 들어 다음과 같이 CSS를 작성하면 됩니다.

.margincenter div{
    width: 300px;
    margin: 0 auto;
}

전체 컨텐츠를 감싸는 요소인 경우 margin 속성으로 "0 auto" 를 지정하면 상하 여백은 없고 좌우 여백만 자동으로 같은 너비로 지정됩니다.

3. left, transform 속성으로 정렬

position 속성을 "absolute"로 사용한 요소는 절대값 좌표를 사용하기 때문에 text-align, line-height 과 같은 속성으로 수직 정렬을 하는 것이 불가능합니다.

position 속성을 "absolute"로 사용한 요소는 부모 요소의 position 속성이 relative 여야 부모 요소의 안쪽에 가운데 수평 정렬을 할 수 있으므로 position 속성이 "absolute" 인 요소를 가운데 정렬할 때는 부모 요소의 position에 주의해야 합니다.

수직 정렬과 같은 원리로 "left: 50%;" 속성으로 가로 중심을 기준선 오른쪽에 자식 요소가 위치하며, "transform: translateX(-50%);" 속성으로 자식 요소 너비의 절반 만큼 왼쪽으로 이동시켜 정 가운데에 정렬되도록 합니다.

예를 들어 다음과 같은 HTML 블록 요소에

<div class="hcenterabs">
  <div>
    <span>테이블 셀 태그와 마찬가지로 각각의 셀은 높이 값을 가지는 블록 요소의 특성을 가지게 됩니다.</span>
    <img class="inlineimg vtextbottom" src="./backup/773/img/noimage.svg">
  </div>
</div>

"position: absolute;" 속성으로 절대 좌표로 가운데 정렬이 되도록 하려면 다음과 같이  CSS를 작성합니다.

.hcenterabs{
    background-color: #a88;    
}
.hcenterabs > div{
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    width: 300px;
    height: auto;
    background-color: #8a8;
}

완성된 레이아웃은 다음과 같이 보여집니다.

절대 위치 값을 가지는 요소를 가운데 정렬한 화면

여기서 "margin" 속성을 사용하는 방법과 중요한 차이점이 있습니다.

클래스 정의를 보면 "hcenterabs" 클래스를 적용한 부모 블록 요소(<div>)에 배경색이 지정되어 있지만, 결과 화면의 좌우 여백 영역에 배경색이 보이지 않습니다.

이것은 가운데 정렬되는 자식 요소가 "position: absolute;" 속성이 부여되어 있기 때문에 자식 요소가 유동되면서 부모 요소의 높이 값에 영향을 주지 않게 되면서 높이 값이 "0"이 된 것입니다.

부모 요소에 "border" 속성을 부여해 테두리 선을 표시하면 다음과 같이 상단에 상/하 2줄이 붙어서 표시되는 것을 확인할 수 있습니다.

부모 요소인 "hcenterabs" 클래스를 적용한 <div> 태그는 높이 값이 0이 됩니다.

"position: absolute;" 속성으로 가운데 정렬을 할 때는 부모 요소에 다른 컨텐츠가 없을 경우 높이 값이 "0" 이 된다는 사실을 항상 염두해 두어야 문제가 없는 레이아웃을 만들 수 있습니다.