본문으로 바로가기

Modernizr(모더나이저)

category Code Lab 2016. 9. 29. 13:15

브라우저 기능 검사를 위한 Modernizr

기존에는 브라우저 호환성을 유지하기 위해 Brower Sniffing 기법(자바스크립트의 navigator.userAgent 프로퍼티를 이용하는 방식)을 사용했습니다.  그러나 나날이 다양한 디바이스가 등장하고 HTML5와 CSS3가 웹표준으로 자리매김하고 있는 상황에서 브라우저마다 HTML5와 CSS3의 구현 정도가 달라 기존의 brower sniffing 방식으로는 이러한 브라우저간의 호환성을 유지한다는 것이 불가능에 가깝게 되어 이에 대한 대처 방안으로 Modernizr를 많이 사용하고 있습니다.




Modernizr Intro

모더나이저(Modernizr)는 작은 크기의 오픈소스 자바스크립트 라이브러리로서, 사용자가 현재 이용중인 웹 브라우저에서 HTML5와 CSS3의 명세에 정의된 기능 중 어떤 기능을 지원하는지를 알아볼 때 사용합니다. 

다시말해, 요소와 속성들에 대한 지원 여부를 점검하는 방식으로 기존의 방식(legacy)보다 더 정확한 분류가 가능합니다.


Modernizr 특징

  • 40개 이상의 신규 요소와 속성들을 테스트할 수 있으며, 웹문서에 Modernizr 스크립트를 포함하면 현재 브라우저가 CSS3(@font-face, border-radius, border-image, box-shadow, rgba()  등) 뿐만 아니라 HTML5의 기능(audio, video, localStorage, 새로 추가된 input 요소의 types과 attributes)에 대해서도 지원 여부를 점검,확인할 수 있습니다.
  • 모더나이저는 Modernizr 라는 자바스크립트 객체를 생성하여 boolean(true, false) 속성으로 지원여부를 판단합니다.
  • 모더나이저는 html 요소에 어떤 요소와 속성들이 지원되고 지원되지 않는지를 클래스 값을 이용해 나타내 줍니다.
  • 모더나이저에서 제공하는 스크립트 로더(script loader)를 사용하여 구형 브라우저에 대한 polyfill(대체방안)을 제공할 수 있습니다. 자바스크립트를 이용하여 지원 안되는 부분에 대한 기능을 추가할 지 아니면 단순히 웹페이지의 기능을 축소(우아한 기능 철학관점)할 지에 대한 결정도 할 수 있게 됩니다. 특히 구형 IE에서 지원하지 않는 HTML5의 header, nav, main, section, aside, footer를 지원하기 위해 html5Shiv를 추가할 수 있습니다.


Modernizr 2.7.0 에서는 html5 Shiv에 <main> 요소가 추가되었다.

Mdernizr

https://github.com/Modernizr/Modernizr


모더나이저는 점진적인 기능 개선 원칙(단계적 기능 향샹 철학)하에 개발되었기 때문에, 웹사이트에서 자바스크립트를 전혀 사용하지 않는 경우에서부터 기능개선을 위해서 단계별로 레이어를 추가할 수 있도록 지원합니다. 

모더나이저는 이러한 단계별 개발 방식을 권장하고 있습니다.




Browser Support(브라우저 지원 여부)

  • IE6+
  • Firefox 3.5+
  • Opera 9.6+
  • Safari 2+
  • Chrome
  • Mobile,  iOS's mobile Safari,  Android's Webkit browser,  Opera Mobile,  Firefox Mobile and whilst we're stiil doing more testing we believe we support Blackberry 6+.





Modernizr Usage(모더나이저 사용법)

모더나이저 홈페이지에 접속하면 Add your detects(Production 버전)와 Development build(개발용)버전을 다운로드할 수 있습니다.

  • Add your detects : 실제 서버스 단계에서 사용하는 것으로 사용자가 지원 여부를 확인하고자 하는 항목들만 선택할 수 있습니다.  사용자가 감지하려는 항목을 체크한 후 좌측 Options에서 minfiy가 체크(default)되어 있으면 우측의 build 버튼을 클릭하면 압축버전의 Custom Modernizr 를 다운로드 받을 수 있습니다. 
  • Development build : 개발 버전으로 모든 항목들이 체크된 파일을 다운로드 받을 수 있습니다.  주로 테스트 용도에서 많이 사용합니다.


