반응형 웹 디자인(RWD)은 웹사이트가 화면 크기에 따라 레이아웃과 콘텐츠를 조정하는 방식이다. 데스크탑, 태블릿, 스마트폰 등 사용자가 어떤 디바이스를 사용하든 자동으로 조정된다.
별도의 웹사이트를 만들 필요 없이 하나의 웹사이트로 모든 디바이스에서 일관된 사용자 경험을 제공할 수 있다.
HTML은 기본적으로 반응형으로 작동하며, 창 크기를 조정하면 뷰포트에 맞게 자동으로 리플로우한다.
반응형 웹 디자인은 기술이 아닌 접근 방식이다. 모든 기기에 대응할 수 있는 레이아웃을 설명하는 데 사용되는 용어로, 2010년에 만들어졌다.
가변 그리드는 레이아웃을 유연하게 만들어 다양한 화면 크기에 대응할 수 있도록 한다. 고정된 픽셀 값 대신 상대적인 크기(%)를 사용함으로써 구현할 수 있으며, 기본적인 비율로 그리드를 적용한다.
가변 그리드 만으로는 반응형 웹을 만족할 수 없다. 특정 화면 크기에서 레이아웃이 크게 변경되어야 할 경우에 추가적인 조정이 필요하다.
미디어 쿼리는 CSS3에서 도입된 기능으로, 특정 조건에 따라 다른 스타일을 적용할 수 있다.
기본 구조는 다음과 같다.
@media <미디어 타입> and <조건> {
/* 스타일 규칙 */
}
아래는 너비가 600px 이하일 때 폰트 크기를 조정하는 예시이다.
body {
font-size: 16px;
}
@media screen and (max-width: 600px) {
body {
font-size: 14px;
}
}
all
: 모든 디바이스 유형에 적용된다. 기본 타입으로, 다른 타입을 지정하지 않으면 all이 적용된다.
print
: 인쇄 출력용으로 스타일을 적용할 때 사용한다. (ex. 문서를 프린터로 출력할 때, PDF로 저장할 때 등.)
screen
: 화면 디바이스(모니터, 태블릿, 스마트폰 등)에 적용된다. 대부분의 웹사이트에서 사용된다.
speech
: 스크린 리더 같은 음성 출력 디바이스에 적용된다. 시각 장애인을 위한 웹 접근성 향상에 도움된다.
그 밖에도 projection
, tv
, braille
, embossed
등 다양한 타입이 있다.
주로 사용되는 조건은 다음과 같으며, 여러 조건을 복합적으로 사용할 수도 있다.
width
, height
: 뷰포트 또는 요소의 너비와 높이@media (max-width: 600px) {
body {
background-color: black;
}
}
@media (min-width: 600px) and (max-width: 1200px) {
body {
background-color: black;
}
}
orientation
: 디바이스의 방향landscape
, 세로 모드는 portrait
이다.@media (orientation: landscape) {
body {
background-color: black;
}
}
resolution
: 디바이스의 해상도@media (min-resolution: 2dppx) {
body {
background-color: black;
}
}
and
: 조건이 모두 해당되었을 때 적용된다. 아래 예시는 너비가 600 이상이고, 가로 모드인 경우에 해당한다.@media screen and (min-width: 600px) and (orientation: landscape) {
body {
color: blue;
}
}
or
: 조건 중 하나라도 해당되면 적용된다. 아래 예시는 너비가 600 이상이거나, 가로 모드인 경우에 해당한다.@media screen and (min-width: 600px), screen and (orientation: landscape) {
body {
color: blue;
}
}
not
: 조건의 의미를 반대로 한다. 따라서 아래 예시는 세로 모드인 경우에 해당한다.@media not all and (orientation: landscape) {
body {
color: blue;
}
}
react-responsive는 React에서 반응형 디자인을 구현하기 위한 라이브러리이다.
CSS 미디어 쿼리와 유사하게 조건부로 컴포넌트를 렌더링할 수 있다.
React 컴포넌트로 미디어 쿼리를 정의하여 보다 직관적이고 효율적으로 구현할 수 있다.
서버 사이드 렌더링(SSR)을 지원하여 초기 페이지 로드 시에도 반응형 디자인을 적용할 수 있다.
import React from 'react';
import { useMediaQuery } from 'react-responsive';
const Example = () => {
const isDesktopOrLaptop = useMediaQuery({ minWidth: 1224 });
const isTabletOrMobile = useMediaQuery({ maxWidth: 1224 });
const isPortrait = useMediaQuery({ query: '(orientation: portrait)' });
return (
<div>
{isDesktopOrLaptop && <p>데스크탑 또는 랩탑</p>}
{isTabletOrMobile && <p>태블릿 또는 스마트폰</p>}
{isPortrait && <p>세로 모드</p>}
</div>
);
};
export default Example;
전달하는 인자의 형식에는 두 가지 방식이 있다.
{minWidth: 1224}
처럼 간단한 객체를 사용하여 라이브러리가 내부적으로 미디어 쿼리 문자열을 생성할 수 있다. 사용하기 간편하지만, 라이브러리에 미리 정의된 것만 사용할 수 있어 제한적이다.
{ query: '(min-width: 1224px)' }
처럼 미디어 쿼리 문자열을 직접 정의할 수도 있다. CSS 미디어 쿼리 구문을 그대로 사용하여 더 복잡한 미디어 쿼리를 작성할 수 있다.
import React from 'react';
import MediaQuery from 'react-responsive';
const MyComponent = () => {
return (
<div>
<MediaQuery minWidth={1224}>
<div>데스크탑 또는 랩탑</div>
</MediaQuery>
<MediaQuery maxWidth={1224}>
<div>모바일 또는 태블릿</div>
</MediaQuery>
</div>
);
};
export default MyComponent;
<Media>
와 유사하지만, 라이브러리에 정의된 객체를 사용하여 보다 직관적으로 작성할 수 있다.
import React from 'react';
import { Media } from 'react-responsive';
const MyComponent = () => {
return (
<div>
<Media query="(min-width: 1224px)">
{matches => matches && <div>데스크탑 또는 랩탑</div>}
</Media>
<Media query="(max-width: 1224px)">
{matches => matches && <div>모바일 또는 태블릿</div>}
</Media>
</div>
);
};
export default MyComponent;
미디어 쿼리 조건을 만족하면 matches
에 true
가, 그렇지 않으면 false
가 온다.
CSS 미디어 쿼리 구문을 그대로 사용하여 보다 복잡한 미디어 쿼리를 작성할 수 있다.