Skip to content

CSS 그리드 레벨2: 서브그리드

CSS 그리드 레이아웃이 나온 지 1년이 넘었다. 현재 주요 브라우저는 CSS 그리드를 지원하고 CSS 작업 그룹CSS Working Group은 이미 레벨 2 그리드 명세를 작업 중이다. 이 글에서는 작업 중인 CSS 그리드 명세 초안 일부를 설명하려고 한다. 여기서 다룬 내용은 향후 변경될 수 있으며 아직 지원하는 브라우저는 없다. 진행 중인 내용을 미리 알아보는 정도로 읽기를 권한다. 향후 구현이 더 구체화되면 보다 실질적인 내용을 주제로 글을 쓸 계획이다.

 

CSS 명세 레벨

현재 웹 브라우저에서 사용할 수 있는 그리드 기능은 CSS 그리드 명세 레벨1에 기반한다. CSS 명세는 여러 모듈로 나누어져 있는데 CSS 2.1에서 CSS로 넘어가는 과정에서 이런 모듈화가 이루어졌다. CSS 2.1의 다음 버전인 셈이라서 CSS3라고 부르지만 사실 CSS3는 없다. 대신 원래 CSS 2.1 명세에 정의되어 있던 내용 일부를 포함하는 여러 모듈이 있을 뿐이다. CSS2.1에 있었던 CSS는 레벨3 모듈이 된다. 따라서 CSS 2.1에 정의되어 있던 선택자는 CSS 선택자 레벨3이 되었다.

CSS 그리드 레이아웃처럼 CSS 2.1에는 없던 새로 추가된 CSS 기능은 레벨1부터 시작한다. CSS 그리드 레벨1 명세는 그리드의 첫 번째 버전이다. 특정 레벨의 명세가 후보 권고안Candidate Recommendation 상태로 변하면 여기에는 새로운 주요 기능을 추가할 수 없다. 따라서 브라우저를 비롯한 사용자 에이전트는 이 명세를 구현할 수 있고 이 명세는 후에 W3C 권고안이 될 수 있다. 새로 만들어진 기능은 해당 명세의 다음 레벨에 포함된다. CSS 그리드 레이아웃이 바로 이 단계에 있다. 레벨1 명세는 후보 권고안 상태이기 때문에 작업 중인 새 기능을 추가하기 위해 레벨2 명세를 만들었다. 이 글에서는 마지막으로 결정된 내용만 다룰 것이므로 이 명세와 관련된 논의 진행 과정이 궁금하다면 편집자 초안을 살펴볼 것을 권한다.

 

CSS 그리드 레벨2에는 무엇이 포함되나

CSS 그리드 명세2는 레벨1에 있던 내용에 더해 몇 가지 새로운 기능을 포함할 것이다. 이 글을 쓸 당시에는 레벨2가 후보 권고안이 되면 레벨1의 모든 내용을 레벨2로 옮기라는 메모가 있었다.

이제 새로운 기능을 알아보자. 그리드 레벨2의 핵심은 CSS 그리드의 서브그리드subgrid 기능이다. 서브그리드는 원래 레벨1 명세에 포함되어 있었다가 빼기로 했다. 그 이유는 서브그리드 사용 사례를 충분히 이해할 만한 시간이 필요했고 다른 기능을 레벨1로 먼저 내보낸 후 서브그리드에 집중할 시간을 확보하려는 이유도 있었다. 이제 현재 편집자 초안에 서술된 서브그리드 기능을 살펴보려고 한다. 서브그리드 기능이 아주 초기 단계이지만 그렇기 때문에 오히려 현재까지의 진행 상황을 살펴보고 이 명세의 발전 방향을 형성하는 데 도움을 주기에 좋은 시점이다. 이 글을 통해 논의 중인 몇 가지 내용을 소개함으로써 많은 사람이 이 내용을 이해하고 참여했으면 한다.

 

서브그리드는 무엇인가

CSS 그리드 레이아웃에서는 그리드를 중첩할 수 있다. 아래 예제에는 열 트랙 6개와 행 트랙 3개가 있는 부모 그리드가 있다. 이 그리드에 열 기준선 2번에서 6번까지, 행 기준선 1번에서 3번까지 걸쳐 있는 그리드 아이템을 배치했다. 그리고 이 아이템을 그리드 컨테이너로 만들고 여기에도 행 트랙을 정의했다.