감지하려는 항목을 클릭하면 해당 항목에 대한 설명, Polyfills, More Details 등이 제공됩니다.

예를 들어 Box Sizing을 감지하려고 할 때 이 항목을 클릭하면 Polyfills과 이에 대한 추가적인 내용을 살펴볼 수 있는 링크들이 나타납니다.


좌측 사이드바의 Options 항목 몇 가지만 알아보겠습니다.

html5shiv

IE6~9, 사파리4.x(아이폰3.x 포함), 파이어폭스 3.x 브라우저에서 HTML5의 기본 스타일을 적용할 수 있도록 해주고 특히 레거시 IE에서 HTML5의 section 요소들을 사용할 수 있게 해주는 도구입니다.


html5printshiv

프린트를 해야 할 필요가 있을 경우에 이 옵션을 선택해야 합니다.


Add CSS classes

기본으로 체크되어 있으며 html 요소에 클래스를 추가해서 지원하는 CSS3 속성과 기타 지원 기능들을 알수 있도록 해줍니다.



Modernizr 삽입

<head> 요소에 다운로드한 스크립트를 삽입합니다.

html
<head>
  <link rel="stylesheet" href="css/main.css" />
  <script src="js/lib/modernizr-custom.js"></script>
</head> 


성능적인 측면에서 스타일시트 다음에 위치시키는 것이 권장됩니다.

  • html5 Shiv는 <body> 요소 이전에 실행되어야 하기 때문입니다.
  • Modernizr를 이용해 CSS 클래스를 추가한다면 FOUC를 예방하기 위해 필요합니다.


FOUC는 외부의 CSS가 불러오기 전에 잠시 스타일이 적용되지 않은 웹 페이지가 나타나는 현상이다.

이 현상은 스타일이 적용되지 않은 웹 페이지가 스타일이 적용된 웹 페이지로 변화하는 것이다.  

브라우저가 웹 페이지에 스타일 정의를 부르고 적용할 때 보여지는 부분을 최대한 빨리 수정하지만, 이 변화는 짧지 않은 시간 동안 나타나므로 사용자는 페이지에 오류가 있다는 생각을 하게된다. 

FOUC는 CSS와 HTML의 버전 변화와는 관계가 없으며, 이것은 브라우저의 문제로 보인다.


만일 IE8 이하 버전을 지원하지 않기를 원하거나 FOUC를 개의치 않는다면 원하는 곳에 추가하여 사용해도 됩니다.



no-js 추가

<html> 요소에 class="no-js" 를 추가하도록 합니다.

html
<html class="no-js">


Modernizr가 실행되면서 사용자의 웹브라우저가 자바스크립트 사용이 가능한 환경이라면 no-js 부분은 js 로 변경되고 위에서 설명한 Modernizr build 에서 체크한 속성들을 감지하여 지원하지 않는 속성에 대해서는 해당 클래스명 앞에 no- 를 삽입하고 지원하는 속성은 no- 가 제거된 클래스명이 추가하게 됩니다.

아래의 그림처럼 클래스명이 추가된 것을 확인하실 수 있습니다.





Modernizr를 이용한 detection(감지)

모더나이저의 속성은 모두 소문자로 이루어져 있으며 기본적으로 아래와 같은 포맷을 사용합니다.

JavaScript
if(Modernizr.svg) {
  //svg supported
  console.log(Modernizr.svg); // true 출력
} else {
  //svg not supported
}


모더나이저에서 감지하는 항목 리스트를 몇 가지만 나열해 봅니다. 

그 외의 리스트는 Documentation 을 참고하세요.


 Detect 속성

문법(CSS class/JS property)

Canvas

Modernizr.canvas 

Canvas Text 

Modernizr.canvastest 

HTML5 Video 

Modernizr.video 

HTML5 Audio 

Modernizr.audio 

SVG 

Modernizr.svg 

Box Shadow 

Modernizr.boxshadow 

Box Sizing 

Modernizr.boxsizing 

CSS Calc 

Modernizr.csscalc 


JavaScript
if(!Modernizr.input.placeholder){
  document.write('<script src="polyfill.placeholder.js" type="text/javascript"></script>');
  $("input[placeholder]").placeholder();
}

