IT/HTML & CSS

반응형 웹 사이트 만들기(반응형 웹 단위도 같이 알아보기)

라임웨일 2022. 11. 23. 12:36
반응형

 

📘 반응형 웹이란?

웹 사이트는 크게 적응형과 반응형으로 나눌 수 있습니다. 

아니 적응형은 뭐고 반응형은 또 뭔가요??🥶🥶🥶

 

적응형은 사용자의 환경에 최적화 되게 PC와 모바일 환경을 구분해서 두 개의 웹 사이트 주소로 각각 구성된 화면을 보여줍니다. 

예를 들어 모바일 사용자가 네이버에 접속하면 m.naver.com에 접속되고 PC 사용자는 www.naver.com 주소로 접속 됩니다. 반면 반응형은 웹 사이트 크기에 따라서 화면의 UI가 변경되면서 사용자에게 최적화된 화면을 제공해주는 방식입니다. 

 

두 개의 가장 큰 차이점은 하나의 소스로 관리되며 화면의 브라우저 크기에 맞게 최적화된 UI를 제공하는가(반응형) 아니면 두 개의 소스로 관리하면서 사용자에게 모바일, PC의 최적의 화면을 각각 제공하는가의 여부가 차이점이라고 할 수 있습니다. 

 

적응형과 반응형은 각각 장점과 단점이 명확하기 때문에 회사의 상황과 여러 환경적인 요소를 고려해서 사용하면 될 것 같습니다.

 


1. meta 태그 & viewport

html 최단에 아래와 같은 메타 태그가 들어있는 것을 본적이 있나요? 아마 요즘은 대부분의 기본 html 화면에는 거의 다 들어있다고 봐도 무방한데요.

<meta name="viewport" content="width=device-width,initial-scale=1">

 

위의 메타 태그는 뷰포트라는 것으로 위의 메타태그가 설정되어 있어야만 우리는 반응형 웹을 만들 준비가 되는 것입니다. (위의 메타태그가 없으면 브라우저 엔진은 해당 웹이 반응형 웹인지 인지하지 못해요!!!!!😥)

 

뷰포트(viewport)란, 웹 페이지에서 사용자의 보이는 영역(visible area)을 말합니다. 따라서 이는 기기별로 달라지게 됩니다. 같은 페이지라 하더라도 모바일과 태블릿은 화면 크기가 다르기 때문에 사용자가 볼 수 있는 범위가 다르니까요.

즉, 이 태그는 뷰포트를 지정해주는 역할을 합니다.

 

좀 더 자세히 알아볼게요!!

- width

width는 뷰포트의 가로 크기를 정합니다. 만약 500이란 값을 넣으면, 500만큼의 픽셀 개수를 가진 너비로 설정됩니다. device-width라고 지정했으니, 기기의 스크린 너비에 맞추라는 뜻이 됩니다.

- initial-scale

initial-scale은 페이지에 처음 접속했을 때 보여질보일 확대 배율을 설정합니다. 1로 정하면 CSS 픽셀과 화면에 보일 픽셀이 1:1을 이룹니다. 달리 말해, 이 값이 1보다 작다면 페이지는 축소되어 보이고, 1보다 크다면 확대되어 보입니다.

width 뷰포트의 가로 크기
initial-scale 페이지 처음 접속 시 보여질 배율

 

뷰포트 메타태그에는 아래의 속성들도 들어갈 수 있어요.

user-scalable 사용자의 축소/확대 허용 여부. 초기값은 yes며, no로 금지 가능
minimum-scale 뷰포트의 최소 배율값 (0~10)
maximum-scale 뷰포트의 최대 배율값 (0~10)

 

 

네이버 모바일 화면의 메타태그 속성을 보면 user-scalable=no이 지정된 걸 볼 수 있습니다. 즉, 사용자가 줌인이나 줌아웃을 할 수 없도록 막아둔 상태입니다. minimum-scale과 maximum-scale도 1.0으로 지정했기 때문에 고정된 UI를 항시 보여줄 수가 있습니다.

 