자식 그리드 트랙은 부모 트랙과 아무 상관이 없다. 다시 말해 부모 그리드 기준선과 동일한 위치에 자식 그리드 기준선을 두려면 부모와 자식 트랙의 크기가 같아질 수 있도록 트랙의 크기를 계산하고 몇 가지 작업을 더 해야 한다. 앞 예제에서 부모와 자식 그리드의 트랙은 잘 정렬되어 있을 것이다. 정해진 것보다 더 큰 공간을 차지하는 그리드 아이템이 부모에게 추가되기 전까지는 말이다.

작은 아이템을 추가할 때까지는 잘 정렬되어 있다.(이미지 확대)
큰 아이템을 추가하면 트랙의 정렬이 흐트러진다. (이미지 확대)

위와 같은 열 문제는 그리드의 유연성을 제한하면 해결할 수 있는 경우도 많다. 더 큰 아이템이 추가돼도 무시하도록 fr 단위로 설정한 열을 minmax(0, 1fr)로 설정하거나 예전처럼 퍼센트 단위를 사용하는 방법도 있다. 하지만 이 방법을 사용한다면 그리드 사용의 장점도 일부 사라진다. 게다가 자식 그리드 행을 정렬할 때는 이 방법을 사용할 수 없다.

각 카드에 헤더, 본문, 푸터가 있는 카드 레이아웃을 생각해보자. 당연히 모든 카드의 헤더와 푸터는 줄에 맞춰 잘 정렬되어 있어야 한다.


카드 레이아웃 (이미지 확대)

이 레이아웃은 각 카드 헤더와 푸터 높이가 다른 카드와 같을 때만 잘 동작한다. 콘텐츠를 추가하면 환상은 깨지고 헤더와 푸터는 같은 줄에 정렬되지 않는다.

모든 헤더를 같은 줄에 정렬할 수 없다.(이미지 확대)

 

서브그리드 만들기

[역주]이 절에 나온 ‘서브그리드’나 ‘중첩 그리드’는 위에서 설명한 ‘자식 그리드’로 생각하면 이해하기 쉽다.[/역주]

이제 현재 서브그리드 기능 명세가 어떻게 정의되어 있는지 살펴보고, 위에서 언급한 문제를 서브그리드로 해결하는 방법도 알아보자.

주의: 이 글을 쓰는 현재 이 절에서 소개한 코드가 동작하는 브라우저는 없다. 이 코드는 문법과 개념을 보여주는 용도로 생각하자. 최종 명세에서는 세부 사항에 변화가 있을 것으로 생각한다. 이 글은 2018년 7월 23일 현재 공개된 편집자 초안에 기초하여 작성했다.

서브그리드를 만들려면 grid-template-rowsgrid-template-columns에 새로 추가된 값을 사용하면 된다. 이 속성들은 보통 행 트랙과 열 트랙의 크기와 개수를 정의할 때 사용한다. 하지만 서브그리드를 만들 때는 이런 트랙을 정의할 필요가 없다. 대신 subgrid라는 값을 사용하여 이 중첩 그리드nested grid의 트랙 크기와 개수를 중첩 그리드가 차지하는 부모 그리드의 영역에 맞춰야 한다는 것을 알려야 한다.

아래 코드에는 행 6개와 열 3개가 있는 부모 그리드가 있다. 그리고 부모 그리드의 2번 열에서 6번 열, 1번 행부터 4번 행까지 걸쳐서 표현되는 그리드 아이템이 있는데, 이 그리드 아이템은 그 자체가 그리드 컨테이너인 자식 그리드이기도 하다. 여기까지는 앞서 나온 예제와 똑같다. 이제 서브그리드의 사용법을 살펴보자. 이 중첩 그리드는 grid-template-columnsgrid-template-rows 속성에 subgrid라는 값이 설정되어 있다. 다시 말해 이제 중첩 그리드에는 부모 그리드에 정의된 트랙과 크기가 똑같은 열 트랙 4개와 행 트랙 2개가 나타난다.


중첩 그리드는 부모 그리드에 정의된 트랙을 사용한다.(이미지 확대)

이는 곧 부모 그리드에서 트랙의 크기를 변경하면 서브 그리드 트랙의 크기도 변경된다는 의미이기도 하다. 긴 단어 때문에 부모 그리드의 한 트랙이 넓어지면 중첩 그리드도 따라서 넓어져서 줄은 여전히 정렬된 상태로 유지된다. 반대로도 똑같이 동작한다. 콘텐츠 때문에 서브그리드가 더 넓어지면 부모 그리드도 넓어진다.

 

