CSS 그리드(Grid) - 1. 인라인블록(Inline-block), 플렉스박스(Flex), 그리드(Grid) 레이아웃

CSS 로 레이아웃을 배치하는 속성 중 가장 혁신적이고 뛰어나지만, 아직도 사용 비중이 낮은 대표적인 CSS 기술이 그리드(Grid)입니다.

부트스크랩(Bootstrap) 같은 그리드 기반의 프론트엔드 웹 프레임워크까지 많이 사용되고 있지만, 그에 못지 많게 강력한 기능을 구현할 수 있는 CSS 그리드는 여전히 사용을 꺼려하는게 현실입니다.

여전히 프론트엔드 개발자들은 그리드의 호환성 문제를 걱정하고, 기존에 써왔던 인라인 블록(inline-block) 이나, 퍼센트(%) 값으로 일일이 계산한 크기를 배치 요소들에 적용을 하는 방식을 사용합니다.

걱정의 주된 이유는 인터넷 익스플로러이고, 아직도 남아있는 소수의 인터넷 익스플로러 때문에 그리드의 사용을 망설입니다.

2021년 8월이 되면 인터넷 익스플로러는 완전히 퇴출이 되며, 현존하는 웹 브라우저들은 그리드 지원에 충실하기 때문에 더 이상 호환성 문제를 걱정하지 않아도 됩니다.

caniuse.com에서 확인한 그리드 속성의 호환성

레거시 레이아웃 구현 방법

많은 프론트엔드 개발자 들이 지금까지 사용하는 익숙한 레이아웃 구현 방식은 다음과 같습니다.

.content{
    width: 400px;
    display: block;
    background-color: #9a9;
    margin: 0 auto;
}
.content .item{
    float: left;
    width: 47.5%; /* 아이템 너비 */
    margin-right: 5%; /* 아이템 사이 여백 */
    margin-bottom: 1.25em;
    background-color: #a99;
    min-height: 100px;
}
.content .item:nth-child(2n){
    margin-right: 0; /* 오른쪽 끝 아이템 여백 제거 */
}

완성된 레이아웃은 호환성 문제도 없고 대부분의 그리드형 레이아웃에 잘 동작합니다.

하지만 이 레이아웃은 아이템을 감싼 부모 요소인 ".content" 높이가 컨텐츠 영역 높이로 설정되지 않아 0으로 인식되기 때문에 배경색이 전혀 보이지 않게 됩니다.

float 속성으로 제작한 레이아웃

이런 문제를 해결하려면 부모 요소인 ".content" 의 "display" 속성을 "display: inline-block;" 으로 변경하면 됩니다.

인라인 요소가 되므로 자식 요소들인 아이템 요소들의 높이값이 인식되어 배경색이 보이게 됩니다.

단, 이렇게 하면 인라인블록의 속성으로 인해 "margin: 0 auto;"로 가운데 정렬을 한 속성이 적용되지 않아 왼쪽에 붙은 형태가 됩니다.

이 문제를 하결하려면 인라인블록 요소인 ".content" 감싸는 상위 블록 요소(<div></div>)를 추가해서 "text-align: center;" 속성을 부여하면 됩니다.

.wrap{
    text-align: center;
}
.content{
    width: 400px;
    display: inline-block;
    background-color: #9a9;
}
.content .item{
    float: left;
    width: 47.5%;
    margin-right: 5%;
    margin-bottom: 1.25em;
    background-color: #a99;
    min-height: 100px;
}
.content .item:nth-child(2n){
    margin-right: 0;
}
인라인블록으로 만든 레이아웃

인라인블록으로 만든 레이아웃은 온전하게 잘 동작하지만, 태그도 추가해야 하고, 설정해야 하는 속성 값들도 많습니다.

여백 계산이 필요없는 플렉스 박스

조금 더 고급스럽고 심플하게 구현을 하면 다음과 같이 플렉스박스로 구현할 수 있습니다.

.content{
    width: 400px;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    background-color: #9a9;
    margin: 0 auto;
}
.content .item{
    width: 31%;
    margin-bottom: 1.25em;
    background-color: #a99;
    min-height: 100px;
}
.content .item:nth-child(2n+1){
    margin-left: 0;
}

결과는 동일하지만, 더 간결하고 보기 좋으며, CSS 속성 관리도 단순해집니다.

반응형 레이아웃을 제작할 때도 아이템 너비만 변경해주면 깨끗하게 레이아웃이 변경되기 때문에 훨씬 유연하고 완성도도 높습니다.

플렉스박스로 구현한 레이아웃

플렉스박스의 가장 좋은 점은 여백 계산과 속성 관리를 일일이 하지 않아도 알아서 자동으로 계산이 되어 배분되는 것입니다.

마지막 행의 여백 제거

맨 마지막행에 여백이 붙는 것은 다음과 같은 CSS로 간편하게 제거할 수 있습니다.

CSS 속성을 자꾸 추가해야 하고 미디어쿼리로 반응형 레이아웃을 구현할 때 처리해야하는 속성이 자꾸 늘어나는 단점이 있는 것을 제외하면, 인라인블록이나 플렉스박스로 원하는 모든 레이아웃을 만들 수 있습니다.

.content .item:nth-last-child(-n+2){
    margin-bottom: 0;
}
마지막 행의 마진을 제거한 레이아웃

그리드로 레이아웃 구현

플렉스박스의 편리한 레이아웃 구현 방법을 알게되면, 그동안 사용해왔던 레이아웃 구현 방법이 얼마나 원시적이고 불편한 방법이었는지를 알 수 있습니다.

플렉스박스를 사용하면 빠르게 레이아웃을 구현할 수 있지만, 여백 크기 관리를 사용자 정의로 정밀하게 하려면 기존에 사용하던 레거시 구현 방법과 별다른 차이가 없어지는 단점이 있습니다.

이런 불편함을 해결할 수 있도록 전체 웹페이지의 레이아웃을 빠르고 정확하게 할 수 있도록 고안된 속성이 그리드(Grid) 입니다.

그리드는 이름처럼 모눈 종이에 레이아웃을 그리듯이 여백과 가로x세로 아이템 갯수를 정하는 방식으로 레이아웃을 정할수 있습니다. 마치 테이블 같지만, 테이블과는 달리 아주 유연하게 레이아웃을 변형할 수도 있고, 테이블의 최대 약점인 반응형 레이아웃 지원도 완벽하게 대응이 됩니다.

앞서의 예를 그리드로 구현하면 다음처럼 구현됩니다.

.content{
    width: 400px;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 1em;
    background-color: #9a9;
    margin: 0 auto;
}
.content .item{
    background-color: #a99;
    min-height: 100px;
}
그리드 레이아웃

앞서의 방법들은 마지막 열이나 마지막 행의 여백에 대한 처리를 따로 해야 했지만, 그리드 레이아웃은 자동으로 모두 처리가 되기 때문에 이런 예외 처리를 할 필요가 없습니다.

그리드 속성 정의를 위한 다음의 단 3줄만으로 크기와 여백, 그리고 예외 처리까지 정리가 됩니다.

    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 1em;

당연하게도 유지해야 하는 CSS 속성의 분량도 현저히 줄어들고, 반응형 레이아웃을 위한 미디어쿼리도 내부 아이템 속성 CSS를 수정하지 않기 때문에 명확하고 간결한 관리가 가능합니다.