다만, 이 경우엔 웹 접근성 관련해 경고 카드를 받을 수도 있어요. 아래는 이걸 본 validator.w3.org와 lighthouse가 날린 경고장입니다 😞

 

 

정리하자면, 메타 태그로 뷰포트를 지정해 주면 모바일 친화적인 UI를 제공할 수 있게 됩니다.

자 이제 반응형 웹 사이트를 만들 준비가 되었습니다. 

다음 단계는 미디어 쿼리입니다. 


2. 미디어 쿼리

미디어 쿼리는 반응형 웹을 구성하기 위한 기본이자 핵심입니다.

media라는 키워드로 사용하며, 아래는 미디어 쿼리를 활용한 예시입니다.

.title {
  font-size: 40px;
}

@media (max-width: 600px) {
  .title {
    font-size: 20px;
  }
}

타이틀의 텍스트 기본 크기를 40px로 정의하였지만, 브라우저의 화면이 600px보다 작은 화면에서는 20px로 줄인다는 CSS 코드 내용입니다. 

미디어 쿼리 예시 이미지

- 미디어쿼리 적용

미디어 쿼리를 적용하는 법은 간단합니다.

 

1) CSS 파일 내에 직접 작성하거나

@media (min-width:768px) {}

 

2) <link> 태그에 media 속성을 설정해 사용합니다

<link rel="stylesheet" media="all and (min-width:1200px)" href="desktop.css" >
<link rel="stylesheet" media="all and (min-width:768px) and (max-width:1199px)" href="laptop.css" >

 

대부분의 경우 첫 번째 방법을 사용합니다. 왜냐하면 두 번째 방법처럼 CSS를 분리해 두더라도, 브라우저의 랜더링 과정 속에서 브라우저는 일단 모든 CSS 파일을 다운로드하기 때문입니다. (이 내용은 브라우저의 동작원리에 대한 글을 참고하면 좋습니다. 저도 해당 내용글을 잘 정리해 놓았으니 그 글을 참고하는 것도 아주 좋은 선택일 것 같습니다.)

HTTP 요청이 많아지면 성능이 그만큼 저하되므로, 기본적인 방법은 CSS 파일 내에서 @media로 분기하여 사용합니다.

 

구문

미디어 쿼리 구문은 '미디어 유형 / 논리 연산자 / 특성'으로 이루어지며 대소문자를 구분하지 않습니다.

 

미디어 유형

all 모든 디바이스 대상
print 인쇄 결과물 및 인쇄 미리보기 문서
screen 화면 대상

 

@media screen {}을 쓰면, 스크린이 있는 디바이스에서만 적용이 됩니다. 이외에도 여러 유형이 있지만 제일 많이 쓰는 건 all과 screen입니다. 유형을 지정하지 않은 경우엔 디폴트인 all이 지정됩니다.

 

논리 연산자

and 모든 쿼리가 참이여야 적용
not 모든 쿼리가 거짓이여야 적용
, (comma) 어느 하나라도 참이면 적용 (or에 해당)
only 미디어쿼리를 지원하는 브라우저만 적용

 

여기서 only라는 생소한 키워드가 나왔네요!

 

@media only screen {}을 사용하면 미디어쿼리를 지원하지 않는 브라우저(IE8 이하)에서는 해당 스타일을 무시합니다.

더 정확히 얘기하자면, 미디어쿼리를 지원하는 브라우저는 only 키워드를 만나면 무시하고 그대로 읽어 들입니다.

반면에 지원하지 않는 브라우저는 only라는 이름의 미디어 유형이 있다고 생각합니다.

하지만 only라고 정의된 미디어 종류는 없기 때문에, 결국 아무것도 적용되지 않는 거죠.

 

특성

width 뷰포트 너비
height 뷰포트 높이
aspect-ratio 뷰포트 가로세로비
orientation 뷰포트 방향

 

orientation의 경우, 아쉽게도(?) 모바일 전용 속성이 아닙니다. '가로가 세로보다 긴지' 또는 '세로가 가로보다 긴지'에 따라 가로 모드/세로 모드라고 판단합니다. 만약 모바일 환경에만 특정 CSS를 적용해야 한다면 User Agent를 판단 후 분기해야 합니다.

 

