CSS 제대로 쓰기

(주)시도우 eBI 팀 신현석

2005. 01

개요

W3C.ORG 홈페이지 여러가지 웹 표준 스펙을 만들고 있는 월드 와이드 웹 컨소시움(World Wide Web Consortium; W3C) 홈페이지

CSS는 현재 대부분의 사이트에서 폰트나 링크 스타일에 대한 정의 정도로만 사용되고 있습니다. 이러한 사용도 서체나 링크의 디자인을 효과적으로 관리하는데 도움이 되겠지만 CSS의 가장 큰 장점인 문서의 구조와 디자인의 분리를 활용하지 못하고 있는 경우입니다. CSS를 서체 정도에만 사용하게 되면 HTML에 레이아웃이라든가 배경이미지 같은 디자인 적인 요소가 들어갈 수 밖에 없습니다. 여기서는 이러한 디자인 적인 요소를 HTML에서 분리해 냄으로서 얻어질 수 있는 여러가지 장점에 대해서 알아보도록 하겠습니다.

CSS

CSS 일반

Cascading Style Sheet

CSS는 구조적으로 짜여진 문서(HTML, XML)에 스타일(글자, 여백, 레이아웃 등)을 적용하기 위해서 사용하는 기술입니다. CSS는 문서의 구조와 디자인을 분리할 수 있게 해 줌으로써 웹 제작이나 유지관리를 효과적으로 할 수 있게 해 줍니다. 또한 스타일을 미디어(화면, 프린트, 보이스머신 등) 별로 적용 할 수 있게 하기 때문에 다양한 기기별로 서로 다른 스타일을 적용할 수 있습니다(CSS2 표준에서 발췌).

CSS 2.1 Specification W3C의 CSS2.1 스펙

이것을 잘 보여주는 사이트로 CSS 젠 가든(css zen garden) 사이트가 있습니다.

스타일을 변경한 여러 CSS 젠 가든 사이트 들 CSS 젠 가든

위의 사이트들은 다 전혀 다른 사이트 같지만 실제적으로는 동일한 사이트 입니다. HTML은 동일하고 CSS 만 바꿔서 사이트의 디자인을 다르게 표현한 것입니다. 내용의 구조와 디자인이 완벽하게 분리되어 있기 때문에 디자인 요소만 바꾸어도 이렇게 다른 사이트 처럼 보이게 되는 것입니다.

CSS 선택자(Selector)

CSS를 정확히 이해하고 사용하기 위해서는 CSS 선택자에 대해서 알아야 합니다. CSS를 사용하시면서 "내가 만든 CSS class 가 다른 사람의 것과 겹치면 어떻게 하지?", 또는 "CSS class가 너무 많아서 복잡하고 이름 정하기가 힘들다." 라는 생각을 하신 적이 있으실 것입니다. CSS 선택자를 잘 알게 되면 이러한 고민은 더 이상 하실 필요가 없습니다. 일반적으로 사용되고 있는 CSS 선언을 보면 다음과 같은 경우가 많습니다.

body {
	margin: 0;
}
.text {
	font-weight: bold;
}

여기서 'body', '.text' 같은 것이 선택자입니다. 'body' 선택자는 요소 이름(element name)이 body인 요소를 선택(select)하라는 선택자입니다. '.text'는 '*.text'의 생략형입니다. 일반적으로 .className과 같은 표현은 앞에 모든 요소를 지칭하는 '*'이 생략된 것입니다. '.text'는 className이 text인 모든(*) 요소를 선택하는 선택자입니다.

인터넷 익스플로러6에서 사용할 수 있는 선택자는 다음과 같습니다.

