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: 순서 없는 목록 - [본문으로]
  • 프로필사진
    Favicon of http://yourwebsite.com BlogIcon 조아영2011.06.29 18:48

    궁금한게 있는데요 CLL을 할줄알아야 위에있는 것을 할수있다는 내용인가요?
    CSS에 해봤는데 안되더라구요;;;

    • 프로필사진
      Favicon of https://circlash.tistory.com BlogIcon circlash2011.06.29 20:58 신고

      혹시 위 예제의 메뉴는 제대로 표시되시나요? 제가 확인한 바로는 IE8, Chrome, Firefox, Opera, Safari에서 제대로 적용되더라구요.

      CLL은 어떤 것을 말씀하시는지 잘 모르겠습니다;;; 위 내용은 티스토리의 skin.html에 HTML 코드를 입력하고 style.css에 CSS만 입력하면 적용됩니다. 혹시 위 코드 예제의 CSS와 HTML을 그대로 입력하셨나요?

  • 프로필사진
    Favicon of http://yourwebsite.com BlogIcon 조아영2011.06.30 08:09

    답글 달아주셔서 감사합니다.^^;
    잘되요..제가 잘몰라서.ㅠㅠ
    감사합니다

  • 프로필사진
    Favicon of http://yourwebsite.com BlogIcon 조아영2011.06.30 08:16

    궁금한게 생겨서 물어볼게요
    5번째 html에
    <li class="nav_cat root""><a href="/category"> Category ▽</a>
    li 엘리먼트에 nav_cat클래스와 root 클래스를 중복했잔아요?
    그런데 nav_cat클래스는 정의 되지 않았는데 왜 쓰신거에요?
    밑에 li엘리먼트를 정의하기 위해서 쓰신건가요?
    만약 그렇다면 .root li 이런식으로 되는건가요?

    • 프로필사진
      Favicon of https://circlash.tistory.com BlogIcon circlash2011.06.30 13:13 신고

      네, 맞습니다. nav_cat는 root 클래스의 li 요소와 category에 사용할 li 요소의 스타일을 구분하기 위해 사용했습니다. 또 category에 마우스 커서를 올렸을 때 실제 탐색 메뉴가 나오도록 하는 역할도 합니다.

      .nav_cat li {clear: both; background: transparent; border: 0}
      이 부분은 단순히 category의 li 요소 스타일을 root의 li 스타일과 구분하는 부분입니다.

      .nav_cat:hover .nav_sub {position: absolute; width: 100px; top: 33px; right: -21px; z-index: 99}
      이 부분은 category 글자에 마우스를 올렸을 때 세부 항목을 포함하는 nav_sub의 스타일을 지정한 부분입니다.

  • 프로필사진
    Favicon of https://ecotex.tistory.com BlogIcon 겨울소나기2011.09.20 02:22 신고

    블로그 만들면서 가장 많이 읽어본 글이 되었습니다.
    블로그에 관한 좋은 글 감사드립니다.
    제 사이트 http://ecotex.tistory.com 만들고 있는 중 입니다.
    외관은 타겟은 이 사이트 입니다. 특별한 이유는 없습니다.
    http://blog.creation.net/505
    올려주신 글을 2-3번 읽어 보고 copy수준으로 진행하고 있는데, 다음 2가지 문제 직면했습니다.
    1. 메뉴가 header안으로 들어가지 않음.
    2. conent 와 aside 부분을 붙이기 할 수 업습니다.
    div를 사용하여 wrap으로 헤드+콘텐츠+사이드바+풋터를 싸서 조정해야 하는지요.
    -----
    벌써 html5 오류 27개 왠지 모르겠네요?
    쉽지않은 작업이군요.

    • 프로필사진
      Favicon of https://circlash.tistory.com BlogIcon circlash2011.09.21 10:57 신고

      channy님 블로그 저도 가끔 가요~ 좋은 내용이 많아서요^^

      1. HTML에 menu가 header 안에 들어있지 않습니다. 헤더 안에 넣어주세요. 그 다음 위치 조정하면 됩니다.

      2. content는 700px, aside는 250px에 패딩값이 content 좌우 10px, aside가 좌우 10px. 전체 가로가 990px입니다. 그런데 전체를 싸고 있는 position 클래스는 1020px. 게다가 content는 float:left, aside는 float:right라서 둘 사이에 공간이 남는 것입니다. 전체 너비를 조정하던가 content, aside 둘 다 float:left를 하던가 하면 사이에 남은 공간이 없어질 겁니다.

      일단 오류는 레이아웃 완성한 다음 신경쓰셔도 될 것 같은데요~ 근데 에코텍스가 뭔가요? 궁금하네요^^

  • 프로필사진
    Favicon of https://ygang.tistory.com BlogIcon 연양갱2011.11.02 12:38 신고

    왼쪽 여백 40 이 계속 들어가네요 ㅠ ㅠ 어떻게 없애나요 ? ...

    • 프로필사진
      Favicon of https://circlash.tistory.com BlogIcon circlash2011.11.12 10:30 신고

      전체 여백을 이야기하시는건지 하위 메뉴 여백을 이야기하시는건지 확실히 모르겠지만, 아마 40이면 ul 요소의 기본 좌측 여백일 것 같습니다.

      해당 요소에 padding-left:10px!important 처럼 원하는 만큼 여백을 지정하시면 될 것 같습니다.

  • 프로필사진
    Favicon of http://stleamist.com/ BlogIcon Stleamist2012.03.26 20:38

    circlash님의 블로그 오른쪽 사이드바 버튼처럼 왼쪽 위의 곡선 반지름과 왼쪽 아래쪽의 반지름이 다르게 하려면 어떻게 해야 하나요?

    • 프로필사진
      Favicon of https://circlash.tistory.com BlogIcon circlash2012.03.28 12:39 신고

      CSS 내용은
      border-radius:3px 0 0 15px;
      -moz-border-radius:3px 0 0 15px;
      -webkit-border-radius:3px 0 0 15px;
      입니다.

      border-radius는 모서리를 둥글게 만드는 속성인데 예전 버전의 Firefox, Chrome 등에 사용하려면 -moz, -webkit을 앞에 붙여야 합니다.

      border-radius 속성에 네 가지 수치를 연속으로 사용하면 왼쪽위, 오른쪽위, 오른쪽 아래, 왼쪽 아래에 순서대로 적용됩니다.

      위 스타일을 적용하면 제 블로그 메뉴처럼 왼쪽 위 모서리는 3px만큼 둥글게, 왼쪽 아래 모서리는 15px만큼 둥글게, 나머지 두 머서리는 둥글지 않게 설정됩니다.

  • 프로필사진
    Favicon of http://blog.naver.com/ddowner BlogIcon 검둥이2013.11.26 16:54

    깔끔하게 정리되있네요 ㅋ 블로그에 주소만 담아갈게요^^