이런 식으로 유형, 연산자, 특성을 조합해 다양한 구문을 만들어 낼 수 있습니다.

@media all and (min-width:768px) and (max-width:1080px) {}
/* '모든 디바이스 & 최소 너비가 768 이상 & 최대 너비가 1080 이하'라는 조건을 모두 만족할 때 */
@media (min-height: 680px), screen and (orientation: portrait) { ... }
/* '최소 높이가 680 이상'이거나 '세로 모드의 스크린 기기' 중 하나를 만족하는 경우에 적용*/

 

미디어 쿼리의 스펙 문서를 살펴보면 이외에도 정말 많은 특성을 만나볼 수 있습니다. 예를 들면, 미디어 쿼리 레벨 4 스펙에서 추가된 hover나 pointer등이 있습니다.

 

@media (hover: hover) and (pointer: fine) { }를 써서 마우스나 트랙패드가 있는 기기를 조건으로 하는 구문을 만들 수 있습니다. 하지만 최신 스펙에는 언제나 지원 브라우저가 제한되어 있다는 한계가 존재하죠 😕

실무에서는 특성에 주로 width 값을  기준으로 사용합니다.

 

- 모바일과 데스크탑, 무엇을 먼저 기준값으로 정해야 하는 것일까?

미디어 쿼리의 분기는 대부분 width 값을 사용하는데, 이때 min을 쓸지 max를 쓸지 고민될 때가 있죠. 방법은 여러 가지가 있겠지만, 아래의 예를 참고해서 작업하면 수월할 것 같습니다.

 

- 모바일 퍼스트: min

- 데스크탑 퍼스트 : max

 

모바일 퍼스트는 말 그대로 모바일 우선입니다. 따라서 모바일에 대한 스타일이 우선 적용되도록, 분기점(break point)이 낮은 순대로 작성해 나갑니다.

 

/* Mobile First */
.title { font-size: 12px; }

@media (min-width: 640px) {
  .title { font-size: 14px; }
}

@media (min-width: 768px) {
  .title { font-size: 16px; }
}

@media (min-width: 1024px) {
  .title { font-size: 18px; }
}

 

위와 같이 작성한 경우, iPhoneX 사이즈(375px)의 기기에서는 폰트 사이즈가 어떻게 될까요?

어떠한 미디어 쿼리 구문도 만족하지 못하므로 12px이 적용됩니다.

 

한편, 800px 너비의 뷰포트에서 본다면요?

우선 12px이 적용되지만, 최소 너비 640이란 조건을 만족하므로 스타일을 덮어써서 14px이 됩니다.

또, 최소 너비 768이라는 조건도 만족하므로 스타일을 다시 덮어써서 16px이 됩니다.

하지만 최소 너비 1024는 만족하지 못한 상태이므로 16px이 그대로 유지돼요.

 

 

 

반면에 데스크탑 퍼스트는 분기점(break point)을 높은 순서부터 작성합니다.

이 경우에는 뷰포트 값이 작아질수록 스타일을 덮어쓰는 방식으로 적용이 되겠죠!

 

/* Desktop First */

.title { font-size: 18px; }

@media (max-width: 1023px) {
  .title { font-size: 16px; }
}

@media (max-width: 767px) {
  .title { font-size: 14px; }
}

@media (max-width: 639px) {
  .title { font-size: 12px; }
}

 

보이는 결과물은 똑같기에 크게 상관은 없으며, 작성 방식에만 차이가 있어요. 

다만 한 가지 방법을 정했다면 (Min or Max) 정한 방법으로 동일하게 작성하는 것이 좋습니다. 어떤 구문에서는 Min속성을 사용하고 어떤 속성에서는 Max 속성을 사용한다면 이는 추후에 CSS가 충돌하게 되는 요소가 되고 유지보수 또한 어려워지게 됩니다. 

 

- 도와줘요 믹스인😉 (좀 더 유용하게 코드를 작성해봐요)

