CSS로 이미지, JavaScript 없는 블로그 메뉴 만들기

2011. 5. 5. 02:03IT/Tistory Tips

CSS로 CCL각주를 만든 것처럼 블로그 메뉴도 만들 수 있다. CSS만으로 블로그 메뉴를 만들면 이미지나 JavaScript를 내려받고 연산하는 데 시간이 허비되지 않으므로 페이지 로딩이 빨라지고 메뉴 표시에 시간 지연도 없다. ul 요소를 중복으로 사용해서 HTML 코드를 작성하고 CSS만 적용하면 끝이다. 아래의 메뉴는 마우스 커서를 올리면 확장되는 분류(Category)를 포함한 블로그 메뉴 예제다.

블로그 메뉴 소스 코드
HTML 코드
<ul class="nav">
<li class="root fst"><a href="/">Home</a></li>
<li class="root"><a href="/tag">Tag</a></li>
<li class="root"><a href="/media">Media</a></li>
<li class="nav_cat root""><a href="/category"> Category ▽</a>

  <ul class="nav_sub">
  <li class="nav_sub1-1"><a class="trg" href="/category/일상">일상 ▷</a>

    <ul class="nav_sub1">
    <li><a href="/category/일상/습작">습작</a></li>
    <li><a href="/category/일상/문화생활">문화생활</a></li>
    <li><a href="/category/일상/주절주절">주절주절</a></li>
    </ul>

  </li>
  <li class="nav_sub2-1"><a class="trg" href="/category/컴퓨터">컴퓨터 ▷</a>

    <ul class="nav_sub2">
    <li><a href="/category/컴퓨터/컴퓨터 팁">컴퓨터 팁</a></li>
    <li><a href="/category/컴퓨터/한글화">한글화</a></li>
    <li><a href="/category/컴퓨터/블로그">블로그</a></li>
    <li><a href="/category/컴퓨터/시스템 유지, 관리">시스템 유지, 관리</a></li>
    <li><a href="/category/컴퓨터/인터넷">인터넷</a></li>
    <li><a href="/category/컴퓨터/멀티미디어">멀티미디어</a></li>
    <li><a href="/category/컴퓨터/파일 관리">파일 관리</a></li>
    <li><a href="/category/컴퓨터/압축 프로그램">압축 프로그램</a></li>
    <li><a href="/category/컴퓨터/CD/DVD">CD/DVD</a></li>
    <li><a href="/category/컴퓨터/보안">보안</a></li>
    <li><a href="/category/컴퓨터/오피스">오피스</a></li>
    <li><a href="/category/컴퓨터/기타">기타</a></li>
    </ul>

  </li>
  <li class="nav_sub3-1"><a class="trg" href="/category/기타">기타 ▷</a>

    <ul class="nav_sub3">
    <li><a href="/category/기타/음식">음식</a></li>
    <li><a href="/category/기타/건강 상식">건강 상식</a></li>
    </ul>

  </li>
  <li><a href="/category/임시 보관소 (비공개)">임시 보관소</a></li>

