이미지 메뉴를 더 가치있게
Tuesday, June 13, 2006 
W3C 에서 권고하는 디자인(프레젠테이션)과 문서(컨텐츠)의 분리는 많은 이득을 가지고 옵니다. 물론 반론도 있지만요 ^^;; 분리로 인해 디자인은 더욱 자유로울수 있으며 훨신 높은 유연성을 가질수 있게됩니다. 문서 또한 문서대로 의미에 맞는 태그안에 분류하여 의미를 부여하고 문서에 충실할수 잇는 효과를 불러올수 있습니다. 지난번 CSS 옷벗는날(css naked day) 에 각자의 블로그 스타일시트를 꺼 놓아서 문서와 디자인의 분리를 명확히 보여주었던 일도 있었죠. 하지만 이러한 장점들 앞에도 장애물이 있습니다. 이미지가 대부분 사용되는 메뉴 혹은 네비게이션 부분입니다.
문제는 이렇습니다. 이미지로 텍스트를 대체하면 접근성에 문제가 되니 이미지를 포기해야 하고 텍스트를 쓰자니 글꼴이 받쳐주질 않아 이러지 저러지도 못하고 메뉴 이미지에 title 넣는 정도로 만족을 하는 경우가 많습니다. 혹은 이미지 맵을 사용하는 경우도 많구요. 이런 애매한 경우를 간단한 CSS 로 손을 보면 접근성에 어긋나지 않도록 어느정도 커버가 가능하니 한번 살펴보겠습니다. 예제는 제 블로그 메뉴를 보아도 되고 맨밑에 링크를 첨부해 놓았습니다.
text-indent
여기서 중요하게 사용이 될 속성은 text-indent 입니다. 문단이 시작할때에 첫 문장이 몇칸정도 공간을 둔 후에 시작하는데 사용할수 있는 text-indent 입니다.
div#hello { text-indent: 3em; }
hello 라는 div 의 안에 있는 글자를 3em 정도 띄고 시작하라 라는 말이되겠죠.
이것을 응용하여 #hello 에 3000px 을 주면, 글자는 div의 위치에서 3000px 이 떨어진 곳에서 시작을 하게 됩니다. 다시말하면 모니터 화면 밖에 위치하고 있겠죠. 물론 div 자체의 위치는 변하지 않습니다.
메뉴만들기
text-indent 를 이해하셨으면 대충 감이 잡히셨으리라 생각됩니다. 차근차근 단계적으로 설명하겠습니다.
일단 알려진 3가지 방법을 소개하겠습니다. 텍스트대체 이미지들은 이 방법들을 약간씩 변화시켜 사용하고 있으니 이것들만 아셔도 문제없을거라 생각됩니다.
- Phark revisited 방법
먼저 html 에는 의미적으로 맞게 단순히 링크와 텍스트만 넣습니다. 예를들어 이렇게 넣습니다.<div id="menu"> <ul> <li id="menu_home"><a href="index.html" title="첫페이지로 이동">첫페이지로</a></li> <li id="menu_intro"><a href="introduce.html" title="소개페이지로 이동">소개합니다</a></li> </ul> </div>
menu 라는 div 안에 리스트를 넣어서 각각의 리스트에 링크를 담은 메뉴들을 넣었습니다. 그리고는 링크를 담고 있는 리스트들에 id 로 고유이름을 정해 주었네요.
그리고 이제 css 가 모든걸 하게 합니다.
/* menu 라는 div 의 li(리스트) 안에 들어있는 링크는 모든 텍스트를 모니터에서 치운다 */ #menu li a { text-indent: -5000px; } /* 이제 각각의 링크에 이미지를 준다. */ /*첫번째 메뉴에 배경을 넣는다 */ #menu_home a { background: url(home.gif) no-repeat 0 0; } /*마우스를 메뉴에 놓았을때에 이미지가 변하게 한다 */ #menu_home a:hover { background: url(home_hover.gif) no-repeat 0 0; } /*두번째 메뉴에 배경을 넣는다 */ #menu_intro a { background: url(intro.gif) no-repeat 0 0; } /*마우스를 메뉴에 놓았을때에 이미지가 변하게 한다 */ #menu_intro a:hover { background: url(intro_hover.gif) no-repeat 0 0; }
텍스트가 모니터 밖에 있으니 배경이미지만 보일것이고 hover 때에 다른 배경이미지를 보여주면 js 를 쓰지 않고도 간단히 마우스 오버 효과가 나타나게 됩니다. 이것은 css 만 트릭을 준것이기 때문에 스타일을 껐을때, css 를 껐을때엔 모니터 밖으로 나갔던 텍스트가 돌아오게되니 문서적인 부분은 문제가 되지 않습니다.
- FIR(Fahrner Image Replacement) 방법
두번째 방법은 메뉴 글자들이 text-indent 로 모니터 밖에 존재하는것이 싫으신 경우입니다. 별로 큰 변화는 업고 단지 위 html 부분에서 링크안의 텍스트에 <span> 을 넣어 주는겁니다.<div id="menu"> <ul> <li id="menu_home"><a href="index.html" title="첫페이지로 이동"><span>첫페이지로</span></a></li> <li id="menu_intro"><a href="introduce.html" title="소개페이지로 이동"><span>소개합니다</span></a></li> </ul> </div>
그후 css 에서 text-indent 를 사용하는대신 span 에다가 display:none; 을 적용시켜주는 방법이 있겠습니다.
#menu li span { display:none; }
text-indent 를 사용하지 않아도 되는 깔끔함이 있지만 html 자체에 불필요한 span을 넣어주어야 한다는게 결점이겠습니다.
- Leahy/Langridge 방법
마지막으로 약간은 복잡할수 있는 방법입니다. 이것은 overflow 와 padding 을 사용한 방법입니다. 대표적으로 SXSW 사이트가 사용하고 있죠.아이디어는 이렇습니다. list 의 높이(height)값을 0으로 설정한후 padding을 메뉴이미지 높이만큼 준 후에 overflow되는것들은 hidden 하라고 설정을 하는것입니다. 이렇게 설정을 하면 텍스트가 height 밖으로 위치하지만 overflow:hidden 이기에 보이지 않게 되는 것이죠.
<div id="menu"> <ul> <li id="menu1"><a href="index.php" title="Home">Home</a></li> <li id="menu2"><a href="intro.php" title="Intro">Intro</a></li> </ul> </div>
그 후 css 는 이렇게 설정해 주면 됩니다
/* 배경 이미지가 50px 의 height 을 가지고 있다고 가정 */ #menu li a { display: block; height: 0px !important; height /**/: 50px; padding: 50px 0 0 0; overflow: hidden; } #menu1 a {background: url(home.gif) no-repeat;} #menu1 a:hover {background: url(home_hover.gif) no-repeat;}
이런식으로 응용해 주시면 됩니다. 이미지를 많이 쓰고 싶지 않다면 한개의 이미지에 hover 했을때와 아닐때의 이미지를 합치셔서 background-position 값을 조절하시면 편하겠죠.
거의 대부분의 메뉴들이 이미지(혹은 플래쉬)로 형성되어있는 상황인 만큼 이러한 css 의 응용법도 괜찮다고 생각됩니다. 후에 맑은고딕이 많은 변화를 주겠지만 지금상황으로써는 약간의 코딩이 좀 들어가더래도 쓸만하겠네요.