미디어 쿼리를 멋지게 쓰는 건 좋지만, 구문과 분기점을 항상 외우고 다닐 순 없죠. 그럴 땐 믹스인을 만들어 쓰면 좋습니다. 유지보수도 매우 편해져요!

 

미디어 쿼리를 관리하기 위한 scss 파일을 만들어 주세요.

분기점은 변수로 만들고, @content로 내용이 비워져 있는 믹스인을 작성합니다.

// Break Point
$tablet: 768px;
$laptop: 1020px;
$desktop: 1400px;

// Mixins
@mixin tablet {
  @media (min-width: #{$tablet}) {
    @content;
  }
}

@mixin laptop {
  @media (min-width: #{$laptop}) {
    @content;
  }
}

@mixin desktop {
  @media (min-width: #{$desktop}) {
    @content;
  }
}

 

이제 @include로 불러와 사용합니다.

// SCSS

.logo {
  width: 20px;

  @include desktop {
    width: 40px;
  }
}
/* 컴파일된 CSS */

.logo {
  width: 20px;
}

@media (min-width: 1400px) {
  .logo {
    width: 40px;
  }
}

위와 같이 사용하면 보다 쉽게 미디어 쿼리를 사용할 수 있습니다.

 

 

중첩 미디어 쿼리

믹스인을 사용할 때 아래처럼 미디어 쿼리를 별도로 작성할 수도 있지만,

/* 미디어 쿼리를 별도로 작성하는 경우 */

.title {
  font-size: 12px;
}

.logo {
  width: 20px;
}

@include laptop {
  .title {
    font-size: 14px;
  }

  .logo {
  width: 30px;
  }
}

 

요소 바로 밑에 작성하는 방법도 있습니다. 바로 아래처럼요.

/* 미디어 쿼리를 바로 아래에 작성하는 경우 */

.title {
  font-size: 12px;

  @include laptop {
    font-size: 14px;
  }
}


.logo {
  width: 20px;

  @include laptop {
    width: 30px;
  }
}

 

위의 방식대로 작성하는 경우, 반응형 디자인을 바로 확인할 수 있어 직관적이라는 장점이 있습니다.

특히 분기점이 많아질수록 보기가 편하며 유지보수에도 좋습니다.

 

한 가지 아쉬운 점이 있다면, 컴파일한 CSS에서 미디어 쿼리 구문이 계속 중복된다는 점입니다.

아래 코드를 보면 미디어쿼리 1020px 부분과 1600px 부분이 하나의 구분점으로 작성될 수 있는데 각각 생성되었습니다. 

/* 컴파일 후 중복되는 미디어 쿼리 구문 */

.title {
  font-size: 12px;
}
@media (min-width: 1020px) {
  .title {
    font-size: 14px;
  }
}

@media (min-width: 1600px) {
  .title {
    font-size: 16px;
  }
}

.logo {
  width: 20px;
}
@media (min-width: 1020px) {
  .logo {
     width: 30px;
  }
}
@media (min-width: 1600px) {
  .logo {
    width: 40px;
  }
}

 

성능에 큰 영향을 줄 만한 요소는 아닌 것 같지만, 이왕이면 짧은 CSS가 좋겠죠. 이럴 땐 중복되는 미디어 쿼리 구문을 합쳐주는 도구를 쓰면 아래처럼 깔끔해져요

gulp를 사용 중이시라면 'gulp-group-css-media-queries'를 설치해서 사용할 수 있습니다. 

var gulp = require('gulp');
var gcmq = require('gulp-group-css-media-queries');

gulp.task('default', function () {
  gulp.src('src/style.css')
 .pipe(gcmq())
 .pipe(gulp.dest('dist'));
});
/* 중복되는 미디어 쿼리 구문 제거 */

.title {
  font-size: 12px;
}

.logo {
  width: 20px;
}

@media (min-width: 1020px) {
  .title {
    font-size: 14px;
  }
  
  .logo {
    width: 30px;
  }
}

 