* (Universal selector)
모든 요소 선택
E (Type selectors)
요소 이름이 E 인 것들을 선택
E F (Descendant selectors)
E 요소의 하위에 있는 F 요소들을 선택
E:link, E:visited (The link pseudo-classes)
아직 방문하지 않았거나(link) 방문한(visited) 하이퍼링크들을 선택
E:active, E:hover
사용자 액션이 active이거나 hover인 E 요소들을 선택
E.foo
className이 foo인 E 요소들을 선택
E#elId
요소 아이디가 elId인 E 요소를 선택
<ul id="list">
	<li><a href="list.html?id=34&amp;type=blah">34번글</a></li>
	<li><a href="list.html?id=35&amp;type=blah">35번글</a></li>
	<li><a href="list.html?id=36&amp;type=blah">36번글</a></li>
	...
	...
	<li><a href="list.html?id=37&amp;type=blah">37번글</a></li>
	<li><a href="list.html?id=38&amp;type=blah">38번글</a></li>
</ul>

일반적으로 다음과 같은 선택자를 생각해 볼 수 있습니다.

a.list {
	color: #999;
}

이 경우 모든 a 요소에 class="list"와 같이 지정을 해주어야 합니다. 하지만 descendant 선택자를 사용하게 되면 HTML에서 class를 지정할 필요 없이 상위 요소에 id 만 부여함으로써 간단하게 선택할 수 있게 됩니다.

ul#list a {
	color: #999;
}

선택자는 스타일을 적용할 요소를 선택해 오는 목적으로 사용을 할 수 있고 우리 모두들 이미 이 선택자를 사용하고 있습니다. 단지 아직까지는 그 사용이 일부 선택자에 제한적일 뿐입니다. 풍부한 선택자를 익히고 이를 이용해서 구조적으로 잘 짜여진 문서에 스타일을 적용할 수 있다면 작성해야 하는 소스코드의 길이 자체도 훨씬 줄어들게 되고 사이트 구축 작업도 한결 손쉽게 할 수 있습니다.

CSS 선언 방법

CSS는 3가지 방법으로 선언하여 사용할 수 있습니다.

외부 CSS(external css)
<link rel="stylesheet" type="text/css" href="mystyle.css" />

위와 같이 사용 하면 외부에 별도의 파일로 되어 있는 CSS 정의를 불러올 수 있습니다. 여러파일이 하나의 CSS 파일을 공유할 수 있어서 표현에 일관성을 갖게 됩니다.

문서안에 포함된 CSS(embeded css)
<head>
<style type="text/css">
body {
	margin: 0;
	padding: 0;
}
</style>
</head>

위와 같이 head 요소 안에서 style 요소를 사용하여 문서 안에서 CSS를 정의 할 수 있습니다.

요소에 직접 선언(inline css)
<div style="padding: 10px; border: 1px solid #eee;">
	<p>내용</p>
</div>

위와 같이 사용하면 별도의 class를 선언할 필요 없이 HTML 요소에 직접 선언이 가능 합니다.

이러한 CSS의 선언방법들을 우선 순위에 따라서 각 요소에 스타일을 적용할 수 있게 해 줍니다. 우선순위 별로 나열해 보면, 가장 우선 순위가 낮은 것은 외부 CSS와 포함된 CSS이고 그 다음이 인라인 CSS 순 입니다. 가장 우선 순위가 높은 것은 여기서 소개는 하지 않은 사용자 정의 CSS(user defined CSS)라는 것입니다. 사용자가 자신만의 CSS를 정의 하여 현재 보고 있는 문서의 표현을 자신에 맞게 커스터마이징 하는 것입니다. 이것이 우선 순위가 가장 높습니다. 아직 인터넷 익스플로러에서는 지원이 되지 않는 기능이기 때문에 별도로 소개는 하지 않겠습니다.인터넷 익스플로러는 서체에 대한 정의만 할 수 있기 때문에 여기서 다루지는 않겠습니다.

CSS와 HTML

HTML

HTML은 HyperText Markup Language의 약자 입니다.

