반응형 페이지란?
뷰포트(Viewport) 사이즈에 따라 정적인 웹 페이지의 요소가 잘 보이지 않거나, 텍스트의 줄 바꿈이 깨지는 경우가 있다. 때론 디바이스에 따라 요소들의 배치, 사이즈, 구성 등을 유연하게 조정해줘야 하는 경우도 있다. 즉, 사용자가 웹 페이지에 접근한 디바이스의 종류나 뷰포트 사이즈(웹 애플리케이션이 구동되고 있는 프로그램의 사이즈) 등 환경에 따라 UI가 유동적으로 바뀌는 게 필요할 수 있는 셈이다.
이러한 필요로 인해 등장한 것이 반응형 페이지(Responsive Page)이다. 반응형 페이지는 사용자가 웹 애플리케이션을 사용하는 환경을 고려해서 HTML과 CSS 요소가 뷰포트 사이즈 변동에 따라 유기적으로 변동된다.
반응형 페이지와 함께 자주 언급되는 개념으로 '적응형 페이지(Adaptive Page)'가 있다. 적응형 페이지도 사용자가 애플리케이션을 사용하는 환경을 고려하는 방식이다. 다만, 적응형 페이지의 다른 점은, 사용자의 환경에 따라 전혀 다른 HTML과 CSS 파일을 적용시킨다는 것이다. 즉, 데스크톱과 모바일에서 각각 적응형 페이지 서비스를 사용한다면 데이터를 처리해 주는 서버는 공유될 수 있겠지만, 사실상 서로 다른 정적 파일이 적용되기 때문에 다른 웹 사이트라고 해도 과언이 아니다(실제로 적응형 페이지로 기기에 따라 기능이나 로직의 차이를 두기도 한다).
반응형 페이지는 이와 달리, 하나의 HTML-CSS 페이지 내에서 사용자의 환경을 고려해 다른 배치와 디자인을 적용하는 식으로 구현된다. 즉, 반응형 페이지의 경우 웹과 모바일이 동일한 HTML-CSS 파일을 공유한다는 것이다. 그리고, 해당 방식의 개발을 하기 위한 다양한 방식이 있다.
HTML-CSS와 반응형
HTML과 CSS는 기본적으로 반응형으로 동작한다. 예를 들어, 아래와 같이 아무 태그로도 감싸지 않고 긴 문장을 표현해보면 문장이 뷰포트 사이즈의 변화에 따라 자동으로 줄 바꿈이 되는 게 확인된다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>EXAMPLE</title>
</head>
<body>
Lorem ipsum odor amet, consectetuer adipiscing elit. Mi rutrum interdum tempor morbi vel
himenaeos taciti. Conubia hendrerit et sed bibendum pretium class. Rhoncus hendrerit ipsum
sagittis placerat non id. Dignissim fringilla commodo parturient ridiculus ligula a quisque
senectus. Vestibulum feugiat venenatis ex sagittis conubia. Enim rutrum convallis sit
habitasse litora eget mattis amet. Risus dignissim dictum maecenas; rutrum fames faucibus.
Vehicula suspendisse dictum suspendisse ultrices tempus. Condimentum rhoncus sagittis
blandit semper sociosqu in. Interdum tempor aptent quis enim nec erat. Natoque a maximus
neque est sollicitudin? Luctus praesent leo mollis convallis conubia diam parturient. Magna
taciti nostra dictum scelerisque cubilia augue. Senectus in viverra ornare venenatis
molestie leo. Ut phasellus nam finibus natoque inceptos. Gravida himenaeos natoque mus proin
senectus morbi amet. Parturient per mi mauris platea ut.
</body>
</html>
작성한 문장이 뷰포트 사이즈 변경, 화면의 배율 변경에 반응하여 자동으로 줄바꿈을 해주고 있다. 물론, 모든 HTML의 요소가 반응형으로 동작하는 것은 아니지만, 그래도 기본적으로 HTML은 사용자의 이용 환경에 대한 고려를 어느 정도는 알아서 해주고 있는 셈이다.
만약에 CSS까지 함께 사용한다면 좀 더 쉽게 여러 요소를 반응형으로 처리할 수 있다. 예를 들어, div
요소의 크기를 뷰포트 width
사이즈 기준 퍼센티지(%
)로 적용하면 뷰포트 사이즈의 변경에 맞게 자동으로 요소의 크기가 변경되는 게 확인된다(div
태그 안에 있는 p
태그는 반응형으로 자동 줄 바꿈이 되기 때문에 박스 영역을 벗어나지 않고 함께 반응형 처리가 잘 이루어진다).
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./style.css" />
<title>EXAMPLE</title>
</head>
<body>
<div class="container">
<p class="text">
Lorem ipsum odor amet, consectetuer adipiscing elit. Mi rutrum interdum tempor morbi
vel himenaeos taciti. Conubia hendrerit et sed bibendum pretium class. Rhoncus
hendrerit ipsum sagittis placerat non id. Dignissim fringilla commodo parturient
ridiculus ligula a quisque senectus. Vestibulum feugiat venenatis ex sagittis
conubia. Enim rutrum convallis sit habitasse litora eget mattis amet. Risus
dignissim dictum maecenas; rutrum fames faucibus. Vehicula suspendisse dictum
suspendisse ultrices tempus. Condimentum rhoncus sagittis blandit semper sociosqu
in. Interdum tempor aptent quis enim nec erat. Natoque a maximus neque est
sollicitudin? Luctus praesent leo mollis convallis conubia diam parturient. Magna
taciti nostra dictum scelerisque cubilia augue. Senectus in viverra ornare venenatis
molestie leo. Ut phasellus nam finibus natoque inceptos. Gravida himenaeos natoque
mus proin senectus morbi amet. Parturient per mi mauris platea ut.
</p>
</div>
</body>
</html>
.container {
width: 60%;
background-color: #38bdf8;
border-radius: 10px;
padding: 20px 40px;
}
.text {
font-size: 14px;
text-align: justify;
}
이외에도 flex
, grid
등을 사용해 요소들의 영역을 잡고, 자연스럽게 반응형으로 동작하도록 사용이 가능하다. 즉, 기본적으로 HTML과 CSS는 사용자의 환경에 맞게 반응형으로 요소를 배치하기 위한 최소한의 기능이 제공되는 셈이다.
미디어 쿼리(Media Query)
HTML과 CSS는 반응형 구현을 위한 다양한 기능을 이미 제공하고 있다. 뿐만 아니라, 자바스크립트의 이벤트 객체와 DOM API까지 이용하면 사실상 모든 반응형 처리를 하는 것이 가능하다(예를 들어, 자바스크립트의 전역 window
객체의 사이즈 변화를 resize
이벤트로 감지하고, window.innerWidth
와 window.innerHeight
를 이용해 뷰포트의 사이즈를 수치로 받아와서, 조건문을 통해 분기처리한 후 원하는 요소의 클래스 명을 추가하거나 삭제해 가면서 CSS를 원하는 방식으로 다르게 적용하는 것이 가능하다).
말로 설명은 해놨지만, 실제로 구현을 해보지 않은건 너무나도 귀찮기 때문이다. 자바스크립트로 뷰포트 사이즈 변화를 감지하려면 window
객체에 이벤트 핸들러를 달아줘야 하고, 이벤트가 발생하면 window
객체에서 지속적으로 변하는 width
와 height
값을 관찰하고(디바운스나 스로틀링을 사용하면 이벤트 발생 횟수를 제어할 수 있지만, 아무튼 개발자에게나 컴퓨터에게나 많은 비용이 드는 일이긴 하다), 조건에 맞는 분기문과 요소에 클래스 추가, 그리고 클래스 변화에 따라 다르게 적용될 CSS 작성을 모두 해줘야 한다. 이 모든 걸 해둬야 HTML, CSS, 자바스크립트만 가지고 반응형 구현이 가능한 것이다.
하지만, 이러한 방식은 너무나 귀찮고 번거롭기 때문에, 해당 과정을 도와주는 도구를 사용하는 것이 권장된다. 그리고, 해당 작업에 사용될 수 있는 도구가 바로 미디어 쿼리(Media Query)이다.
미디어 쿼리는 CSS가 제공하는 자체적인 기능이다(CSS 표준에 포함되어있다). 미디어 쿼리의 사용 문법은 아래와 같다.
@media media-type and (media-feature-rule) {
/* 적용할 CSS */
}
일단 해당 문법을 사용해서 반응형 처리를 해보고, 그 다음 각각에 대해 좀 더 자세히 살펴보겠다. 아래는 미디어 쿼리를 이용해 뷰포트 사이즈가 600px
보다 작아지면 div
컨테이너의 색깔을 변경하는 코드다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
.container {
background-color: #38bdf8;
width: 500px;
height: 500px;
}
@media screen and (max-width: 600px) {
.container {
background-color: #f85a4b;
}
}
</style>
<title>EXAMPLE</title>
</head>
<body>
<div class="container"></div>
</body>
</html>
하나씩 살펴보겠다. 먼저, 미디어 쿼리를 사용하기 위해 @media
라는 CSS 조건부 스타일을 문법을 사용해야 한다. 그리고, @media
바로 뒤에는 screen
은 웹 애플리케이션이 사용되는 미디어 유형을 의미한다. screen
은 데스크톱-모바일 기기의 화면을 의미하며, 인쇄를 위한 미디어 쿼리에선 print
를 사용한다(HTML는 '문서'고, CSS는 '문서를 꾸미기 위한 스타일링 언어'이다. 기본적으로 문서를 전제하기 때문에 미디어 유형에 인쇄가 고려된 것 같다).
미디어 유형 위치에 all
과 only
도 사용할 수 있다. all
을 쓰면 모든 미디어 유형을 전부 고려하는 미디어 쿼리가 되고, only
를 쓰면 하나의 미디어 유형만을 고려하게 된다(only screen
처럼 사용한다). 미디어 유형을 정의하지 않으면 기본적으로 all
이 적용된다.
미디어 유형 다음, and
는 앞과 뒤에 있는 모든 조건이 일치할 때를 의미한다. 그리고 and
뒤에 있는 max-width: 600px
는 미디어 쿼리가 적용되는 조건을 의미한다. 작성한 쿼리는 뷰포트의 최대 width
가 600px
일 때를 의미하기 때문에, 뷰포트가 600px
이하일 땐 미디어 쿼리 안에 있는 CSS가 적용되고, 600px
초과일 땐 미디어 쿼리 밖의 CSS가 적용된다.
참고로, 미디어 쿼리의 CSS는 미디어 쿼리 밖에 선언된 같은 CSS 속성을 덮어쓰고, 선언되지 않은 CSS 속성을 추가하기만 한다. 미디어 쿼리 밖의 CSS를 완전히 덮어쓰는 게 아니다. 아래 예시를 보면, 미디어 쿼리 밖에서 선언된 border-radius: 15px
는 미디어 쿼리 안에서 조건에 해당하는 CSS가 적용될 때에도 동일하게 적용되는 게 확인된다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
.container {
background-color: #38bdf8;
border-radius: 15px;
width: 500px;
height: 500px;
}
@media screen and (max-width: 600px) {
.container {
background-color: #f85a4b;
}
}
</style>
<title>EXAMPLE</title>
</head>
<body>
<div class="container"></div>
</body>
</html>
결론
모든 반응형 웹을 구현하는 데 있어서 미디어 쿼리가 능사는 아니다. flex
와 grid
를 잘 이용하면 미디어 쿼리의 도움 없이도 적절하게 반응형 처리를 하는 게 가능하다. 물론, 미디어 쿼리는 사용법도 간단하고, 굉장히 직관적으로 적용이 가능하기 때문에, 필요에 따라서 적절히 활용해도 문제는 없을 것 같다(사실, 사이드 이펙트가 있는지 확인해 본 건 아니긴 하다. 그래도 CSS 표준 문법이고, 외부의 도구를 가져와서 사용하는 게 아니기 때문에, 사이드 이펙트가 덜 하지 않을까 생각한다).
포스트에선 미디어 쿼리의 간단한 사용법만 알아봤다. 미디어 쿼리에도 보다 디테일하고 많은 내용들이 있긴 한데, 자세한 미디어 쿼리 사용에 대한 정보는 MDN 문서에서 참조할 수 있다(굳이 다 외울 필요 없이, 필요할 경우 찾아보면서 하면 될 것 같다).
'HTML-CSS' 카테고리의 다른 글
input 태그로 Date Picker 구현하기 (1) | 2024.12.04 |
---|---|
프로젝트에 module.css 적용하기 (1) | 2024.12.03 |
사용자 지정 CSS 속성(CSS 변수) 사용하기 (0) | 2024.12.02 |
HTML label 태그 사용하기 (1) | 2024.11.17 |
Form 태그의 유용한 기능들 (0) | 2024.11.10 |