지금까지 뷰포트 메타 태그와 미디어 쿼리에 대해 살펴보았습니다. 사실 이 두 개만 활용해도 멋진 반응형을 만들 수 있습니다. 하지만 빠르게 반응형을 만들어야 하거나, 분기점을 하나하나 고려하기가 힘들 때 유용하게 써먹을 수 있는 vw이나 rem 같은 CSS 속성들이 있습니다.

 

좀 더 쉽게 반응형을 구현할 수 있는 속성에 대해 알아보겠습니다.


1. vw / vh

CSS 작업을 할 때 주로 사용하는 단위의 기본은 픽셀(px)을 가장 일반적으로 사용합니다. 하지만 px값은 고정값이기 때문에 화면의 크기에 대한 변경에 유연하게 대응하기 위해서는 유동 단위인 %를 사용하면 좀 더 유연한 코드를 만들 수 있습니다. 예를 들어 width:50%로 지정해두면 항상 부모의 절반 사이즈를 가지니까 이것 역시 좋은 반응형 CSS죠!

가장 기본적인 % 말고도 유연한 값을 가지는 단위가 몇 개 있는데요, 우선은 vw, vh라는 친구들을 만나봅니다 🙋‍♀️

 

[ v, 뷰포트를 기준으로 하다 ]

이들의 풀네임은 Viewport Width / Viewport Height입니다. 이름에서 유추할 수 있듯이 뷰포트를 기준으로 한 단위입니다.

뷰포트는 '보이는 영역'이라고 했으니, 결국 보여지는 영역에서 얼마만큼 차지할 것인지를 지정하는 단위라 말할 수 있습니다.

 

'1vw = 뷰포트 너비의 1%'로 계산됩니다. 그렇다면 500px 너비인 뷰포트에서 1vw의 값은? 5px이 되겠네요.

만약 브라우저의 가로 사이즈가 유동적으로 변경된다면(500px -> 850px로 변경) 브라우저는 정의된 1vw의 값을 다시 알아서 계산해 줍니다.

따로 미디어 쿼리를 써주지 않았음에도 불구하고 1vw = 8.5px / 10vw = 85px으로 값이 커지게 됩니다.

 

 

vh단위도 똑같이 계산해요! '1vh = 뷰포트 높이의 1%'입니다. 따라서 800px 높이의 뷰포트에서 1vh = 8px이 됩니다.

 

vw와 vh 활용법

이들 단위는 뷰포트 영역 전체를 차지하게 하거나, 그 일부분만 차지하게 하는 데 유용하게 쓸 수 있습니다.

속성 값으로 100vw, 100vh만 써도 가로와 세로의 높이를 모두 채울 수 있어요! 사용자가 브라우저 창 크기를 바꾸거나 모바일 화면을 회전시켜도 상관이 없습니다.

 

또, 이들을 calc() CSS속성과 함께 사용하면 좀 더 좋은 코드를 작성할 수 있습니다. 가령 헤더 영역 높이가 50px이고 콘텐츠 영역 높이를 '헤더를 제외한 나머지 높이 전체'로 만들고 싶다면, height: calc(100vh - 50px);을 지정해주면 됩니다.

 

그럼 여기서 의문이 들텐데요. 도대체 % 와 다른 게 무엇이냐?라는 의문이 생길 수 있습니다. height: 100%로 지정해도 100vh처럼 전체 높이를 차지할 수 있지 않나요?라는 의문이 생기셨다면 아주 잘 이해하고 계신 겁니다. 


결론적으로 말씀드리면 상황에 따라서 맞기도 하고 틀리기도 합니다. % 는 vh와 달리 해당 속성 값을 부여한 바로 위 부모 요소를 기준으로 계산한다는 점에서 차이가 있습니다.

 

예를 들어, 뷰포트 높이를 꽉 채우는 섹션이 있는 페이지를 만든다고 해봅시다. 이때, height: 100%를 지정하려면 부모에게도 height: 100%을 지정해야 합니다. 그래야 상속받아서 쓸 수 있어요. 또한 가장 최상위인 body, html에도 height: 100% 속성을 지정해야 하죠.

 

- 퍼센트로 작성한 예

html, body {
  height: 100%; //부모의 높이 지정 필요
}