나니
June 13th, 2006 at 1:10 am 인용
제 방식대로 css로 이미지 메뉴 컨트롤하는 방식이 있었는데
제가 사용하는것보다 코딩이 간결해서 좋아요
일몰님 최고
[Reply]
개울
June 13th, 2006 at 2:13 am 인용
한RSS 사용자인데 구독기에서 이 글을 읽을 때 1번에 삽입하신 css 코드 끝부분과 2번 첫부분이 7줄 정도 겹쳐서 보이네요. 한RSS의 문제인지 이 블로그의 문제인지 모르겠습니다만 처음 보는 현상이라 알려드립니다.
[Reply]
HFK
June 13th, 2006 at 2:19 am 인용
Adobe 사이트에서도 CSS를 이용해 비슷한 방법을 쓰고 있는데, 좀 복잡한 것 같더군요. 디자인과 문서를 구분한다는 점에선 상당히 유용한 방법인 것 같습니다. 좋은 걸 배우고 갑니다.
[Reply]
성렬
June 13th, 2006 at 4:36 am 인용
개울님: http://www.hanrss.com/myfeeds_main.qst?fsrl=3602 인데, IE나 Opera에선 문제없는데 FF에서만 겹쳐보이는군요. 원인은 에서 “height:280px”이 영향을 주는 거였고요. 그냥 참고상… 약간 희한한 현상이긴 하네요.
[Reply]
일모리
June 13th, 2006 at 6:48 am 인용
네 어도비는 약간의 js 를 첨가한 css 인데 깔끔하고 좋죠 ^^
아마도 포스팅안의 코드들을 출력하는 플러그인때문인거 같습니다. ^^ 살펴보겠습니다.
[Reply]
PRAK
June 13th, 2006 at 6:48 am 인용
이삼구님의 처음 글부터 여기까지 따라 왔습니다. 두 분 건강하게 논의를 발전시켜 나가시는 것이 보기 좋습니다.^^
만약 제가 일모리님께서 말씀하신 “디자인과 문서의 분리가 가져오는 많은 이득”을 웹2.0이라는 context에서 구체화해 본다면, 그것은 아마 Perpetual beta에 적합하다는 것일 겁니다.
이제 웹사이트라는 것이 한번 만들어 놓고 줄창 가는 것이 아니라 사용자의 요구, 새로운 아이디어에 맞추어 지속적으로 컨텐츠나 디자인을 업데이트해야 하는 것이라고 할 때, 만약 각 디바이스에 따라 또 사용자 환경에 따라 따로 만들어둔 페이지들을 모두 수정해야 한다면 인력과 시간이 많이 필요하겠지요. 하지만 컨텐츠와 디자인이 분리되어 있으면 보다 더 빨리, 비용효율적으로 시장의 요구에 대응할 수 있게 되는 것 같습니다. 아마 이것이 CSS가 Perpetual beta로 유지되는 lightweight business model에 있어 가장 큰 잇점일 겁니다. 듣자하니 플릭커는 30분마다 새로운 빌드가 올라온다고 하지요..
[Reply]
신현석
June 13th, 2006 at 7:36 am 인용
사파리에서도 겹쳐요~
“응용법” 같이 이미지가 아닌 링크를 사이에 구분 없이 딱 붙이면 접근성이 떨어 집니다. ㅎㅎ
[Reply]
okoru
June 13th, 2006 at 9:55 am 인용
http://www.virga.info/blog/index.php/2006/06/11/new-css-replacement.html
제 친구는 이런 방법을 쓰던데, 불필요한 span 태그만 제외하곤 괜찮은 방법인것 같습니다. 지금까지와는 다르게 이미지를 보이지 않게 해도 텍스트가 보인다는 장점이 있죠.
[Reply]
은빛늑대
June 13th, 2006 at 10:27 am 인용
text-indent 를 이용해서 ‘글자 바꿔치기’ 를 하자는 의미인 것 같군요.
이렇게 하니 실제로는 글자가 존재해서 읽어 주는 장점이 있네요.
[Reply]
일모리
June 13th, 2006 at 10:53 am 인용
현석님은 예리하심다 ㅠ.ㅠ;
okoru// 네 위의 3가지 다른 방법들이 다 이미지, 스타일을 껐을때에 텍스트가 보여지는 방법들 입니다.
작년부터 첫번째 방법을 써오고 있는데 만족하고 있습니다. 음,, 친구분의 span 낭비는 약간 무의미하게 사용되는거 같아서 추천해드리고 싶지는 않네요. ^^ span 사용을 굳이 원하시면 두번째 방법도 괜찮겠죠. 첫번째는 무난하고 세번째는 좀 프로페셔널한,, ^^;;
은빛늑대// 해외에서는 워낙 폰트가 받쳐주기때문에 많은 사용은 않더군요. 하지만 국내에선 많이 쓸만하죠.
[Reply]
일모리
June 13th, 2006 at 11:53 am 인용
prak님 죄송합니다. model이라는 단어때문에 moderation 에 들어가 있었습니다. ^^
잘 찝어 주셨네요 ^^; espn 도 뉴스크기에 따라서 이미 preset 된 css 조절로 간단히 레이아웃 자체를 변형하고 있습니다. 단 몇분안에 최신뉴스가 올라와야하는 스포츠언론사 웹사이트로서는 인력만큼 시간또한 중요하죠. 문서 디자인분리는 많은 이득을 가져오는거 같습니다.
[Reply]
okoru
June 13th, 2006 at 8:11 pm 인용
혹시 잘못 말씀 하신 건가요? 3가지 방법 전부 이미지가 안보이도록 설정할 경우 텍스트도 보이지 않을텐데..
[Reply]
일모리
June 14th, 2006 at 1:56 am 인용
앗 네 제가 잘못이해했군요! 죄송합니다. 친구분께서 보여주신 방법은 Shea Enhancement 이라고 말씀하신데로 이미지를 껐을때에도 텍스트가 보이게 하는 유일한 방법입니다. 제가 알려드린 3가지 모두 텍스트가 안보이죠. 지적감사합니다. =]
[Reply]
Jay G.
June 15th, 2006 at 2:01 am 인용
위에서 소개하신 기술이 Todd Fahrner의 이름을 딴 FIR(Fahrner Image Replacement) 같군요.
사용하시는 분들은 이런 점을 유의하셔야 할 것 같습니다.
사실 저도 제 블로그에서 이 기술을 사용하긴 하지만 실제로 접근성에 있어서 문제가 있다는 보고가 있습니다. 대부분의 스크린 리더에서 제대로 읽어주지 못한다고 하는 실험결과도 있구요.
자세한 내용은 A List Apart의 글을 참고하세요.
Flash를 이용한 sIFR 이라는 기술도 있습니다.
Introducing sIFR: The Healthy Alternative to Browser Text
제 블로그는 나름의 장점 때문에 두 기술을 섞어서 사용하고 있구요.
그리고 맑은고딕이 분명히 한글 표준 폰트의 역할을 하겠지만 사실 윈도우의 한글 폰트일 뿐인데 이점이 좀 마음에 들지 않네요.
[Reply]
일모리
June 15th, 2006 at 6:22 am 인용
Jay 님도 ALA 를 즐기시는군요. 저도 매번 나오는것들은 읽는다고 하는데 워낙 방대하다보니 몇년이되도 못읽겠습니다. ㅎㅎ
네 말씀하신데로 제가 소개한 3가지 방법중 두번째가 바로 FIR 방법입니다. 일단 display:none; 자체가 들어간다는 것에대한 우려가 높죠.
간단히 말해서 후에 css 를 이해해서 일어주는 스크린리더에겐 위의 방법이 읽혀지지 않을것이다 라고 되어있네요. 덕분에 좋은글 읽었습니다.
제가 즐거쓰는 방법이 첫번째 방법인데, 이 Phark Revisited 방법은 스크린 리더에도 괜찮은걸로 알고 있습니다. okoru 님께서 지적하신 이미지를 껐을때에 텍스트가 보이지 않는다는게 단점이겠죠. 좋은 지적 이십니다. ^^
ps. 위의 방법들에다가 이름을 달아 주어야겠군요
[Reply]
Jay G.
June 15th, 2006 at 9:36 am 인용
사실 위 글이 공개된 후 몇 가지 대안이 나오긴 했지만 완벽한 해결책은 없다고 합니다. 그리고 ‘CSS를 이해해서 읽어주는 스크린리더’라면 위 방법들도 신중하게 사용하여야 할 듯 합니다.
Stopdesign의 글 ‘Using Background-Image to Replace Text’도 참고하세요.
[Reply]
okoru
June 15th, 2006 at 7:51 pm 인용
CSS의 경우 media를 설정할 수 있는데도 스크린리더에서 문제가 되나요? 스크린리더가 media=”screen”의 경우에도 CSS를 처리하는지 궁금합니다.
“element:value” 라거나 하는 가상클래스(엘레멘트 속의 텍스트만을 선택하는..)가 있으면 좋겠습니다. CSS3에선 구현 되려나..
[Reply]
Jay G.
June 16th, 2006 at 10:26 am 인용
@okoru:
Stopdesign의 글을 보면 미디어 타입을 적용해도 문제가 되는 것 같습니다. 그리고 ALA의 글을 보면 스크린 리더는 대부분 음성과 함께 화면 또는 점자를 동시에 출력하는 ‘multimodal devices’이기 때문에 현재의 미디어 타입에 문제가 있다고 지적합니다.
[Reply]
ssari
July 9th, 2007 at 11:24 am 인용
위 Phark revisited 방법을 적용했을시..
배경이미지도 text-indent가 같이 적용이 되서
안보입니다..저만 안되는건가요?? ㅡㅡ;
[Reply]