컴퓨터 그래픽스 디자인이라는 대학교 강의를 수강하며 피그마를 사용해 앱을 디자인하는 과제를 수행한 적이 있다. 이때 피그마의 '오토 레이아웃'이라는 기능을 알게 되었는데 정말 너무 좋더라... 🥲
개발도 이렇게 쉽게 화면 크기에 따라 반응하도록 할 수 있으면 얼마나 좋을까 싶었고, HTML과 CSS를 처음 배울 시기의 나는 반응형 디자인 하면 미디어쿼리만 사용하려고 했는데 이 '오토 레이아웃'을 통해 반응형 웹의 상대길이에 대한 중요성을 깨달을 수 있었다.
그렇게 오늘은 반응형 웹 디자인을 위한 방법을 알아보려고 한다.
반응형 웹 디자인(responsive web design, RWD) 이란 하나의 웹사이트에서 PC, 스마트폰, 태블릿 PC 등 접속하는 기기의 종류와 크기에 따라 사이트가 최적으로 보이고 작동하도록 만드는 데 초점을 맞춘 웹 개발 개념이다.
세상엔 정말 많은 전자기기가 존재하고, 그들의 크기는 너무 다양하다. 모든 사용자의 경험을 보장해줘야 할 개발자가 웹 브라우저 요소들의 크기를 절대 길이로 고정해놓는 무례한(?) 행동은 하지 않도록 하겠다.
앞서 말했던 것처럼 웹 개발을 처음 배울 때의 나는 이 반응형 웹 디자인을 위해서 미디어쿼리만 사용할 생각을 했는데,
반응형 웹 디자인하면 자연스레 따라오는 미디어쿼리는 스크린 해상도 크기에 따라 CSS 스타일을 적용하도록 분기 처리해주는 모듈이다.
아래와 같이 @media
뒤에 미디어 유형
과 미디어 특성
으로 작성하면 된다. 미디어 유형과 미디어 특성에 대한 값들은 여기를 참고하자.
/* Small devices (landscape phones, 576px and up) */
@media screen and (min-width: 576px) { ... }
/* Medium devices (tablets, 768px and up) */
@media screen and (min-width: 768px) { ... }
/* Large devices (desktops, 992px and up) */
@media screen and (min-width: 992px) { ... }
/* X-Large devices (large desktops, 1200px and up) */
@media screen and (min-width: 1200px) { ... }
/* XX-Large devices (larger desktops, 1400px and up) */
@media screen and (min-width: 1400px) { ... }
예시는 화면 크기가 768px 이상 992px 이하일 때 body 요소의 폰트 크기는 14px로 설정되고, 992px 이상일 때는 16px로 설정된다.
@media screen and (min-width: 768px) {
body {
font-size: 14px;
}
}
@media screen and (min-width: 992px) {
body {
font-size: 16px;
}
}
이런 미디어쿼리도 단점이 있는데,
1. 로딩 시간
미디어쿼리는 브라우저의 렌더링 이후 동작하므로 초기 로딩 시간이 오래 걸릴 수 있어 사용자 경험을 저하시킬 수 있다.
2. 성능 저하
미디어쿼리를 잘못 적용한 경우, 불필요한 스타일시트가 로드되거나 필요없는 DOM 요소가 생성될 수 있다.
3. 유지보수
미디어쿼리를 상세하게 작성했다면, 점차 서비스해야 할 플랫폼이 늘어났을 때 이를 유지보수하기 어려울 수 있다.
4. 브라우저 호환성
물론 소수겠지만, 일부 브라우저는 미디어쿼리를 지원하지 않을 수도 있다. 또한 미디어쿼리 문법 중 비교적 최근에 생성된 range syntax
의 경우 지원되지 않는 브라우저가 존재한다.
위와 같은 단점을 해결하기 위해 미디어쿼리를 최소화해서 사용하는 방법이 있다. 첫 번째는 바로 상대길이를 이용하는 것
상대 길이는 말 그대로 상대적인 길이이다. 부모 요소의 크기 변화에 따라 자식 요소의 크기도 맞게 변하는 것으로 모든 웹 브라우저의 최상위 부모는 브라우저이다. 결국 브라우저의 크기가 변경되면 그 하위 자식의 크기가, 또 그 하위 자식의 크기가, 또또 그 하위 자식의 크기, ....
상대 길이의 단위는 em
rem
vw
vh
등이 있다.
em
부모의 font-size에 대한 상대길이 적용
- [부모] 1em(16px) → [자식] 0.5em (12px)
- [부모] normal → [자식] 0.5em (10px)
부모에 적용할 경우 기본값에 대한 상대길이 적용
- [부모] 2em (32px) → [자식] 0.5em (16px)
rem
font-size
1rem == 16px
, 2rem == 32px
.parent {
color: cornflowerblue;
font-size: 2em; // 32px
}
.child {
color: indianred;
font-size: 0.5rem; // 8px
}
vw
- 100vw : 뷰포트 가로의 100%
- 50vw : 뷰포트 가로의 50%
vh
- 100vh : 뷰포트 세로의 100%
- 50vh : 뷰포트 세로의 50%
.container {
width: 50vw;
hegith: 100vh;
}
vmin
, vmax
- 가로모드 (최대넓이)
.container {
width: 100vmax;
hegith: 100vmin;
}
vmin
, vmax
- 세로모드 (최대넓이)
.container {
width: 100vmin;
hegith: 100vmax;
}
물론 이들은 부모 요소의 영향을 받기 때문에 사용할 때 주의가 필요하다.
상대길이를 통해 폰트 크기나, 화면의 넓이 등을 유연하게 바꿀 수 있는 방법에 대해 알아봤는데, 그렇다면 레이아웃을 미디어쿼리없이 유연하게 바꿀 수 있는 방법은 없을까?
display: flex;
를 통해 유연한 레이아웃을 생성할 수 있다.
.container {
display: flex;
flex-wrap: wrap;
}
.item {
background-color: #ccc;
padding: 10px;
flex-basis: calc(50% - 10px);
margin: 5px;
}
이처럼 길이나 레이아웃을 미디어쿼리 없이 유연하게 변화시킬 수 있는 방법에 대해 알아봤다.
마지막으로 화면 크기 별로 색상이 바뀐다거나, 요소가 보이지 않는다거나 하는 경우는 미디어쿼리를 사용해야 하는데 이럴 때 미디어쿼리를 최소화해서 사용할 수 있는 방법에 대해 알아보자.
말 그대로 디바이스 크기별로 변해야 할 속성을 한 미디어쿼리 안에 작성해놓는 것이다. 여러 미디어쿼리를 하나로 그룹화하면 높은 가독성과 쉬운 유지보수를 기대할 수 있다. 중복 코드를 줄일 수 있고 변경이 필요한 경우 한 곳에서 수정할 수 있기 때문이다.
/* Small devices (landscape phones, 576px and up) */
@media screen and (min-width: 576px) {
.nav {
display: none;
}
.body {
background-color: #000000;
}
}
/* Medium devices (tablets, 768px and up) */
@media screen and (min-width: 768px) {
.body {
background-color: #F2F2F2;
}
}
/* Large devices (desktops, 992px and up) */
@media screen and (min-width: 992px) {
.body {
background-color: #F4F4F4;
}
}
/* X-Large devices (large desktops, 1200px and up) */
@media screen and (min-width: 1200px) { ... }
/* XX-Large devices (larger desktops, 1400px and up) */
@media screen and (min-width: 1400px) { ... }
이렇게 반응형 웹 디자인 구현하기 위한 미디어쿼리의 사용 방법과, 미디어쿼리를 최소화해서 사용하는 법에 대해 알아보았다. 앞으로의 개발도 파이팅이다 아자잣