일차원 서브그리드

일차원적인 서브그리드를 만들고 다른 축 방향의 속성으로 트랙 크기 설정할 수 있다. 아래 예제에서 서브그리드는 grid-template-columns로만 정의가 되어 있다. grid-template-rows 속성은 트랙 목록을 정의한다. 따라서 열 트랙은 위에서 본 것과 같이 4개가 만들어지지만, 행 트랙은 부모 트랙과는 별개로 설정된다.


따라서 이 서브그리드 열은 부모 그리드 안에 있기는 하지만 제일 앞에서 살펴봤던 자식 그리드와 성질이 같다. 중첩 그리드는 부모 그리드의 행 2개에 걸쳐 있으므로 서브그리드의 콘텐츠를 모두 품으려면 서브그리드 영역과 겹치는 부모 그리드의 행도 함께 늘어나야 한다. 그렇지 않으면 콘텐츠가 넘쳐흐르는 것처럼 보이게 된다.

다른 축 방향의 트랙을 암묵적으로 설정한 일차원 서브그리드를 정의할 수도 있다. 다음 예제에서 서브그리드는 행 트랙을 설정하지 않고 grid-auto-rows에만 값을 설정했다. 이 암묵적 그리드는 내가 설정한 크기의 행을 만든다. 앞 예제와 마찬가지로 콘텐츠가 넘쳐흐르는 것처럼 보이지 않으려면 부모 그리드의 행에 서브그리드를 담을 수 있을 만큼 충분한 공간을 확보해야 한다.


 

줄 번호와 서브그리드

가장 처음 봤던 예제를 다시 살펴보자. 서브그리드 트랙 크기가 행과 열 모두 부모 그리드에 의해 정해졌다는 것을 알 수 있다. 하지만 줄 번호는 서브그리드에서도 평상시와 같이 동작한다. 첫 번째 열 기준선이 1번 줄이 되고 가장 끝은 -1번 줄이 된다. 부모 그리드의 줄 번호를 사용해서 서브그리드 줄 번호를 지칭하면 안 된다.


중첩 그리드는 줄 번호를 1부터 시작한다.(이미지 확대)

 

간격과 서브그리드

서브그리드는 부모 그리드에 설정된 열과 행 간격을 그대로 사용한다. 하지만 행 간격과 열 간격은 서브그리드에서 재정의할 수도 있다. 예를 들어 부모 그리드에는 column-gap이 20px로 설정되어 있지만 서브그리드에서는 column-gap이 0으로 설정된 경우를 생각해보자. 간격이 0으로 줄었기 때문에 서브그리드 그리드 셀의 외곽선은 열 간격이 있던 중간 위치까지 확장됐다. 결과적으로 그리드 셀은 각 방향으로 10px만큼씩 늘어난다.

이제 서브그리드가 이 글 초반에 설명했던 두 번째 사용 사례의 문제를 어떻게 해결하는지 살펴보자. 서브그리드를 사용하면 모든 카드의 헤더와 푸터를 줄에 맞춰 정렬할 수 있다.


모든 카드의 헤더와 푸터가 줄에 맞추어져 있다.(이미지 확대)

 

줄 이름과 서브그리드

부모 그리드에서 설정된 기준선 이름은 서브그리드에 그대로 전달된다. 따라서 부모 그리드에서 줄의 이름을 정했다면 이 줄 이름을 따라서 그리드 아이템을 배치할 수도 있다.



부모 그리드의 줄 이름은 서브그리드에도 적용된다.(이미지 확대)

물론, 서브그리드 줄에도 이름을 설정할 수 있다. 그리드 기준선에는 여러 개의 이름을 붙일 수도 있다. 줄 이름을 설정하려면 grid-template-columnsgrid-template-rows의 값을 subgrid로 설정한 후 이 값에 줄 이름을 나열하면 된다. 다음은 위 예제의 서브그리드에 있는 각 줄에 이름을 추가한 것이다. 즉, 이 예제에 있는 서브그리드 줄은 모두 2개의 줄 이름이 설정되어 있다.



부모에게서 전달받은 이름에 서브그리드에서 설정한 줄 이름이 추가된다.(이미지 확대)

 

암묵적 트랙과 서브그리드