.wrap {
  height: 100%; //부모의 높이 지정 필요
}

.section {
  height: 100%;
}

 

반면, height: 100vh를 지정하면 부모의 높이에 무관하게 전체 영역을 차지합니다. vh는 부모가 아닌, 뷰포트를 기준으로 한 단위니까요!

 

- vh로 작성한 예

.section {
  height: 100vh;
}

 

 

vw와 vh는 너비나 높이값에만 쓸 수 있는 건 아닙니다. 폰트 사이즈나 여백 등에 다양한 속성에 쓸 수 있습니다. 즉, font-size: 10vw;와 같이 지정하면 뷰포트가 넓어지면 폰트 크기도 그에 맞춰 커지게 되겠죠. vw, vh를 잘 활용하면 모바일 반응형에 유용하게 쓸 수 있는 단위입니다.

참고로 vw와 vh는 IE9부터 지원하는 속성입니다. (Can I Use : vw)

 

 

2. vmin / vmax

이 친구들은 이름이 vw, vh랑 비슷한데 hoxy...?

넵, vmin과 vmax도 viewport를 기준으로 하는 단위입니다. 하지만 뭔가 다른 역할을 하니 이름이 다르겠죠?! 이들은 vw와 vh 중 더 작거나 큰 것을 찾아 적용합니다.

 

[ vmin과 vmax, 더 작거나 더 크거나 ]

좀 더 정확하게 설명하면 이렇습니다.

 

 

vmin은 vw와 vh 중 더 작은 것을 적용하고, vmax는 vw와 vh 중 더 큰 것을 적용합니다.

 

 

예를 들어 1200px*600px의 뷰포트가 있습니다. 아까 배운 대로 계산하면 1vw = 12px / 1vh = 6px이 됩니다.

따라서 1vmin = 1vh = 6px으로 계산됩니다. 한편 vmax는 더 큰 걸 적용할 테니, 1vmax = 1vw = 12px이 됩니다.

 


이때 뷰포트 크기가 500px*900px로 바뀌었다고 해볼게요. 이렇게 되면 1vw = 5px / 1vh = 9px이 됩니다. 그럼 vmin과 vmax도 이에 영향을 받아 1vmin = 1vw = 5px / 1vmax = 1vh = 9px가 됩니다!

 

vmin과 vmax 활용법

이러면 vw나 vh랑 뭐가 다른가 싶지만,
이들을 잘 사용하면 '언제든 화면에 보이는 요소'와 '언제든 화면을 꽉 채우는 요소'를 쉽게 만들 수 있어요.

 

 

예를 들어 80vw * 80vw로 지정한 요소가 있습니다. 현재 뷰포트는 1000px * 1000px이에요.

80vw = 뷰포트 너비의 80%'으로 계산되므로 이 요소의 실제 크기는 800px * 800px입니다.

 

 

하지만 vw는 너비에만 반응할 뿐, 높이엔 반응하지 않습니다.

그러니 브라우저 높이가 500px로 줄어든다고 해도, vw는 반응하지 않아 요소의 크기는 변하지 않습니다.
결국 800px 높이인 요소는 500px인 브라우저 높이에서 잘려 보이게 됩니다.

 

 

이번엔 가로세로 값이 80vmin인 요소입니다.

1000px * 1000px 뷰포트일 때, 80vw와 마찬가지로 800px * 800px의 크기 값을 가지겠죠?

 

 

이 상태에서 아까처럼 브라우저 높이만 줄여본다면?!

vmin은 둘 중 더 작은 값을 택하기 때문에, 작아진 높이값에 반응해서 잘리지 않고 화면에 표시됩니다.

즉, 너비/높이값 중 무엇이 바뀌던 상관없이 화면에 잘 나타낼 수 있습니다

 

생소한 단위지만 vmin은 IE9부터 사용할 수 있어요! (Can I Use : vmin)

단, vmax는 IE에서 지원되지 않으며 Edge부터 사용 가능합니다. (Can I Use : vmax)

 

 

3. em / rem

[ em, 상위 부모의 폰트를 기준으로 한 단위 ]