위의 코드는 사용자의 브라우저가 input의 플레이스 홀더가 지원하지 않는다면 polyfill 스크립트를 로드하여 해당 js를 사용하겠다는 의미입니다.




Conditional JS with Modernizr.mq 

모더나이저 미디어쿼리를 이용한 img 요소 제어하기

모더나이저 객체에는 mq라는 미디어쿼리 프로퍼티가 있습니다.

이를 통해 RWD(반응형)에서 이미지의 사이즈를 제어할 수 있는 테그닉에 대해 알아보겠습니다.

물론 서로 다른 화면 크기에 대한 이미지 콘텐츠를 제어하는 방법 중에는 Reponse JS 와 같은 것을 이용해도 되지만 모든 사람들의 요구에 불필요할 수도 있습니다. 그리고 다른 테크닉으로는 window.matchMedia 도 있지만 아직 모든 브라우저/플랫폼에서 완벽하게 지원되지 않습니다.

위와 같은 이유로 이 테크닉을 이용하지 않는다면 모더나이저가 그 해결책이 될 수 있습니다.

다음의 소스는 img 요소에 data를 이용하여 두 벌의 이미지를 준비하도록 합니다.

HTML
<img class="img" src="http://placekitten.com/320/480" alt="" data-big="http://placekitten.com/1024/768" />

모바일 퍼스트 기준으로 작은 이미지는 기본으로 제공되는 기본 URL로 설정하고 큰 이미지는 데이터 속성에 설정되어 있습니다.

사용자는 그 화면 사이즈를 Modernizr.mq를 사용하여 모바일보다 큰 경우 데이터의 URL을 기본 URL로 아래와 같이 설정할 수 있습니다.

JavaScript
$(".img").each(function() {
  if (Modernizr.mq('only screen and (min-width: 1200px)')) {
    $(this).attr("src", $(this).attr("data-big"));
  }
});

지금 이 해결책은 RWD 사이트에 효과적으로 사용될 수 있는 방법 중의 하나가 될 것입니다.





Using Modernizr width CSS (html 요소의 class 활용과 대체방안)


CSS 속성명 - Modernizr JS 오브젝트 속성(CSS 클래스명)

  • @font-face - fontface
  • background-size - backgroundsize
  • border-image - borderimage
  • border-radius - borderradius
  • box-shadow - boxshadow
css
/* Simulated box shadow using borders: */
.demo {
  border-bottom: 1px solid #666;
  border-right: 1px solid #777;
}

.boxshadow div.demo {
   border: none;
   -webkit-box-shadow: #666 1px 1px 1px;
      -moz-box-shadow: #666 1px 1px 1px;
               box-shadow: #666 1px 1px 1px;
}


  • Flexible Box Model - flexbox
  • Multiple backgrounds - multiplebgs
  • opacity - opacity
  • rgba() - rgba
  • hsla() - hsla

대부분의 경우 rgba 와 hsla 클래스는 브라우저가 fallback을 기본적으로 제공합니다.

그렇기 때문에 .hsla, .rgba 클래스의 사용이 필요치 않을 수도 있습니다.

css
.my_container {  /* no .hsla use necessary! */
  background-color: #ccc; /* light grey fallback */
  background-color: hsla(0, 0%, 100%, .5); /* white with alpha */
}
  • text-shadow - textshadow

IE9 이하는 text-shadow를 지원하지 않습니다.

css
.glow { 
  /* ghosted letters */
  color: transparent;
  text-shadow: 0 0 10px black;
}
.no-textshadow .glow {
  color: black;
}


  • CSS Columns - csscolumns
  • Generated Cotent (:before/:after) - generatedcontent
  • CSS Animation - cssanimations

Android 2.1~3 은 동작하지만 오직 하나의 속성만을 애니메이션(animate a single property)할 수 있습니다.

Android 4+ 는 기대한대로 대부분의 속성 애니메이션 사용이 가능합니다.


  • CSS Gradients - cssgradients
  • CSS Reflections - cssreflections
  • CSS 2D Transforms - csstransforms
  • CSS 3D Transforms - csstransforms3d
  • CSS Transitions - csstransitions

좋은 사용 예는 애니메이션 엔진에 Modernizr를 구축하고 브라우저가 CSS transition 를 가지고 있다면 Native CSS transition을 사용하는 것이고, 브라우저가 CSS transition의 사용이 불가능하다면 애니메이션을 자바스크립트로 구현하는 것입니다.