그리드의 한 차원[역주]열 또는 행 중 ‘한 방향’으로 이해해도 좋습니다[/역주]을 서브그리드로 만들면 해당 차원에는 암묵적 그리드를 추가할 수 없다. 여기에 아이템을 추가하려고 하면 훨씬 큰 그리드에서 그리드 아이템을 다루는 방식처럼 새로 추가된 그리드 아이템을 다룬다. 즉, 사용 가능한 서브그리드 마지막 트랙에 추가된 아이템을 배치한다. 사용 가능한 것보다 더 많은 트랙으로 확장하려는 서브그리드에 다른 그리드를 만들면 이 그리드는 자신의 마지막 줄을 서브그리드 마지막 줄에 일치하도록 설정한다.

하지만 앞서 설명했듯이 서브그리드의 한 차원을 평범한 자식 그리드와 똑같은 방식으로 동작하게 만드는 것도 가능하다. 암묵적 트랙까지 포함해서 말이다.

 

개발 과정에 참여하기

CSS 작업 그룹은 다른 오픈소스 프로젝트와 마찬가지로 깃허브GitHub에서 공개적으로 작업을 진행한다. 덕분에 메일링 리스트에서 있었던 작업을 좇는 것도 다소 편리해졌다. CSS 작업 그룹의 깃허브 저장소에서 css-grid-2라는 태그가 붙은 이슈를 확인하면 CSS 그리드 명세 레벨 2에 대해 제기된 여러 이슈도 볼 수 있다. 언제라도 여러분의 생각과 사용 사례를 해당 이슈에 공헌할 수 있다.

CSS 그리드 레이아웃에는 사람들이 요청한 여러 다른 기능도 있다. 레벨 2에 포함되어 있지 않다고 해서 아예 고려하고 있지 않다는 의미는 아니다. 명세의 레벨은 제품의 기능 공개와 비슷하다. 지금 버전에 포함되지 않았다고 해서 앞으로도 영원히 포함되지 않는다고는 볼 수 없다. 새로운 웹 플랫폼 기능을 출시하는 과정이 제품 공개 주기보다 조금 길기는 하지만 프로세스 자체는 유사하다.

 

명세 작업에는 얼마나 걸릴까

명세 개발과 브라우저 구현은 일종의 순환하는 반복 과정으로 볼 수 있다. 명세에 ‘최종’이라는 확인이 붙기 전에도 브라우저에서 구현될 수 있다. 초기 구현은 보통 기능 플래그를 사용해야만 볼 수 있다. 그리드 명세도 처음엔 그렇게 브라우저에서 구현됐었다. 이 기능이 언제 브라우저에서 구현되는지 지켜보자. 코드와 함께 사용해보면 이 기능을 더 쉽게 이해할 수 있을 것이다.

향후 추가될 기능을 살펴봤던 이 글이 재미있었기를 바란다. 서브그리드는 웹을 위한 완전한 그리드 레이아웃 시스템에 필수불가결한 기능이다. 그래서 현재 진행 중인 서브그리드 기능에 거는 기대가 크다. 앞으로도 이 기능의 진행 상황과 브라우저 구현에 관한 소식을 올릴 테니 관심 있게 지켜보기를 바란다.

 

도서 소개

레이철 앤드루의 신간 『새로운 CSS 레이아웃』
그리드를 사용한 레이아웃을 기존 레이아웃과 비교해서 살펴볼 수 있습니다. 예제를 통해 그리드 레이아웃이 어떻게 활용되는지 확인해보세요. 레이아웃만을 다룬 ‘그리드 레이아웃’ 전문서 『새로운 CSS 레이아웃』입니다. 새로운 웹 디자인 시대 흐름에 뒤처지지 않으려면 이 책을 꼭 읽어야 합니다!!
저작권 정보이 글은 Smashing Magazine 기사를 번역한 것입니다. 저작권자의 정당한 허락을 받은 저작물로 한국어판 저작권은 웹액츄얼리에 있습니다. 웹액츄얼리의 서면 동의 없이 무단 전재, 복제를 금합니다. 원본은 CSS Grid Level 2: Here Comes Subgrid에서 확인할 수 있습니다.
참여를 기다립니다!국내 웹 디자인계 발전에 도움 주실 분을 찾습니다. 최신 웹 기술에 관심 많은 프론트엔드 개발자이면서, 영어를 우리말로 옮기는 데 어려움 없는 분의 연락을 기다립니다. 번역물에 대한 소정의 번역료를 지급합니다. 메일로 연락주시면 안내드리겠습니다.
books@webactually.com


맨위로