하이퍼 텍스트(HyperText)는 일반적으로 많이 알고 계실 것입니다. 쉽게 이해 하지면 링크로 연결되는 문서를 의미 합니다. 보통의 인쇄되어 있는 책들과 비교해 볼 때 하이퍼 텍스트는 엄청난 장점을 가지고 있습니다. 하이퍼 텍스트의 장점을 잘 살려서 웹 사이트라고 하는 정보를 전달 할 수 있는 구조적인 문서를 만들어 낼 수 있는 것입니다. HTML에서 우리들이 쉽게 생각하지 못하는 것이 HTML은 마크업 언어(markup language)라는 것입니다.

출판이 전산화 되기 전에는 글을 쓰는 사람이 자신의 원고에 내용의 표현과 의미에 대해서 표기를 하였습니다. 그리고 이것을 바탕으로 활자를 짰습니다. 여기서 저자가 내용에 표기하는 작업을 "마크업한다(mark it up)."라고 했습니다. 즉 마크업이라는 것은 원고에 대한 무엇인가를 설명하고 그것을 표기하는 것입니다. 이 '무엇인가'라는 것은 문서의 표현 형식일 수도 있고, 문서 내용이 제목이나 문단과 같이 문서내에서 뜻하는 것이 어떠한 것이라는 것의 설명일 수도 있습니다.

그러나 대부분의 HTML 작업자들은 HTML을 마크업에 사용하기 보다는 '표현 형식에 대한 기술'로만 사용하고 있습니다. 사실 더 정확히 말하면 대부분의 작업자 들은 HTML이 마크업이라는 것을 간과하고 무의식 중에 "<table"부터 적기 시작합니다. 예를 들어서 HTML 작업자에게 "h1 태그가 무엇인가요?"라고 물어보면 "매우 크고 두꺼운 폰트"라고 답변을 할 것입니다. "h2 태그가 무엇인가요?" 라고 질문을 하게 되면 "두번째로 크고 두꺼운 폰트"라는 답변을 얻을 수 있을 것입니다. 틀린 말은 아니지만 이러한 답변은 HTML이 문서의 구조를 나타낸 다는 것을 생각지 못한 답변입니다. h1이나 h2는 크고 두꺼운 폰트를 나타내는 것이 아니라 해당 섹션에서 가장 중요한 제목을 나타내는 것 입니다.

어느순간부터 우리들은 HTML 태그들이 구조적인 의미를 갖는 다는 것은 잊어 버린채 단순히 화면상에서 어떻게 보이는 가를 기준으로 이들을 사용하고 있습니다. 결국 많은 구조를 나타내는 태그들은 사용이 안되고 오직 table, img, form 태그 정도만 이용을 하고 있습니다.

CSS와 HTML과의 관계

야후!(yahoo.com)의 초기 페이지의 HTML 소스(2005년 1월 현재)를 보면 table 요소는 하나도 없습니다. 야후!의 초기페이지에는 표형식의 데이터는 없고 서비스되고 있는 항목들의 목록이 주이기 때문에 테이블이 사용되지 않은 것입니다. 대신 각 섹션을 나누어주는 div 요소와 목록를 의미하는 ul, li 요소가 주를 이루고 있습니다. 페이지 내에서 컨텐츠의 의미를 바탕으로 마크업이 되어 있고, 이를 어떻게 사용자에게 보여주는가 하는 것은 CSS로 정의가 되어 있는 것입니다.

YAHOO.COM 홈페이지 HTML 테이블 요소는 없고 구조를 나타내는 HTML 요소들로만 마크업이 이루어져 있다.

다시 말해서 HTML은 페이지의 내용과 각 내용들이 어떠한 의미만 갖는가를 나타내게 됩니다. HTML에는 "메뉴가 어디서부터 어디까지이고 목록 형태로 나타나고 항목의 내용은 1, 2, 3이다."라는 것만 나타냅니다. 좌측 메뉴가 페이지내에서 왼쪽에 위치하고 각 메뉴 항목은 삼각형모양의 불렛이 좌측에 있고 메뉴 아래에는 점선이있고 폰트크기는 어떻고 색은 어떻다라는 것은 CSS에서 정의하는 것입니다.

구조와 표현의 분리가 가장 중요한 CSS의 특징입니다.

CSS layout

