@mixin mb-lg {
@media (max-width: $size__mb-lg) {
@content;
}
}
반응형 웹을 제작할 때, 위와 같이 미디어 쿼리를 사용하는 것이 일반적이었을 것입니다. 미디어 쿼리는 브라우저 전체의 크기를 기준으로 스타일을 적용하기 때문에 특정 요소의 크기에 따라 스타일을 적용하고자 하면 em
, %
등의 단위를 사용하거나 JavaScript를 사용하여 요소의 크기를 감지해 주여야 했습니다. @container
쿼리를 사용하면 브라우저 뷰포트 기준이 아닌, 🌟특정 요소의 크기🌟에 따른 반응형 웹 구현이 가능합니다.
.container{
container-type: inline-size; /* 컨테이너 타입 지정 */
container-name: parent-container; /* 컨테이너 이름 지정 */
container: parent-container / inline-size; /* background, margin처럼 단축 형태로 사용할 경우 */
}
기준이 될 요소의 CSS에 container-type
을 사용하여 쿼리 컨테이너로 지정할 수 있습니다. 또한, container-name
속성을 지정하여 포함 컨텍스트(컨테이너 쿼리를 적용할 범위 지정 시 사용)를 명명할 수 있습니다.
size
: 인라인 및 블록 축에 대해서 컨테이너 쿼리를 설정합니다. 높이를 기반으로 자식 요소의 콘텐츠를 제어할 때 사용합니다.inline-size
: 인라인 축에 대하여 컨테이너 쿼리를 설정합니다. 너비를 기반으로 자식 요소의 콘텐츠를 제어할 수 있으며, 가장 일반적으로 사용됩니다.normal
: 해당 요소는 어떠한 쿼리 컨테이너도 아니지만, 컨테이너 스타일 쿼리에 대한 쿼리 컨테이너로 남아 있습니다. (일반적으로 지정할 필요가 없습니다.)size
와 inline-size
에 대한 개념이 헷갈렸는데,
일반적으로 너비 기준으로 자식 요소의 스타일을 조정할 수 있는 inline-size
를 많이 사용할 것이고 컨테이너에 이미 높이가 지정되어 있으며,orientation: portrait
등 높이를 기반으로 자식 요소의 스타일을 지정할 때에는 size
를 사용하는 것으로 이해하였습니다. (https://stackoverflow.com/questions/74825464/what-is-the-difference-between-size-and-inline-size-of-container-type-css-pr)
.container{
container-type: inline-size; /* 컨테이너 타입 지정 */
border: 1px solid red;
max-width: 800px;
padding: 24px;
}
.box{
width: 100px;
height: 100px;
background: #000;
}
@container (min-width: 500px) {
.box{
width: 200px;
height: 200px;
border-radius: 100%;
}
}
미디어 쿼리를 등록했던 것과 마찬가지로, @container
구문을 사용하여 스타일을 지정해 줍니다. 위 코드는 .container
요소가 500px 이상일 경우, width와 height 속성이 200px로 지정되고 사각형 형태에서 원 형태로 변경됩니다.
.container{
container-name: container-name; /* 컨테이너 이름 지정 */
container-type: inline-size; /* 컨테이너 타입 지정 */
...
}
@container container-name (min-width: 500px) {
.box{
...(컨테이너 쿼리 스타일 지정)
}
}
여러 컨테이너가 중첩되어 있을 경우, @container <컨테이너 이름>
구문을 통해 특정 컨테이너에 대한 스타일만 지정할 수 있습니다.
min-width
, max-width
뿐만이 아닌 여러 설명자를 조건으로 사용할 수 있습니다.
aspect-ratio
: 컨테이너의 너비와 높이의 비, 즉 종횡비 값을 표현block-size
: 컨테이너의 블록 축의 값inline-size
: 컨테이너의 인라인 축의 값orientation
: 컨테이너의 방향(landscape, portrait)width
: 컨테이너의 너비height
: 컨테이너의 높이container-type
을 size
로 지정하고, orientation: portrait
를 조건에 사용해 보았습니다.
.container{
container-name: container-name;
container-type: size; /* 컨테이너 타입 지정 */
border: 1px solid red;
max-width: 600px;
height: 500px;
padding: 24px;
}
.box{
width: 100px;
height: 100px;
background: #000;
}
@container container-name (orientation: portrait) {
.box{
width: 200px;
height: 200px;
border-radius: 100%;
}
}
컨테이너의 높이가 너비보다 길어질 경우, 사진과 같이 컨테이너 쿼리가 적용된 것을 확인할 수 있습니다.
컨테이너 쿼리를 사용할 경우 %
, em
뿐만이 아닌 컨테이너 쿼리 길이 단위를 상대 단위로 사용할 수 있습니다.
cqw
: 전체 컨테이너 너비의 1%cqh
: 쿼리 컨테이너 높이의 1%cqi
: 쿼리 컨테이너의 인라인 크기의 1%cqb
: 쿼리 컨테이너의 블록 크기의 1%cqmin
: cqb, cqi 중 더 작은 값cqmax
: cqb, cqi 중 더 큰 값.container{
container-name: container-name;
container-type: inline-size; /* 컨테이너 타입 지정 */
border: 1px solid red;
max-width: 1000px;
padding: 24px;
}
@container container-name (min-width: 500px) {
.text-title{
font-size: 5cqi; /* 컨테이너 쿼리 길이 단위로 설정 */
}
}
2024년 8월 기준으로 IE를 제외한 Chrome, Edge, Safari 등 대부분의 모던 브라우저에서는 컨테이너 쿼리를 지원하고 있는 모습을 볼 수 있습니다.👀
다만 대체적으로 2022년 이전 버전의 브라우저들은 지원하고 있지 않아서, 미디어 쿼리를 대체해서 바로 실무에서 사용하기에는 조금 어려워 보입니다.💦
하지만 개인적으로 컴포넌트 기반으로 개발하는 리액트, 뷰 등 모던 프론트엔드 생태계와 컴포넌트 기반으로 UI를 문서화하는 Storybook과 찰떡궁합인 기능이라고 생각이 듭니다. 이제는 너무나도 많이 쓰이는 grid
속성처럼 머지않아 컨테이너 쿼리도 어렵지 않게 볼수 있지 않을까 조심스럽게 생각해봅니다.