</ul>
</li>
<li class="root"><a href="/guestbook">Guestbook</a></li>
<li class="root"><a href="/admin">Admin</a></li>
<li class="root"><a href="/admin/entry/post">Post</a></li>
</ul>
CSS 코드
.nav .root {width: 90px; text-align: center; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc}
.fst {border-left: 1px solid #ccc}
.nav li {float: left; list-style-type: none; padding: 5px 10px; position: relative; background: #ededeb; border-right: 1px solid #ccc}
.nav li a:link, .nav li a:visited, .nav li a:hover, .nav li a:active, .nav li a:focus {color: #666; text-decoration: none}
.nav_cat li {clear: both; background: transparent; border: 0}
.nav_sub {position: absolute; background: #f7f7f7; border: 1px solid #ccc; margin-left: -99999em; line-height: 1.5em; text-align: left; padding-left: 10px!important}
.nav_cat:hover .nav_sub {position: absolute; width: 100px; top: 33px; right: -1px; z-index: 99}
.trg {display: block; width: 160px}
.nav_sub1, .nav_sub2, .nav_sub3 {position: absolute; background: #f7f7f7; border: 1px solid #ccc; margin-left: -99999em; line-height: 1.5em; text-align: left; padding-left: 10px!important}
.nav_sub1-1:hover .nav_sub1, .nav_sub2-1:hover .nav_sub2, .nav_sub3-1:hover .nav_sub3 {position: absolute; width: 120px; top: -1px; right: -52px; z-index: 100}

길어서 복잡해 보이지만, 하나씩 뜯어보면 생각보다 간단하다. 일단 HTML 코드를 보자. HTML 코드의 붉은 글씨 부분이 1단계 메뉴인 전체 메뉴 가로줄(Home, Tag, ..., Post)을 구성하는 부분으로, ul1각주 1Unordered list: 순서 없는 목록 요소로 구성된다. ul 요소 아래 li 요소에 1단계 메뉴 항목인 Home, Tag, Media, Category, Guestbook, Admin, Post가 들어간다. 이 항목들을 class="root"로 지정했다. 나머지는 모두 Category 항목의 하위분류를 표현하기 위한 부분이다.

Category 아래에 class="nav_sub"란 ul 요소를 다시 배치한다. HTML 코드에 주황색으로 표시된 부분이다. <ul class="nav_sub"> 부분이 Category에 마우스 커서를 올렸을 때 말풍선으로 표시될 2단계 메뉴 부분이다. <ul class="nav_sub"> 아래의 li 요소에 블로그 대분류 항목인 일상, 컴퓨터, 기타, 임시 보관소를 배치했다.

마지막은 3단계 하위분류를 표시할 차례다. HTML 코드에 파란 글씨로 표시했다. <ul class="nav_sub1(2, 3)">이 각각 일상의 하위분류, 컴퓨터의 하위분류, 기타의 하위분류다. ul 아래 li 요소에 3단계 분류의 세부 항목을 입력한다. 여기까지 구성했으면 반은 끝났다. 이제 CSS만 작성하면 끝이다.

CSS는 CCL각주 게시물을 읽었다면 아주 간단히 끝난다. 기본 개념은 완전히 같다. 일단 .nav .root는 1단계 메뉴(Home, Tag, ..., Post) 부분의 스타일이다. 너비 80픽셀, 글자 가운데 정렬, 상하 테두리 1픽셀을 지정했다. .fst는 1단계 메뉴 중 Home 항목 왼쪽 테두리 표시를 위해 임의로 삽입한 부분이다. div 요소나 기타 다른 요소를 사용하면 더 깔끔하게 코드를 정리할 수 있지만, 일단 메뉴 자체 구성을 이야기하기 위해 ul 요소를 제외한 다른 요소는 포함하지 않았다. .nav .root와 .fst 모두 크게 중요하지 않으니 넘어가자.

.nav li는 메뉴에 사용한 모든 li 요소(하나하나의 세부 항목)에 적용되는 스타일이다. float:left는 block 요소를 마치 inline 요소처럼 왼쪽으로 정렬하는 부분이다. 블로그 메뉴 자체를 세로로 구성하려면 필요 없는 부분이지만, 위 예제는 기본 메뉴가 가로로 구성되므로 float:left를 사용해서 1단계 메뉴(Home, Tag, ..., Post) 부분이 가로로 배열되도록 했다. list-style-type:none은 ul 요소의 각 항목 앞에 목록 구분을 위한 작은 원 표시를 없애는 것이다. padding으로 내부 여백, background로 배경색, border-right로 오른쪽 테두리를 표시했다. 앞에서 상하 테두리, 첫 번째 왼쪽 테두리를 이미 추가했으므로 이제 1단계 메뉴 항목은 상하좌우 테두리가 모두 표시된다. position:relative는 Category 항목에 마우스 커서를 올렸을 때 2단계 메뉴를 불러오는 데 필요한 부분이니 꼭 그대로 놔둔다.

.nav li a:xxxx 부분은 메뉴의 하이퍼 링크(a) 항목 스타일이다. link는 평소 때, visited는 이미 방문한 항목, hover는 마우스 커서를 올렸을 때, active는 활성화됐을 때(마우스 단추를 클릭했을 때), focus는 현재 하이퍼 링크 항목에 포커스가 가 있을 때 스타일이다. 각각 다른 스타일을 적용해도 되고 위 예제처럼 모두 같은 스타일을 적용해도 된다. 여러 선택자에 같은 스타일을 적용할 땐 각 선택자를 쉼표(,)로 구분한다. 여기선 글자색은 짙은 회색(색상 코드 #666666), 글 꾸밈(하이퍼 링크 항목에 밑줄 등)은 없도록 지정했다.

.nav_cat li는 Category 항목 하위분류(2단계 분류, 3단계 분류)의 li 요소(개별 목록) 스타일이다. clear:both는 앞에서 메뉴를 가로로 배열하기 위해 사용한 float:left 속성을 없애는 것이다. float가 block 항목을 띄워서 왼쪽 또는 오른쪽으로 붙여버리는 속성이라면 clear는 float 속성을 없애서 원래의 block 속성으로 되돌아가도록 한다. clear는 left, right, both, none 값을 사용할 수 있는데 여기선 clear:left를 사용하나 clear:both를 사용하나 결과는 같다. background:transparent는 1단계 메뉴에 적용된 배경색을 투명으로 바꾸는 속성이다. 이 속성을 지정하지 않으면 1단계 메뉴와 2단계 메뉴 배경색이 다를 때 2단계 메뉴 배경색 위에 1단계 메뉴 배경색에 나타날 수 있다. border:0 역시 1단계 메뉴에서 li 요소에 오른쪽 테두리를 표시하도록 지정한 속성을 없애기 위해 지정한 부분이다.

.nav_sub부터 본격적으로 2단계 메뉴(팝업 메뉴)에 대한 스타일이다. 2단계 메뉴 표시 위치 지정을 위해 position:absolute를 사용했다. 메뉴 표시를 위해 꼭 필요한 부분이다. background에서 1단계보다 옅은 배경색을 지정하고 border로 테두리를 표시했다. line-height:1.5em으로 줄 간격을 글자 크기 150%로 지정하고 text-align:left로 각 항목을 왼쪽 정렬했다. 마지막 margin-left:-99999em으로 왼쪽 여백을 과도하게 지정해서 화면에 2단계, 3단계 메뉴가 보이지 않도록 했다. padding-left: 10px!important는 원래 ul 요소의 좌측 여백을 강제적으로 조정하기 위한 값으로 10px 대신 원하는 좌측 여백을 입력한다.

.nav_cat:hover .nav_sub는 1단계 메뉴 Category 항목에 마우스 커서를 올렸을 때 2단계 메뉴의 상태를 지정하는 부분이다. 기본 상태에서 2단계 메뉴는 화면에 표시되지 않으니 Category 항목에 마우스 커서를 올렸을 때 올바른 위치에 표시되도록 지정해야 한다. position:absolute는 앞서 말한 것처럼 메뉴 사용을 위해 꼭 필요한 부분이니 삭제하지 않는다. width:100px로 2단계 메뉴 너비를 지정하고 top, right로 2단계 메뉴 위치를 지정했다. top은 1단계 메뉴 맨 위에서부터 거리로 33픽셀 아래이고 right는 1단계 메뉴 오른쪽에서 거리로 음수(-n)를 사용해서 오른쪽에서 왼쪽으로 1픽셀만큼 옮겼다. z-index는 2단계 메뉴가 다른 항목에 가리지 않도록 더 위에 보이게 지정한 부분이다. 99라는 값을 사용했지만, 실제론 블로그 스킨이나 홈페이지 구성에 따라 바꿀 수 있다. 여러 항목이 겹쳤을 때 z-index가 더 큰 항목이 위에 표시된다.

.trg는 2단계 메뉴 항목 중 3단계 메뉴를 불러와야 하는 일상, 컴퓨터, 기타 항목 스타일이다. display:block 속성으로 inline 요소인 a 요소에 block 속성을 부여했다. 이는 너비를 지정하기 위함인데, a 요소에 너비를 지정하지 않으면 3단계 메뉴를 불러올 때 마우스 커서가 글자를 벗어나면 3단계 메뉴가 사라진다. 그래서 2단계 메뉴 전체 너비에 맞게 일상, 컴퓨터, 기타 항목 너비를 지정해서 3단계 메뉴를 사용하는 데 지장이 없도록 했다.

이제부터 3단계 메뉴 부분이다. .nav_sub1, .nav_sub2, .nav_sub3은 각각 일상, 컴퓨터, 기타 항목의 하위분류인 3단계 메뉴 부분이다. position:absolute는 여러 번 이야기했으니 넘어가자. background와 border로 배경색 및 테두리 스타일을 지정했다. 여기선 2단계 메뉴와 똑같이 지정했지만, 사용자가 원하는 색으로 바꿔서 2단계와 3단계 메뉴 배경색을 다르게 할 수 있다. margin-left:-99999em으로 평소 때 3단계 메뉴가 표시되지 않도록 했다. line-height:1.5em은 줄 간격을 글자 크기 150%로 지정한 부분, text-align:left는 글자를 왼쪽 정렬한 부분이다.

마지막 .nav_sub1-1:hover .nav_sub1, .nav_sub2-1:hover .nav_sub2, .nav_sub3-1:hover .nav_sub3은 2단계 메뉴의 일상, 컴퓨터, 기타 항목에 마우스 커서를 올렸을 때 3단계 메뉴가 화면에 나타나도록 지정하는 부분이다. position:absolute는 넘어가고 width는 3단계 메뉴 너비 지정 부분이다. top: -1px; right: -52px로 일상, 컴퓨터, 기타 항목에 마우스 커서를 올렸을 때 각 하위분류가 표시될 위치를 지정한다. 2단계 메뉴 너비나 줄 간격, 글자 크기 등에 따라 위치를 적절히 조정한다. 마지막 z-index: 100은 2단계 메뉴와 3단계 메뉴가 겹칠 때 3단계 메뉴가 더 위에 표시되도록 하기 위한 부분이다. 앞에서 z-index 값이 클수록 위에 표시된다고 했는데, 2단계 메뉴는 z-index가 99고 3단계는 100이므로 3단계 메뉴가 2단계 메뉴 위에 표시된다.



위 기본 예제에서 배경색, 테두리 색만 바꿔도 다양한 메뉴를 연출할 수 있다. 또 2단계 메뉴 ul 요소(.nav_sub)와 3단계 메뉴 ul 요소(.nav_sub1, .nav_sub2, .nav_sub3) 스타일에 border-radius(-moz, -webkit), box-shadow(-moz, -webkit) 스타일을 추가하면 IE9, Chrome, Firefox, Opera, Safari에서 말풍선 테두리가 둥글게 나오고 그림자도 표시된다. float:left와 clear:both를 없애면 가로가 아닌 세로로 배열된 메뉴도 만들 수 있다. CSS를 사용한 메뉴는 IE8 이상, Chrome, Firefox, Opera, Safari에서 사용할 수 있다.

  1. Unordered list: 순서 없는 목록 - [본문으로]