가장 간단한 상단, 서브 메뉴, 컨텐츠, 하단으로 구성된 화면 입니다.

Layout 캡춰 기본 layout

markup

레이아웃을 구성하기 위해서 우선 마크업을 작성 합니다.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
<title>간단한 CSS Layout</title>
<link rel="stylesheet" type="text/css" href="layout.css">
</head>
<body>
<div id="head">
	<div id="logo">로고</div>
	<ul>
		<li>대메뉴1</li>
		<li>대메뉴2</li>
		<li>대메뉴3</li>
	</ul>
</div>
<hr>
<div id="submenu">
	<ul>
		<li>서브메뉴1</li>
		<li>서브메뉴2</li>
		<li>서브메뉴3</li>
	</ul>
</div>
<hr>
<div id="content">
	<h1>문서제목</h1>
	<p>내용</p>
</div>
<hr>
<div id="foot">
	<div id="copyright">카피라이트</div>
</div>
</body>
</html>

마크업은 아주 간단합니다. 상단, 서브 메뉴, 내용, 하단에 해당하는 div 요소를 만들어 주고 각각에 id를 부여 하였습니다. 각 div 안에는 사이트 구성 요소에 따른 적절한 요소를 넣어주면 됩니다. 여기서는 상단 부분에 대메뉴와, 서브메뉴 부분에 메뉴를 넣었습니다. 그리고 내용 부분에서는 페이지의 타이틀인 h1 요소를 넣어 주었습니다. 이 마크업을 브라우저 화면에서 보면 위에서 아래로 나열된 모습을 볼 수 있습니다.

스타일 적용하지 않은 Layout 스타일이 적용되지 않은 화면

이제 이 마크업을 바탕으로 스타일을 적용하여 사이트 레이아웃을 만들어 보겠습니다.

레이아웃 제작을 위한 CSS

레이아웃을 제작하는데 사용되는 CSS 속성은 float, position, top, left, right, bottom 등입니다. 그리고 크게 float을 사용한 레이아웃과 position을 사용한 레이아웃으로 나뉠 수 있습니다. float을 사용한 레이아웃은 하위버젼 호환성이 좋습니다. 반면에 마크업에서 해당 섹션의 위치가 중요하게 됩니다. 화면상에서 위치가 많이 바뀌게 되면 마크업의 위치를 변경해 주어야 합니다. position을 이용한 레이아웃은 섹션의 위치를 자유롭게 지정 할 수 있습니다. 레이아웃의 가변성에 있어서는 position을 이용한 레이아웃이 float 보다 더 좋습니다. 좌측에 있는 메뉴를 마크업은 수정 안하고 CSS 만으로 우측으로 바꾸는 수정도 가능합니다. 여기서는 position을 이용한 레이아웃 설정을 소개하겠습니다.

레이아웃 조정은 아주 간단합니다.

#head {
	position: relative;
	height: 50px;
	background: #fcc;
}
#submenu {
	position: absolute;
	width: 180px;
	top: 60px;
	left: 10px;
	background: #cfc;
}
#content {
	min-height: 450px;
	padding-left: 210px;
	background: #ccf;
}
#foot {
	height: 40px;
	background: #ffc;
}

각각의 요소를 id를 이용해서 선택해 왔습니다. 그리고 크기나 여백에 대한 정의를 한 후, 위치를 설정해 주었습니다. background 속성은 각 요소를 시각적으로 구분 하기 위해서 사용한 것입니다. 실제로 사이트 디자인이 적용 될 때에는 이미지를 적용 하게 될 것입니다.

전체 CSS 파일은 아래와 같습니다.