Modernizr 사용 예제

원문 출처 : Taking Advantage of HTML5 and CSS3 with Modernizr


모더나이저 홈페이지에서 최신 버전을 다운로드 한후 <head> 섹션에 아래와 같이 삽입합니다.

<html> 요소에 no-js 클래스를 추가하는 것도 잊지 않도록 합니다.

html
<!DOCTYPE html> 
<html class="no-js"> 
  <head> 
    <meta charset="utf-8"> 
    <title>My Sample Page</title> 
    <script src="modernizr.js"></script>
  </head> 
…

모더나이저가 실행되면 사용자의 웹브라우저에서 자바스크립트 사용가능 여부를 알 수 있도록 no-js 클래스를  js 로 변경되어 표시해 줍니다.

또한, 브라우저에서 감지되는 모든 속성에 대한 해당 클래스명을 추가해 주는데 브라우저가 지원하지 않는 속성에 대해서는 해당 클래스명 앞에 no- 를 삽입해 주게 됩니다. 

따라서 <html> 요소는 페이지 로드시에 자바스크립트 사용이 가능한 환경에서 아래와 같이 랜더링하게 됩니다.

html
<html class="js canvas canvastext no-geolocation rgba hsla multiplebgs borderimage borderradius boxshadow opacity cssanimations csscolumns cssgradients cssreflections csstransforms csstransforms3d csstransitions video audio localstorage sessionstorage webworkers applicationcache fontface">


모더나이저는 Modernizr라는 자바스크립트 오브젝트를 생성하여 각 속성에 대한 boolean값을 가지는 속성 목록 정보를 제공해 주고 있습니다.

따라서, Modernizr.svg 값은 사용자 브라우저가 svg 요소를 지원하는 경우 true 값을 반환하고 그렇지 않은 경우에는 false 값을 반환하게 됩니다.


이 Modernizr 객체는 특성 속성에 대한 상세정보까지도 제공해 주는데, 예를 들어 Modernizr.video.h264 는 브라우저의 특정 코덱에 대한 지원 여부를 알려줍니다.

또한 Modernizr.inputtypes.search 는 search input 요소의 type에 대한 지원여부에 대해서 알려주게 됩니다.



이제부터 Modernizr를 적용하는 방법에 대해 단계별로 알아보겠습니다. (원문 출처 참고)


우선 기본 마크업을 구성한 샘플 페이지(#1버전)를 하나 만듭니다. 그리고 여기에 보기 좋게 하기 위해 전체적인 포맷이나 색상 그리고 레이아웃을 잡기 위해 약간의 스타일을 추가해 주도록 합니다.

결과적으로 변경된 웹페이지는 이와 같이(#2버전) 보일 것입니다.


#2 페이지는 <h1> 요소에 사용자 임의의 폰트를 사용하고, Modernizr에서 이용 가능한 속성들의 목록을 두개의 컬럼으로 정렬하고 이미지가 포함된 Modernizr 관련 내용을 오른쪽으로 정렬합니다. 그리고 웹페이지의 외곽선을 변경해서 좀 더 멋지게 보이도록 합니다.

이와 같이 CSS를 이용해서 새로운 속성(추가된 스타일)을 추가하게 되면 웹페이지는 더 완성도 있게 보일 것입니다. 하지만 만약 특정 브라우저가 이러한 속성들을 인식하지 못할 경우에는 해당 스타일을 무시한 채로 랜더링되게 될것입니다.


물론 CSS의 캐스케이딩 테그닉을 이용하면 Modernizr를 사용하지 않은 상태에서도 border-radius와 같은 속성을 사용할 수 있습니다.

그러나 Modernizr를 사용할 경우에는 좀 더 추가적인 기능을 이용할 수 있게 됩니다.

즉, 특정 브라우저가 이와 다른 속성들을 지원하는 경우에 해당 속성을 원하는 대로 변경할 수 있게 된다는 것입니다.


위의 내용을 CSS를 작성하여 예를 들어보겠습니다.

css
.borderradius #content {
  border: 1px solid #141414;
  -webkit-border-radius: 12px;
  -moz-border-radius: 12px;
  border-radius: 12px;
}

.boxshadow #content {
  border: none;
  -webkit-box-shadow: rgba(0,0,0, .5) 3px 3px 6px;
  -moz-box-shadow: rgba(0,0,0, .5) 3px 3px 6px;
  box-shadow: rgba(0,0,0, .5) 3px 3px 6px;
}