em 역시 동적인 단위에요! 재미있게도 이 단위는 폰트 크기의 영향을 받습니다.
'1em = 상위 부모의 폰트 크기'라는 계산법을 가지고 있어요.

 

 

대부분의 브라우저에서 폰트 크기의 디폴트 값은 16px입니다.
따라서 별도로 스타일링을 해주지 않았다면 1em = 16px이 됩니다. 2em이라면 32px이겠죠.

 

만약 상위 부모의 폰트 크기가 20px이라면요? 1em = 20px이 되고, 5em = 100px으로 커지게 됩니다.

즉, 부모의 폰트 크기를 키우면 자식 요소의 크기도 덩달아 커지게끔 할 수 있다는 뜻이죠!

 

음... 하지만 디자인 시안은 px이 기준이니까, 실제로 작업할 때는 px를 기준으로 em으로 바꾸는 작업을 거쳐야겠네요.

만약 시안에 있는 마진 값이 20px이라면 이건 몇 em이 될까요?
기본 폰트 크기가 16px이라고 했을 때, (20/16 = 1.25em)이라는 계산이 나오게 됩니다.

 

이러한 계산을 돕는 온라인 사이트(pxtoem.com)도 있고,

SCSS를 쓴다면 이 계산을 함수로 만들어서 필요할 때마다 사용할 수도 있습니다.

 

- 예제

<div class="parent">
  부모요소
  <div class="child">
  	자식요소
  </div>
</div>
html { font-size: 20px; }
.parent { font-size: 16px; }
.child { font-size: 1em; }

위의 코드에서 child는 몇 px일까요? 정답은 16px입니다. em은 상위 부모의 값을 참조한다는 점만 잊지 않으시면 됩니다. 

 

$browser-font-size: 16;

@function em($pixels, $context: $browser-font-size) {
  @return #{$pixels/$context}em;
}

.title {
  font-size: em(32); // 32/16 = 2em;
}

 

[ rem, 최상위 폰트를 기준으로 한 단위 ]

rem이란 속성도 있습니다. 다른 점이 있다면 rem은 'relative to the root element'라는 점입니다.

HTML 문서에서 최상위 요소(root element)는 바로 <html> 요소를 가리킵니다.

 

 

 

따라서 '1rem = html 요소에 지정된 폰트 크기'로 계산됩니다.

예를 들어, 이러한 구조로 된 문서가 있습니다.

 

- 예제

<div class="parent">
  부모요소
  <div class="child">
  	자식요소
  </div>
</div>
<div class="parent">
  부모요소
  <div class="child">
  	자식요소
  </div>
</div>

 

위의 코드에서 child는 몇 px일까요? 정답은 20px입니다. rem은 최상위 부모의 값을 참조한다는 점만 잊지 않으시면 됩니다. em과 rem의 차이점 확실히 아셨죠?

 

 

em과 rem 활용법

그렇다면 이 두 속성을 어떻게 사용하면 되나요? 간단합니다. 바로 '부모의 폰트 값에 영향을 받는다'는 점을 이용하는 거죠!

예를 들면 이런 식으로 값을 줄 수 있어요.

 

.title { font-size: 30px; }
.title__image { width: 10em; }
.title__text { font-size: 1.5em; }
.title__text-small { font-size: 0.8em; }

 

문제: 위 CSS 중에서 .title의 폰트 값을 50px로 바꾸면 무슨 일이 생길까요?
정답: 아래에 있는 모든 자식들이 영향을 받아서 쑥쑥 커집니다!

 

이걸 응용한다면 미디어 쿼리로. title의 폰트 사이즈만 바꿔주면 별다른 공수 없이 반응형을 손쉽게 만들 수 있어요.

 

.title { font-size: 40px; }
.title__image { width: 10em; } //40px
.title__text { font-size: 0.4em; } //16px


@media all and (max-width: 750px) {
  .title { font-size: 20px ; } // 이제 .title 아래에 있는 모든 em 단위가 영향을 받습니다.
}

 

하지만 em은 계산하기 번거롭기 때문에, 저의 경우에는 em보다도 rem을 주로 사용하고 있어요.