/* HTML elements */
body {
	margin: 0;
	padding: 0;
}
hr {
	display: none;
}
/* layout */
#head {
	position: relative;
	height: 50px;
	background: #fcc;
}
#submenu {
	position: absolute;
	width: 180px;
	top: 60px;
	left: 10px;
	background: #cfc;
}
#content {
	min-height: 450px;
	padding-left: 210px;
	background: #ccf;
}
#foot {
	height: 40px;
	background: #ffc;
}
/* menu */
#head ul {
	position: absolute;
	bottom: 0;
	left: 500px;
}
#head ul li {
	float: left;
	width: 100px;
}
/* content */
#content h1, 
#content p {
	margin: 0;
}
#content h1 {
	padding-top: 10px;
}
#content p {
	margin-top: 1em;
}

실제 예제 페이지에서 확인해 보실 수 있습니다.

CSS Hack

browser issue

위의 코드를 이용해서 브라우저에서 랜더링을 해 보면 이상하게도 인터넷 익스플로러6에서는 파이어폭스와는 다르게, 좀 이상한 모습이 나타납니다. 왜 다르게 나타나게 되는 것일까요?

MS 인터넷 익스플로러에서 본 Layout MS 인터넷 익스플로러 에서 본 화면

HTML이나 CSS는 W3C에서 표준을 만들었습니다. 그리고 이 표준을 각각의 브라우저 만드는 회사에서 자신의 브라우저에 구현을 하는 것입니다. 이 과정에서 브라우저 만드는 회사들이 W3C의 표준을 잘 구현을 해 낸다면 별로 문제될 것이 없을 것입니다. 하지만 실제로는 브라우저 만드는 회사들 마다 구현 정도에 차이가 있습니다. 인터넷 익스플로러6은 우리가 가장 많이 사용하고 있는 브라우저이지만 출시된지 많은 시간이 지난 오래된 브라우저 입니다. 그래서 CSS의 구현 정도가 다른 브라우저보다는 떨어집니다. 이렇게 브라우저마다 구현된 CSS 스펙이 다르고, 어떠한 브라우저는 스펙을 잘못 이해하고 적용하는 경우도 있습니다. 가장 좋은 것은 최신의 스펙을 사용한 브라우저를 모든 사람들이 사용하는 것이겠지만 현실적으로 불가능 하기 때문에, 웹사이트 제작을 하는 사람들은 반드시 하위버젼 호환성과 브라우저 호환성을 염두에 두어야 합니다.

brower specific code

CSS 핵(hack)은 표준은 아닙니다. 이것은 브라우저의 CSS 해석 오류를 이용하여 특정 브라우저만을 위한 코드를 넣는 방법입니다. 표준으로 CSS를 작성을 하고 표준을 해석하는 것에 문제가 있는 브라우저 만을 위한 코드를 사용하여 문제를 해결하는 것입니다. CSS 핵의 사용에 대해서는 논쟁이 많습니다. CSS 핵 자체가 고의적으로 에러를 발생시키는 것이라고 볼 수도 있기 때문입니다. 하지만 여기서 소개하는 CSS 핵 들은 경험적으로 보아 사용해도 큰 문제가 없고 CSS 표준과 HTML 표준을 준수 하기 위해서는 어쩔 수 없이 사용해야 하는 경우도 있습니다.

몇몇 유용한 CSS 핵을 소개해 드리겠습니다.

인터넷 익스플로러에서만 인식 되는 코드

div.ie-hack {
	width: 100px;
	padding: 20px;
}
* html div.ie-hack {
	width: 140px;	/* 인터넷 익스플로러에서는 이줄을 인식하게 됨 */
}

인터넷 익스플로러의 경우 표준 DTD를 사용하지 않으면 padding이 표준과 다르게 랜더링 됩니다. 표준에서는 100 픽셀 너비에 20픽셀의 여백을 적용하면 화면에서 차지하는 박스의 너비는 140 픽셀이 되지만 인터넷 익스플로러는 여전히 100 픽셀입니다. 따라서 표준에 맞게 랜더링이 되게 하기 위해서 인터넷 익스플로러에서는 너비를 140 픽셀로 해주어야 합니다. '* html E' 선택자를 사용하게 되면 다른 브라우저들은 html 상위 요소가 존재하지 않기 때문에 인식이 안되지만 인터넷 익스플로러는 인식을 하게 됩니다.