첫번째 CSS는 #content 요소의 둥근 모서리의 크기를 12px로 추가하도록 합니다. 그러나 이미 #content에 대해 2px  outset  #666 으로 외곽선을 지정해 놓았습니다. 

이 스타일(outset)은 외곽선의 모서리가 각이 져 있을 경우에는 어울려 보이지만 만약 둥근 모서리로 변경하게 되면 좀 어색해 보일 수 있습니다. 

그러나 Modernizr를 통해 특정 브라우저가 border-radius를 지원할 경우에만 외곽선을 1px  solid 로 렌더링하도록 할 수 있습니다.


두번째 CSS는 #content 요소에 drop shadow를 추가해 주고 특정 브라우저가 box-shadow 속성을 지원할 경우에는 외곽선을 제거해 주도록 합니다.

왜 이렇게 해 주어야 하는 걸까?


대부분의 브라우저는 border with border-radius 조합을 렌더링하지 못하지만 box-shadow는 멋지게 렌더링해 주기 때문입니다.

여기서는 외곽선만 사용하는 것보다는 drop shadow를 사용하여 모든 CSS를 최상의 상태로 보일 수 있도록 할 수 있게 됩니다.

즉, box-shadow를 지원하는 브라우저는 drop shadow를 제대로 렌더링할 것이고, border-radius를 지원하는 브라우저는 얇은 외곽선과 함께 둥근 모서리를 보여주게 되며, 둘다 지원하지 않는 경우에는 본래의 2px outset 인 외곽선을 보여 주게 되는 것입니다.



