- Modernizr and HTML5/CSS3 -
지금까지는 웹브라우저의 호환성을 유지하기 위해 browser sniffing 기법(자바스크립트의 navigator.userAgent 프로퍼티를 이용하는 방식)을 사용해 왔다. 그러나 스마트 디바이스가 대세로 떠오르는 요즘에는 HTML5와 CSS3가 거의 웹표준으로 자리매김을 하고 있다. 그러나 브라우저마다 HTML5와 CSS3의 구현정도가 달라 기존의 browser sniffing 방식으로는 이러한 브라우저간의 호환성을 유지한다는 것은 바보 같은 일이 아닐 수 없다.
바로 여기서 `Modernizr` 의 필요성이 강조되는 것이다. `Modernnizr`는 브라우저의 종류를 점검하는 것이 아니라 특정 엘리먼트에 대한 지원여부를 점검(feature-detection)하는 것이다.
`Modernizr`는 오픈소스 자바스크립트 라이브러리로, 웹디자이너가 클라이어트 브라우저의 지원정도에 따른 차이를 없애고 결과적으로 모든 브라우저에서 같은 기능을 수행할 수 있게 해준다. 결국 특정 브라우저에서 구현하는 HTML5와 CSS3의 모든 기능을 다른 브라우저에서도 사용자 경험을 할 수 있도록 해 주는 장점을 가지게 되는 것이다.
웹페이지에 `Modernizr` 스크립트를 인클루드하면, 현재 브라우저가 CSS3(@font-face, border-radius, border-image, box-shadow, rgba() 등) 뿐만 아니라 HTML5의 기능(audio, video, localStorage, 새로 추가된 input 엘리먼트의 types과 attributes)에 대해서도 지원하는 정도를 점검할 수 있고 자바스크립트를 이용하여 지원 안되는 부분에 대한 기능을 추가할지 아니면 단순히 웹페이지의 기능을 축소할지에 대한 결정도 할 수 있게 된다. 게다가 `Modernizr`는 IE에서의 스타일 작업시 HTML5 엘리먼트를 사용할 수 있게도 해 준다.
이러한 `Modernizr`는 점진적인 기능개선 원칙하에 개발되었기 때문에, 웹사이트를 자바스크립트를 전혀 사용하지 않는 경우에서부터 기능개선을 위해서 단계별로 레이어를 추가할 수 있도록 지원한다. 오히려 이러한 단계별 개발방식을 권장하고 있다.
`Modernizr`로 시작하기
홈페이지로부터 최신 버전을 다운로드한 후 웹페이지의 <head> 섹션에 아래와 같이 인클루드한다.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My Beautiful Sample Page</title>
<script src="modernizr-1.5.min.js"></script>
</head>
…
다음에 <html> 태그 엘리먼트에 `no-js` 클래스를 추가해 준다.
`Modernizr`가 실행되면 이 클래스가 `js` 로 변경되어 웹브라우저에서 자바스크립트가 사용가능한 지 여부를 CSS로 알수 있도록 해준다. 또한 브라우저에서 감지되는 모든 feature 에 대한 해당 클래스명을 추가해 주게 되는데, 브라우저가 지원하지 않는 feature 에 대해서는 해당 클래스명 앞에 `no-`를 삽입해 주게 된다. 따라서 <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`는 또한 `Modernizr`라는 자바스크립트 객체를 만들어, 각 feature에 대한 불린값을 가지는 프로퍼티 리스트 정보를 제공해 준다. 따라서 Modernizr.canvas 값은 브라우저가 canvas 엘리먼트를 지원하는 경우 true 값을 반환하고 그렇지 않은 경우에는 false 값을 반환하게 된다. 이 자바스크립트 객체는 특정 feature에 대한 상세정보까지도 제공해 주는데, 예를 들어, Modernizr.video.h264는 브라우저의 특정 코덱에 대한 지원여부를 알려준다. 또한 Modernizr.inputtypes.search는 `search` input 엘리먼트의 type에 대한 지원여부에 대해서 알려주게 된다.
이제 `Modernizr`를 적용하는 방법을 단계별로 알아 본다.
그리고 여기에 약간의 스타일을 추가해 준다. 예를 들면, 보기 좋게하기 위해 전체적인 포맷이나 색상 그리고 레이아웃을 잡아 준다. 결과적으로 변경된 웹페이지는
이렇게 보일 것이다.
이제부터는 웹페이지의 기능을 추가해서 좀 더 흥미롭게 해 보자. <h1> 태그에 임의의 폰트를 사용하고, Modernizr에서 이용가능한 feature들의 리스트를 두개의 컬럼으로 배열하고, 이미지가 포함된 Modernizr관련 내용을 오른쪽으로 이동한다. 그리고 웹페이지의 외곽선을 변경해서 더 멋지게 보이도록 한다. 이와 같이 CSS를 이용해서 새로운 프로퍼티(추가된 스타일)를 추가하게 되면 웹페이지는 더 완성도 있게 보이겠지만 만약 특정 브라우저가 이러한 프로퍼티를 인식하지 못할 경우에는 해당 스타일을 무시한 채로 보이게 될 것이다. CSS의 캐스케이딩 기술을 이용하면 Modernizr를 사용하지 않은 상태에서도 border-radius와 같은 것을 사용할 수 있다. 그러나, Modernizr를 사용할 경우에는 뭔가 추가적인 기능을 이용할 수 있게 된다. 즉, 특정 브라우저가 이와 다른 프로퍼티를 지원하는 경우, 해당 프로퍼티를 원하는 데로 변경할 수 있게 된다는 것이다.
아래 두개의 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"로 외곽선을 지정한 바 있다. 이것은 외곽선의 모서리가 각이 저 있을 때에 어울려 보이지만 만약 둥근 모서리로 변경하게 되면 좀 어색하게 보이게 된다. 그러나 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 외곽선을 보여 주게 되는 것이다.
다음에는 헤더 태크에 특정 폰트를 추가한다. 아래에 <h1> 태그에 대해 이미 선언해 놓은 내용을 보여 준다.
h1 {
color: #e33a89;
font: 27px/27px Baskerville, Palatino, "Palatino Linotype", "Book Antiqua", Georgia, serif;
margin: 0;
text-shadow: #aaa 5px 5px 5px;
}
이것은 제대로 동작하여 27px 크기의 폰트가 모든 폰트에 대해서 어울려 보이지만, Beautiful 이라는 폰트에 대해서는 상대적으로 작게 보이게 된다. 이 폰트를 사용하기 위해 아래와 같이 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를 제거했다. Modernizr의 feature들에 대한 목록을 두 컬럼으로 분리할 필요가 있다. 이를 위해서, CSS columns를 사용할 것인데 브라우저는 해당 목록의 순서를 유지한 채 두 컬럼으로 재배열하게 된다. 숫자로 순서를 표시하지는 않았지만 이 목록은 알파벳순으로 배열된다. 물론, 모든 브라우저가 아직 CSS columns를 지원하지 않아서 이 경우에는 float 속성을 이용하게 되는 이 때는 더 이상 알파벳순으로 소팅되지 않지만 하나의 컬럼으로 보이는 것보다는 더 낫게 보이게 된다.
.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;
}
다시 Modernizr를 이용한다. 이때는 프로퍼티 변경이나 캐스케이딩을 이용하여 해결할 수 없는 경우에만 자주 사용하는 프로퍼티를 적용하기로 한다. 브라우저가 CSS columns를 지원할 경우에는 문제없이 원하는 결과를 얻을 수 있지만, 그렇지 못할 경우에는(<html> 태그에 "no-csscolumns" CSS 클래스가 추가되어 알 수 있다), 이 목록 항목들을 float 해서 비슷하게 보이도록 margin과 width를 변경해 준다. 이것은 좋은 방법은 아니지만 길다란 목록을 보는 것보다는 낫다는 것이다.
이미 눈치챗을 수도 있지만, 이전 예제에서 사용했던 border-radius와 box-shadow 프로퍼티와는 다르게 columns를 지정하게 되는데, 오페라(Opera) 브라우저만이 현재 vendor 명을 앞에 붙인 상태로 CSS columns를 지원하고, 모질라(Mozilla)의 경우는 아직까지 "columns"라는 단축형의 프로퍼티를 인식하지 못해서 -moz-column-count 속성을 사용해야 하기 때문이다.
지금까지 작업한 변경내용을
이와 같이 볼 수 있다.
마직막으로 훨씬 더 세련된 기능을 추가해 보도록 한다. WebKit 기반의 브라우저들은 CSS transitions, animations, 3D transforms 같은 멋진기능들을 지원하는데 여기서 몇가지를 적용해 보도록 한다. 이것들 중에 몇가지 프로퍼티는 간단하게 추가할 수 있고 이를 지원하지 않는 브라우저에서는 별문제없이 무시되는데, 그러나 어떤 프로퍼티는 이와 같이 추가하게 되면 모든 브라우저의 레이아웃이 깨져 버리는 사태가 발생할 수 있는데 Modernizr를 사용하면 이런 경우를 효과적으로 조절할 수 있게 된다.
먼저 아래와 같이 설정을 한다.
@-webkit-keyframes spin {
0% { -webkit-transform: rotateY(0); }
100% { -webkit-transform: rotateY(360deg); }
}
.csstransforms3d.cssanimations section {
-webkit-perspective: 1000;
}
@keyframes는 새롭게 추가된 CSS animations 스펙 중에 하나인데, 현재는 WebKit 류의 브라우저에서만 지원한다. 이것은 원하는 프로퍼티만으로도 전체 animation을 선언할 수 있는데 원하는 스텝에서 변경작업도 수행할 수 있다. CSS로 animation을 적용하고자 할 때 duration, loop count, easing curves들을 지정해 줄 수 있지만, 여기서는 duration은 지정하지 않고 key frames 만 지정했다는 것에 주목해야 한다. 이렇게 하므로써 다른 엘리먼트에 대해서는 다른 속도를 지정하여 특정 animation을 재사용할 수 있어 유연성을 극대화 할 수 있다. animations에 대한 더 자세한 정보는
W3C Working Draft specification을 참고하면 된다.
다음은, 3차원 공간에서 엘리먼트를 회전할 수 있도록 <h2> 태그에 animation을 적용한다.
.csstransforms3d.cssanimations section h2 {
background-image: url(modernizr-logo.png);
overflow: hidden;
-webkit-animation: spin 2s linear infinite;
}
여기서는 3차원 공간에서 이미지를 회전시킬 것이기 때문에, 배경이미지로 앤티앨리어스 처리된 멋진 Modernizr 로고를 사용하기 위해 PNG 버전으로 교체할 것이다. 또한 헤더내의 텍스트를 감추기 위해 overflow:hidden 프로퍼티를 추가하고 오프셋을 -9999px 설정해서 보이지 않게 해 준다. 3차원 공간에서 엘리먼트를 회원시키면 회전하는 동안 보이게 되는데 놀랍지만 그렇게 멋지게 보이지 않았다. 마지막으로, animation을 적용해서 2초로 세팅하고 선형 패션으로 무한루프로 회원하게 한다.
최종 웹페이지는
이와 같이 보이게 된다. WebKit 류 브라우저에서는 재밌는 animation이 보이게 된다. 바란건대 Modernizr를 이용하므로써 웹사이트 훨신 잘 제어할 수 있고 점직적인 기능향상을 잘 구현할 수 있기를 바란다. 여기서 설명한 것이 Modernizr의 모든 것이 아니지만 자바스크립트로 구동된 fallback을 생성하고 HTML5의 새롭고 멋진 feature들을 사용하는데 매우 중요한 내용이 될 것이다.