인터넷 익스플로러5에서만 인식 되는 코드

div.ie5-hack {
	padding: 20px;
	width: 140px;
	voice-family: "\"}\"";
	voice-family: inherit;
	width: 100px;	/* 인터넷 익스플로러5는 이줄을 인식 하지 못함 */
}

인터넷 익스플로러6은 표준 모드와 호환모드 두개의 랜더링 모드가 있습니다. 이 것은 !DOCTYPE을 선언 하는 것으로 제어 할 수가 있습니다. !DOCTYPE을 표준으로 선언하게 되면 인터넷 익스플로러6은 표준 스펙을 따라서 랜더링이 되고 !DOCTYPE 선언을 다르게 하거나 하지 않으면 호환모드로 랜더링이 됩니다. 인터넷 익스플로러5는 표준 모드를 지원하지 않기 때문에 표준모드를 사용하게 되면 인터넷 익스플로러6과 인터넷 익스플로러5는 서로 다르게 화면을 랜더링하게 됩니다. 그래서 표준 모드를 지원 하지 않는 인터넷 익스플로러5를 위한 CSS 핵을 사용해야 하는 경우가 있게 됩니다. 위의 코드를 이용하게 되면 인터넷 익스플로러5는 첫번째 voice-family 선언에서 괄호(})를 CSS 선언의 종료로 인식하고 CSS 선언이 끝난 것으로 해석 합니다. 반면 다른 현대 브라우저들은 그 다음줄도 인식을 하기 때문에 최종적으로 너비는 100 픽셀이 됩니다.

CSS 핵을 이용해서 다시 원래의 레이아웃 코드를 수정해 보겠습니다.

#content {
	min-height: 450px;
	padding-left: 210px;
	background: #ccf;
}
* html #content {
	height: 450px;
}

인터넷 익스플로러는 아직 min-height 속성을 지원하지 않기 때문에 height 속성을 이용해서 높이를 정해줍니다. 인터넷 익스플로러는 height 속성도 표준과 다르게 구현하고 있습니다. 안의 내용이 높이를 초과하게 되면 높이를 지정을 하더라도 내용을 다 포함 할 수 있게 자동적으로 늘어납니다. 즉 인터넷 익스플로러의 height 속성은 CSS의 min-height 속성과 같게 구현된 것입니다. 같은 속성을 다르게 구현했기 때문에 단일한 코드로는 서로 같게 보이게 할 수 있는 방법이 없습니다. 이러한 상황에서는 CSS을 사용해서 문제를 해결할 수 있습니다.

이 외에도 CSS 핵에는 많은 종류가 있습니다. 맥용 인터넷 익스플로러5.2를 위한 핵, 오페라를 위한 핵, 넷스케이프 네비게이터4, 인터넷 익스플로러4 등을 위한 핵 등이 그러한 것들인데 대부분 최신버젼의 브라우저에서는 핵을 사용해야 할 만한 상황이 별로 없기 때문에 소개하지 않겠습니다.

결론

CSS는 문서의 구조와 표현을 분리할 수 있게 해주기 때문에 문서가 데이터로서의 가치를 갖게 되고, 표현은 일관적이고 수정이 용이해집니다. 잘 구성된 CSS 디자인 사이트는 더이상 사이트 개편을 위해서 전체 HTML 코드를 변경할 필요가 없습니다. 필요에 따라서 CSS 만 수정해 주면 되는 것입니다. 또한, 문서에서 디자인 적인 요소가 빠지고 구조와 데이터만을 가지고 있기 때문에 접근성이 매우 향상 됩니다. 이렇게 향상된 접근성은 특수한 환경에 있는 사용자나 보조 기기를 사용하는 사용자들이 쉽게 사이트에 접근 할 수 있도록 도와 줍니다.

재정경제부 정책토론장 사이트. 스타일이 적용된 화면

재정경제부 정책토론장 사이트의 스타일을 뺀 화면 스타일이 적용되지 않은 화면

유용한 사이트