다음에는 헤딩 태그에 사용자 특정 폰트를 아래와 같이 정의(#2 페이지)되어 있습니다.

css
h1 {
  color: #e33a89;
  font: 27px/27px Baskerville, Palatino, "Palatino Linotype", "Book Antiqua", Georgia, serif;
  margin: 0;
  text-shadow: #aaa 5px 5px 5px;
}

위의 CSS는 제대로 동작하여 27px 크기의 폰트가 모든 글자에 대해서 어울려 보일 것입니다.

하지만 Beautiful 이라는 폰트를 사용할 경우에는 상대적으로 작게 보이게 될 것입니다. 

이 Beautiful 폰트를 사용하기 위해 아래와 같이 CSS를 추가하도록 합니다.

css
@font-face {
  src: url(Beautiful-ES.ttf);
  font-family: "Beautiful";
}

.fontface h1 {
  font: 42px/50px Beautiful;
  text-shadow: none;
}

우선 @font-face 선언을 통해 추가한 폰트를 위해 path, filename, font-family 속성을 지정해 주도록 하고 h1 요소에 좀 더 큰 폰트 크기로 할당하도록 합니다.

이렇게 한 이유는 추가하게 되는 Beautiful 폰트가 h1 요소에 지정한 다른 폰트에 비해 훨씬 작게 렌더링됙 때문이며 따라서 이 폰트를 렌더링할 때만 브라우저가 헤딩 태그를 훨씬 크게 렌더링하도록 해 주어야 하게 때문입니다.

그리고 Beautiful 폰트는 text-shadow를 렌더링하는데 약간의 문제를 가지고 있어서 브라우저가 이 폰트를 렌더링할 경우에는 shadow를 제거하도록 합니다.


다음으로 CSS columns 속성을 사용하려고 합니다.

물론, 모든 브라우저가 아직 CSS columns 속성을 지원하지 않기 때문에 미지원의 경우에는 float 속성을 이용해야 합니다.

css
.csscolumns ol.features {
  -moz-column-count: 2;
  -webkit-columns: 2;
  -o-columns: 2;
  columns: 2;
}

.no-csscolumns ol.features {
  float: left;
  margin: 0 0 20px;
}

.no-csscolumns ol.features li {
  float: left;
  width: 180px;
}

브라우저가 CSS columns 속성을 지원하는 경우에는 문제없이 원하는 결과를 얻을 수 있지만 그렇지 못한 경우(미지원 여부는 <html> 요소에 "no-csscolumns" CSS 클래스가 추가되어 있는 것을 통해 알 수 있다)에는 columns와 비슷한 결과를 얻기 위해 float 레이아웃방식으로 변경하여 다른 스타일링을 해주도록 할 수 있습니다.

그리고 columns는 오페라(Opera) 브라우저에서 verdor prefix를 사용해야하고 모질라(Mozilla)의 경우는 아직까지 "columns"라는 단축형의 속성을 인식하지 못하여 -moz-column-count 속성을 사용해야 합니다.


지금까지 예제를 통해 구현한 페이지(#3버전)를 확인해보세요.


마지막으로 좀 더 세련된 기능을 추가해 보도록 합니다.

Webkit 기반의 브라우저들은 CSS transitions, animations, 3D transforms와 같은 멋진 기능들을 지원해주고 있는데 여기서 몇 가지를 적용해 보도록 합니다.

이 속성들 중에 몇 가지 속성은 간단하게 추가할 수 있으며 미지원 브라우저에서는 별 문제없이 무시되는데 어떤 속성은 이와 같이 추가하게 되면 모든 브라우저의 레이아웃이 깨져버리는 사태가 발생할 수 있습니다.

이러한 경우를 대비해 Modernizr를 사용하면 효과적으로 제어할 수 있게 됩니다.


먼저 아래와 같이 설정을 합니다.

css
@-webkit-keyframes spin {
   0% { -webkit-transform: rotateY(0); }
 100% { -webkit-transform: rotateY(360deg); }
}
.csstransforms3d.cssanimations section {
 -webkit-perspective: 1000;
}

@keyframes는 새롭게 추가된 CSS Animations 스펙 중의 하나인데, 전에는 Webkit 엔진 브라우저에서만 지원했지만 현재는 모던 브라우저에서 모두 지원하고 있습니다.

이 속성만으로 전체 애니메이션을 선언(함수와 유사)할 수 있으며 원하는 단계에서 변경 작업도 수행할 수 있습니다.


CSS Animation을 적용하고자 할 때 duration, loop count, easing curves들을 지정해 줄 수 있지만 여기 @keyframes에는  duration은 지정하지 않았다는 것에 주목해야 합니다. 이렇게 함으로써 다른 엘리먼트에 대해서는 다른 속도를 지정하여 특정 animation을 재사용할 수 있게 되어 유연성을 극대화할 수 있습니다.

animations에 대한 자세한 정보는 W3C Working Draft Specification을 참고하세요.


다음은 <h2> 요소를 3차원 공간에서 엘리먼트를 회전할 수 있도록 animation을 적용하도록 합니다.

css
.csstransforms3d.cssanimations section h2 {
  background-image: url(modernizr-logo.png);
  overflow: hidden;
  -webkit-animation: spin 2s linear infinite;
}

위의 CSS는 3차원 공간에서 이미지를 회전시킬 것이기 때문에 배경이미지로 안티앨리어싱 처리된 모더나이저 로고를 사용하기위해 PNG버전으로 교체할 것입니다.

또한 헤딩 요소내의 텍스트를 감추기 위해 text-indent 오프셋을 -9999px로 처리(#3버전)되어 있습니다.

마지막으로 animation을 적용해서 2초로 설정하고 선형 패턴(linear)으로 무한반복(infinite) 회전하도록 합니다.


최종 페이지는 이처럼(#4버전) 보이게 될 것입니다.

이렇듯 Webkit 엔진 브라우저에서는 애니메이션 테크닉을 사용할 수 있습니다.




마치며

모더나이저는 웹 브라우저를 좀 더 잘 제어할 수 있으며 점진적(단계적)인 기능향상을 이루는데 기여합니다.

여기서 설명한 것이 모더나이저의 모든 것은 아니지만 앞으로 HTML5, CSS3의 새롭게 멋진 속성들을 사용하는데 매우 중요한 가이드가 될 것입니다.


다음 포스팅에서는 디바이스를 탐지하는 Detectizr에 대해 다뤄보겠습니다.

디텍타이저는 모더나이저의 확장형 라이브러리로서 현존하는 모든 디바이스를 탐지하여 사용자에게 그 정보를 제공해 주고 있습니다.



Jaehee's WebClub


[참고 자료] WEBDIR - 흉내쟁이님