...
컨테이너 쿼리 vs 미디어 쿼리
컨테이너 쿼리는 미디어 쿼리와 같이 문서의 스타일을 반응형으로 지정할 수 있다. 이 둘의 작동 방식은 유사하지만, 차이점은 어느 것을 기반으로 동작되냐는 점이다. 예를들어 미디어 쿼리는 디바이스 또는 미디어 유형을 기반으로 뷰포트에 의해 반응하지만, 컨테이너 쿼리는 페이지내의 특정 컴포넌트 요소 기반으로 반응한다.
아래 그림을 보면 이해가 될텐데, 미디어 쿼리는 브라우저 너비를 기준으로 반응하지만, 컨테이너 쿼리는 문서 내 각 요소 의 크기나 모양에 따라 반응형 쿼리를 지정할 수 있다는 점에서 상위 호환이라고 할 수 있다.
컨테이너 쿼리가 없었을 시절에는 자바스크립트의 Resize Observer 기술을 통해 특정 요소의 크기 변화를 관찰하여 스크립트로 스타일링을 해주어야 했다. 하지만 이제 간단한 CSS 컨테이너 문법 지정을 통해 매우 간편하게 보다 세밀하고 정확한 반응형 쿼리를 구현할 수 있게 되었다.
컨테이너 쿼리의 장점
컨테이너 쿼리 기능이 빛을 발하는 순간은 아래와 같은 '심플 모드' 나 '확장 모드' 기능을 지원하는 반응형 사이드바를 설계할 때 우측 본문 영역에 대한 반응형 스타일링이 필요할 때이다.
예를들어 좌측 사이드바 영역을 제외한 우측 본문 영역 안에 있는 여러 요소들을 홈페이지의 가로폭에 따라 요소에 변화를 주어야 한다고 할때, 기존 방식대로 미디어 쿼리(@media)를 쓴다면 사이드바 영역을 포함한 전체 브라우저 가로폭을 계산하기 때문에 '심플 모드' 일때 와 '확장 모드' 일때를 모두 고려해야 되어 같은 디자인을 적용하더라도 본문과 구분하여 따로 관리해야하는 불편함이 있다.
굳이 구현한다 라면 아래와 같이 사이드바가 '심플 모드' 냐 '확장 모드' 에 따라 사이드바의 길이에 따라 미디어 쿼리를 두번 구현해야 할지도 모른다. 왜냐하면 본문(main) 영역 부분이 사이드바 길이와 함께 브라우저 폭을 계산해야 되기 때문이다.
main {
width: 1100px;
}
/* 사이드바 확장 모드 상태일때의 반응형 쿼리 */
@media screen and (max-width: 1400px) {
html[data-sidebar='expand'] main {
padding: 0 35px;
width: 100%;
}
}
/* 사이드바 심플 모드 상태일때의 반응형 쿼리 */
@media screen and (max-width: 1200px) {
html[data-sidebar='simple'] main {
padding: 0 35px;
width: 100%;
}
}
그러나 위의 본문의 main 영역을 컨테이너 쿼리로 지정한다면, 좌측 사이드바 상태를 따지지 않고 오로지 main 영역의 가로폭에 따라 반응하기 때문에 좀더 직관적이고 유지 보수 좋게 구성할 수 있게 된다.
main {
width: 1100px;
container-name : main-container;
container-type : inline-size;
}
/* 본문 메인 특정 영역에 따른 반응형 쿼리 */
@container main-container (max-width: 992px) {
html main {
padding: 0 35px;
width: 100%;
}
}
CSS Container Queries 정리
컨테이너 쿼리 사용법
컨테이너 쿼리는 브라우저 viewport 기준이 아닌, 특정 요소의 크기에 따라 반응적인 동작을 한다. 그래서 가장 먼저 해야 할 일은 반응형을 적용할 컨테이너 요소를 지정하는 것이다. 그래야 특정 요소를 기준으로 치수를 계산하기 때문이다.
1. 먼저 반응형으로 등록할 요소를 컨테이너로 등록해준다.
container-name 을 통해 쿼리 컨테이너의 이름을 지정한다.
div {
container-name: div-container; /* 컨테이너 쿼리 요소 이름 */
}
2. 컨테이너 요소의 타입을 지정해준다.
container-type 에는 size, inline-size, normal 속성값이 존재한다.
inline-size: 인라인 레벨 기준으로 컨테이너를 적용. 요소의width값에 따라 반응형이 동작된다.size: 블록 레벨 기준으로 컨테이너를 적용.width뿐만 아니라height값에 따라 반응형이 동작 된다.normal: 해당 값이 부여된 요소를 container에서 제외시킨다. 일종의 none 의미라고 보면 되겠다.
div {
container-name: div-container;
container-type: inline-size; /* 왠만한 상황에선 inline-size 로 이용한다고 보면 된다 */
}
div {
/* container-name / container-type */
container : div-container / inline-size; /* 한줄로도 단축 표현이 가능하다 */
}
3. @container 반응 치수를 지정해준다
@media 쿼리를 등록했던 것 처럼 똑같이 @container 쿼리를 등록해주면 된다. 이때 컨테이너 이름을 지정해주면 특정 컨테이너 내에서만 반응하고, 이름을 지정 안해주면 모든 컨테이너에 대해 전역으로 반응하게 된다.
/* 모든 컨테이너 요소에 반응 */
@container (min-width: 700px) {
div {
font-size: 2em;
}
}
/* 특정 container-name의 요소에 반응 */
@container div-container (min-width: 700px) {
div {
font-size: 2em;
}
}
컨테이너 쿼리 길이 단위
viewport의 vw, vh 단위 처럼 container의 너비와 높이를 기준으로 하는 상대 기준점 단위가 존재한다. 이 단위값을 이용하면 요소의 구체적인 길이 값을 다시 계산할 필요 없이 다른 컨테이너에서 유연하게 사용할 수 있다.
- cqw : 쿼리 컨테이너 너비의 1%
- cqh : 쿼리 컨테이너 높이의 1%
- cqi : 쿼리 컨테이너 인라인 크기의 1%
- cqb : 쿼리 컨테이너의 블록 크기의 1%
- cqmin : cqi 또는 cqb 중 더 작은 값
- cqmax : cqi 또는 cqb 중 더 큰 값
/* 컨테이너의 인라인 크기를 기준으로 제목의 글꼴 크기를 설정 */
@container (min-width: 700px) {
div {
font-size: 1em + 2cqi;
}
}
컨테이너 쿼리 브라우저 지원 범위
IE를 제외하곤 왠만한 PC, Mobile 브라우저에서 문제없이 모두 지원됨을 볼 수 있어 더욱더 사용하지 않을 이유가 없다.
컨테이너 쿼리 폴리필
만일 마이너한 구형 브라우저를 꼭 지원해야만 한다면, 폴리필(polyfill) 된 라이브러리가 있으니 이걸 사용하면 된다. 사용법도 css에 컨테이너 쿼리 문법을 쓰고 라이브러리를 로드해 스크립트만 실행하면 알아서 브라우저의 컨테이너 쿼리 지원 유무를 감지하고 폴리필 해준다.
<script src="https://unpkg.com/container-query-polyfill/dist/container-query-polyfill.modern.js"></script>
<script>
const supportsContainerQueries = "container" in document.documentElement.style;
if (!supportsContainerQueries) {
import("container-query-polyfill");
}
</script>
# 참고자료
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries
https://web.dev/cq-stable/
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.