루트 요소의 폰트 크기를 62.5%로 지정하고 rem을 사용하면 훨씬 편해집니다.

 

html { font-size: 62.5%; }
.image { width: 12rem; } //120px
.item { font-size: 1.6rem; } //16px
.copyright { margin-top: 5rem; } //50px

@media all and (max-width: 750px) {
  html { font-size: 50%; } // 이제 문서 내 모든 rem 단위가 영향을 받습니다.
}

 

위 코드를 보면 1rem = 10px이 되어 작성하기가 훨씬 쉽고, 미디어 쿼리로 html 요소의 폰트 사이즈 값만 바꾸면 모든 rem 단위에 영향을 줄 수 있다는 걸 알 수 있습니다. em에 비해 훨씬 편하죠!

 

그게 어떻게 가능하냐면요...

 

html { font-size: 62.5%; }

 

요렇게 생긴 구문 덕분입니다! 이거 보고 뭔 소린가 하신 분? (바로 저요 💁‍♀️)

 

이는 폰트 계산을 더 편하게 하기 위함입니다. 브라우저가 지정해주는 기본 폰트 사이즈는 100% = 16px이죠.
이걸 계산하기 쉽게 62.5% = 10px로 바꿔버리는 거에요.

 

여기서 다시 복습! '1rem = html 요소에 지정된 폰트 크기'로 계산한다고 했었죠. 따라서 위 구문이 있다면 '1rem = 10px'이 됩니다. 그래서 128px = 12.8rem, 4px = 0.4rem 처럼 쓸 수 있습니다. (편-안)

 

em은 IE3부터 지원하며(어르신...), rem은 IE9부터 지원합니다.

단, rem은 IE10 이하에서 단축 속성으로 font를 선언한 경우와 가상 엘리먼트에서 사용할 때는 지원되지 않는다고 합니다. (Can I Use: rem)

 

 

 

근데 왜 %죠?

급 뜬금 퀴즈 타임!

 

html { font-size: 10px; }로 지정해도 결과는 똑같은데 굳이 %로 지정한 이유는?

 

브라우저의 기본 폰트 사이즈는 16px이라고 계속 말했지만, 그건 어디까지나 사용자가 건들지 않았을 경우입니다.

작은 글씨가 불편한 사용자는 웹 브라우저 설정에서 '폰트 기본 사이즈: 크게'와 같이 지정할 수 있어요.

 

 

 

이런 식으로 Large 사이즈를 지정하면 기본 폰트 사이즈가 16px이 아닌 20px이 됩니다. 그런데 우리가 "안됩니다 html은 무조건 10px이여야 해요"이라고 하면 당황스럽겠죠! 웹 접근성 취지에서도 어긋나고요. 하지만 %로 지정해두었으니, 사용자가 폰트 기본 사이즈를 Large로 바꾸든 Small로 바꾸든 그에 대응할 수 있습니다.

rem 단위를 썼을 때 좋은 점은 이러한 경우에도 잘 대응해서 누구에게나 잘 보이는 웹 페이지를 만들 수 있다는 거죠! 👏👏

 


반응형을 처음 만들어보는 분이나 반응형 웹에 자신이 없었던 분, 반응형 웹에 대한 개념을 자세히 알고 싶었던 분들 모두 원하는 결과를 얻었으면 좋겠습니다. 

 

감사합니다.

 

 

출처 :

 

반응형
광고차단(애드블록)프로그램이나 브라우저를 사용중이시면 프로그램을 비활성화이나 블로그 주소를 예외 처리 해주시면 광고가 노출됩니다. 귀찮고 번거롭겠지만 광고 클릭은 저에게는 큰 힘이 됩니다. 🙇🏻‍♂️🙇🏻‍♀️
제 블로그의 모든 글은 제가 직접 작성 하고 다른 글을 참고할 때는 이전 글보다 읽기 편하게 수정해서 작성하고 있습니다. 커피 한잔 사먹고 더 열심히 좋은글로 보답하겠습니다.
오늘도 제 블로그에 와 주셔서 감사합니다. :)
//