티스토리 뷰


* 이번에는 마우스 오버 이미지 배너를 만드는 방법을 알아볼 것이다. 이러한 마우스 오버될 때 이미지가 변경되는 것은 다양한 방법들이 있는데, 이러한 방법들을 해당 태그의 중요도나 위치에 따라서 다르게 구현하는 방법들을 적용하면 UX가 향상된 홈페이지를 만들 수 있을 것이다. 만약 모든 경우에 오직 한가지 방법만 고집한다면 각 방법들의 적용 방법을 익혀서 필요에 따라서 사용한다면 아주 좋을 것이다.


- 이전글

2013/11/01 - [밑바닥부터 홈페이지 만들기] 예고편

2013/11/01 - [밑바닥부터 홈페이지 만들기] HTML5 기본 템플릿, DOCTYPE 종류

2014/01/13 - [밑바닥부터 홈페이지 만들기] 최종 목표 예고 - toc21.com

2014/01/15 - [밑바닥부터 홈페이지 만들기] nav, ul, li 태그 HTML과 CSS로 가로형 메뉴 만들기

2014/01/22 - [밑바닥부터 홈페이지 만들기] HTML과 CSS로 드롭다운 메뉴 만들기



* 마우스 오버 이미지

: 마우스오버 이미지는 다양하게 활용이 되고 있는데, 특별하게는 배너로 많이 사용되고 있다. 만약 '글씨색이나 배경색'이 바뀌는 배너에 이미지를 이용한 마우스 오버를 생각하고 있다면 최소 1번의 request, 또는 2번의 request를 만들어버리는 다소 비효율적인 구현 방법일 것이므로 먼저 이미지를 이용한 마우스 오버 배너가 반드시 필요한지 검토한 다음에 적용하는 것이 좋다. 그렇다면 다양한 마우스오버 배너를 구현하는 방법들에 대해서 살펴보자.



* CSS의 background를 기반으로 구현

: css를 기반으로 구현하게 되면 너무나 간단하게 구현이 가능하기 때문에 아주 쉽게 사용할 수 있는 방법이다. 먼저 이미지 배너를 넣을 곳에 해당 태그를 넣자.

    <div id="rightBanner"></div>

: 이렇게 기본 이미지와 마우스 오버 이미지를 보여줄 배너를 넣을 div를 만들었다. 정말 이게 끝이다. 그리고 나머지는 css로 '아주 간단하게' 끝이난다.

<style>
    #rightBanner {
        width: 250px;   /* 배너의 가로 사이즈 설정 */
        height: 167px;  /* 배너의 세로 사이즈 설정 */
        background: url('https://t1.daumcdn.net/cfile/tistory/197E8B3E4F52C12926') no-repeat center;  /* 배너의 기본 이미지를 백그라운드로 설정 */ 
    }
    #rightBanner:hover {
        background: url('https://t1.daumcdn.net/cfile/tistory/176CF9414F493C5614') no-repeat center;  /* 배너의 마우스오버 이미지를 백그라운드로 설정 */
    }
</style>

: 이렇게 스타일을 설정하고 나면 아래와 같이 해당 div는 백그라운드 이미지와 마우스오버때 사용한 이미지를 가지게 된다.



: 끝. 그야말로 너무나 간단한 구현 방법이다. 하지만 이러한 방법은 위의 div에 마우스오버를 처음 실행하게 되면 그 단점이 나타나게 된다. 바로 hover로 설정한 이미지는 마우스오버가 되면 그때서야 브라우져에서 해당 이미지를 요청하여 다운받게 되므로 첫 마우스 오버에 약간의 깜박임이 생기게 된다. 물론 이러한 것도 해결방법이 다 있다. 이것의 가장 좋은 해결 방법은 CSS sprite를 이용하거나 pseudo selector의 content를 사용하는 방법이 있는데, CSS sprite는 이미지의 request 수를 줄일 수 있는 아주 좋은 최적화 방식이므로 나중에 최적화와 관련된 부분에 좀 더 다뤄볼 것이다. 하지만 웹의 타임라인을 살펴보거나 toc21.com 사이트의 로딩화면을 유심히 살펴보게 되면 이렇게 구현하는 방법의 단점을 또 발견할 수 있을 것이다. 만약 인터넷 속도가 느리다면 이러한 단점은 아주 쉽게 발견할 수 있다.



    



: 바로 순간적으로 css로 설정된 백그라운드 이미지는 다른 img로 로드되는 이미지들에 비해 우선순위가 떨어진다는 것이다. 따라서, 왼쪽의 캡쳐와 같이 다른 img로 설정한 이미지들이 먼저 로드되고나서야 뒤늦게 로드되는 것이다. 따라서, 이러한 CSS를 백그라운드로 사용하는 부분은 로드가 조금 느려도 되는 사이드바나 웹페이지의 아래부분에 있는 조금 늦게 떠도 되는 핵심적이지 않은 배너에 이렇게 쉬운 구현 방법을 사용하는 것이다. 그리고 toc21.com에서는 이러한 로드가 느리다는 체감을 줄여주기 위하여 url이 로드되기 전에 보여줄 기본 백그라운드색을 해당 배너의 배경색과 일치하게 설정하는, 검은색 배너는 기본으로 검은색 바탕색, 흰색 배너는 기본으로 흰색 바탕색을 사용함으로써 UX를 향상시키는 방법을 사용하고 있는 것을 볼 수 있다.



* <img> 태그와 inline 자바스크립트를 기반으로 구현

: 아마 가장 많은 사람들이 사용하는 방법일지도 모르는 방법이다. 바로 마우스오버가 되면 <img> 태그의 src를 수정하고, 다시 마우스아웃이 되면 원래의 src로 다시 수정하는 방법이다. 이것은 자바스크립트로 다양하게 구현이 가능한데, 가장 쉽게는 그냥 인라인으로 만들어버리는 방법이 있을 것이다.

<img id="leftBanner" src="https://t1.daumcdn.net/cfile/tistory/155E5D044B71F5D554" onmouseover="this.src='https://t1.daumcdn.net/cfile/tistory/156F9E0D4B876FBD50'" onmouseout="this.src='https://t1.daumcdn.net/cfile/tistory/155E5D044B71F5D554'"></img>

: 이것도 어떻게 보면 한줄이면 된다. 아주 간단하다. 이것을 구현하면 바로 마우스 오버 이미지 배너가 탄생한다.



게다가 <img> 태그를 이용했기 때문에 css의 백그라운드를 이용하는 것보다 로드가 우선적으로 된다는 점이 매력적이다. 하지만 css sprite를 이용한 최적화가 안되기 때문에 최적화에는 다소 어려움이 있다. 어찌되었든 하나의 배너가 2개의 request를 사용하게 된다는 점, 그리고 이 역시 mouseover에서 설정하는 src가 처음에 마우스 오버를 할 때에는 깜박임이 생겨버리게 되는 것이 불만이다. 그리고 해당 src의 이미지들이 사이즈가 다르게 되면 어찌되었든 별도의 css를 설정해줘야한다는 점이 있다. (위의 예가 사이즈가 다른 경우 나타나는 현상이다. CSS로 설정이 필요한 것이다.) 하지만 이 모든것 또한 다른 방법으로 해결이 가능하다. 이러한 방법들을 보기 전의 위의 inline 자바스크립트가 불만인 사람들을 위하여 별도의 자바스크립트로 구현해보도록 하자.



* <img> 태그와 자바스크립트를 기반으로 구현

: 어쩌면 위의 inline보다는 이렇게 구현하는 사람들이 더 많을지도 모른다. jquery를 사용해서 한다면 결국은 이 방법의 한가지 방식이 되는 것이다. 일단 기본 img 태그를 만들어두고 별도의 script 태그로 위의 onmouseover와 onmouseout을 뽑아내면 된다.

    <img id="centerBanner" src="https://t1.daumcdn.net/cfile/tistory/163A8B274C350DAF3C"></img>

: 그리고 해당 html의 맨 아래에다가 위의 태그 id를 호출하는 부분을 만들어주면 된다. 아래의 태그는 immediate function호출로 바로 실행하려면 body태그의 맨 아래 쯔음에 <script> 태그를 포함해서 추가하면 되고, onload이벤트에 호출하고자한다면 위치는 상관이 없으나, UX적인 향상을 위해서라면 모든 자바스크립트는 그대로 body 태그의 맨 아래에 놔두는 것이 좋다.

<script>
(function(d) {
    var img = d.getElementById("centerBanner");
    img.onmouseover = function () {
        this.src = "https://t1.daumcdn.net/cfile/tistory/113A8B274C350DAB3B";
    };
    img.onmouseout = function () {
        this.src = "https://t1.daumcdn.net/cfile/tistory/163A8B274C350DAF3C";
    };
}(document));
</script>


: 이는 위의 inline 자바스크립트로 구현한것과 큰 차이는 없으나, 최근 웹개발의 트렌드에 따라가고 있는 구현 방법이다. MVVM모델과 비슷한 개념을 구현하기 위해서 HTML에는 오로지 뷰로서의 역할만을 시키도록 하는 것이 최근 트렌드이므로 inline으로 하기보다는 이렇게 구현할 것을 추천한다. 위의 소스가 잘 이해가 되지 않으면 기본적인 자바스크립트 공부를 하거나 "속깊은 자바스크립트 강좌" 시리즈를 쭉 읽어보기를 추천한다. 이렇게 구현한 결과는 아래와 같다.



: 많은 사람들이 사용하고 있을 이 방법 역시도 inline 자바스크립트와는 똑같이 처음으로 마우스오버를 하게 되면 깜빡이는 현상이 나타난다. 이것은 이미지의 용량이 커지면 더 크게 체감하게 되는데, 이 현상을 없애줄 다른 방법을 살펴보자.



* <img> 태그 2개와 자바스크립트를 기반으로 구현

: img태그를 통해서 이미지가 로드되기 시작하는 것은 html이 파싱되어 의 src가 로드가 되는 시점부터 요청을 시작하기 마련이기 때문에 위의 방법들은 마우스오버가 되는 첫번째 시점에 다운로드가 되는 문제가 있다. 이러한 점이 바로 깜박임이 생겨버릴 수 있는 여지도 발생시키고, 인터넷이 느린 경우에는 그 시간이 점점 늘어나게 될 것이다. 이것을 해결하기 위해서는 <img> 태그를 2개 사용해서 미리 로드 시간 다음에 마우스 오버를 하는 경우 숨겨주는 방식이 유용하다. 이것을 구현하는 방법은 다양하지만, 아래의 방법이 일반적인 구현 방법이다.


: 바로 위와 같은 방식으로 2개의 이미지를 겹쳐놨다가 마우스오버가 되는 경우 앞의 <img>를 display:none 등으로 감추는 방식이다. 이것과 비슷한 방법으로는 아래와 같이 2개의 이미지의 앞뒤를 z-index를 수정함으로써 바꾸는 방법도 있다.


: 위의 방식을 응용하면 반투명한 오버랩 이미지도 쉽게 구현이 가능하므로 다양하게 응용이 가능할 것이다. 여기서는 첫번째 방법으로 구현하는 방법을 간단하게 해보자.

    <div id="bannerWrapper">
        <img id="frontImage" src="https://t1.daumcdn.net/cfile/tistory/2002CD414F4869192D"/>
        <img src="https://t1.daumcdn.net/cfile/tistory/203E5A424F471E3025"/>
    </div>

: 먼저 2개의 <img> 태그가 필요할 것이고, 해당 2개의 <img>태그를 겹치기 위해서 하나의 wrapper <div> 태그가 있으면 편리하다. 2개의 이미지를 겹치는 가장 간단한 방법은 wrapper <div> 태그의 css에 position: relative를 적용하고, 2개의 자식 <img>에는 position: absolute를 설정해주는 방법이다. position: absolute를 해주면 좋은 다른 이유는 바로 해당 설정을 한 태그들의 설정 값을 바꾼다고해서 DOM의 reflow가 일어나지 않기 때문에 성능상에도 다소 이점을 가져갈 수 있다는 점이다. 아래와 같이 css를 적용하면 쉽게 구현이 가능하다.

<style>
    #bannerWrapper {
        position: relative;     /* 하위 태그가 상대적인 위치를 가질 수 있도록 설정 */
    }
    #bannerWrapper img {
        position: absolute;   /* img 태그들이 겹쳐질 수 있게, 다른 태그에 영향을 주지 않게 설정 */
    }
    #bannerWrapper #frontImage {
        z-index: 1;    /* 앞에 나올 이미지를 설정 */
    }
    #bannerWrapper:hover #frontImage {
        display: none;  /* 마우스오버가 되면 앞에 나온 이미지를 숨김 */
    }
</style>

: 위의 #bannerWrapper:hover #frontImage 안의 display: none;를 z-index: -1로 수정하게 된다면 위의 2가지 css 적용 방법 중 2번째 방법이 된다. 하지만 z-index는 구버전 사파리에서 제대로 동작하지 않는 현상이 있으므로 그냥 display: none;을 하는 것이 다양한 브라우져의 호환을 고려할 때에는 속편할 것이다. 위의 구현 결과는 아래와 같다.



이러한 경우의 조심할 점이라면 position:relative으로 설정했으면, 해당 wrapper div의 width와 height css를 잘 설정해주지 않으면 그 아래에 오는 태그들이 겹치거나 마우스 오버의 범위가 틀어져버릴수도 있는 결과가 발생할 수 있으므로 조심해야한다. 여기서 또 더 개선을 시킬 수 있는 방법들은 아래의 img를 onload가 되고난 뒤에 추가하는 등 여러 방법들이 있는데, 이것보다 더 성능을 최적화하는 것은 당장은 고려할 필요는 없을 것이므로 일단 이정도로만 구현해도 마우스 오버에 대한 UX는 다소 향상 시킬 수 있다. 하지만 페이지 로드일 때 2개의 request가 생기는 것이 페이지 로드에 다소 영향을 줄 수 있다는 것이 불만일 수도 있다. 이 때에는 약간 새로운 방법으로 최적화도 가능하다.



* <div> 태그의 overflow:hidden과 <img> 태그 1개와 CSS 로 구현하기

: 아마 많은 웹개발자들은 이 방법에 대해서도 잘 모르고 있을 것인데, <img> 태그의 유용한 최적화 방법 중 하나로 웹성능최적화에 응용이 가능한 유용한 방법이다. CSS의 background로 이미지를 표시하는 경우에는 css sprite를 통해서 아주 쉽게 request를 줄일 수 있는 최적화가 가능하지만, background 이미지의 로딩이 페이지 뷰가 먼저 이루어지고나서 시작한다는 점에서 이미지 표시를 빠르게 해줘야하는 경우 이 방법이 css sprite를 활용하는 방법을 대신해서 사용할 수 있는 최적화 방법이다. 이것이 동작하는 방법은 아래와 같다.



: 위의 2개의 이미지를 겹치는 것과는 달리 2개의 이미지를 하나의 이미지로 이어 붙인 다음에 하나의 <img> 태그로 불러오고 wrapper div는 overflow: hidden를 설정해서 한번에 하나의 이미지만 보이게 하는 것이다. 그리고 마우스오버가 되면 이 <img> 태그의 위치를 위로 이동시켜서 아래쪽에 붙인 이미지를 표시하는 방식이다. 이것을 위해서는 일단 하나의 <div>태그와 하나의 <img>태그가 필요하다. 우선 아래와 같이 이미지를 하나로 이어서 붙였다. 위의 그림과 같은 구조로 가기 위해서 위아래로 붙였지만, 양옆으로 해도 무관하다.





: 그리고 이것을 나타내는 <img>태그 하나와 그 wrapper div태그 하나가 필요하다.

    <div id="verticalBannerWrapper">
        <img id="verticalBannerImg" src="https://t1.daumcdn.net/cfile/tistory/2347025052E59D691D"/>
    </div>

: <img>태그 는 위의 이미지 하나만을 로드하기 때문에 페이지의 request는 하나가 되는 것이다. 그렇다면 이제 해당 div와 img 태그에 스타일을 적용해주면 된다. css는 위의 2개의 이미지를 겹치는 것과 비슷하게 wrapper <div>태그에는 relative를 주고 <img> 태그는 absolute 태그를 주지만, wrapper <div> 태그는 overflow:hidden과 함께 배너의 크기를 지정해주고, 마우스 오버인 경우에 <img> 태그의 top의 값을 변경시키는 것이 중요하다.

<style>
    #verticalBannerWrapper {
        overflow: hidden;   /* div의 높이/넓이보다 커지는 경우 보여주지 않도록 설정*/
        height: 400px;      /* 보여줄 배너의 높이 */
        width: 265px;       /* 보여줄 배너의 넓이 */
        position: relative; /* 내부의 태그가 상대적으로 움직일 수 있도록 설정 */
    }
    #verticalBannerImg {
        position: absolute; /* 위치 변경이 다른 태그에 영향을 주지 않도록 설정 */
    }

    #verticalBannerWrapper:hover #verticalBannerImg {
        top: -400px;    /* 마우스 오버가 됐을 때 img 태그를 400px만큼 올리도록 설정 */
    }
</style>

: 각각의 css들은 위의 설명도에서 나타내고 있는 것 그대로 동작할 수 있도록 제공해주고 있으므로 모든 스타일이 중요하다. 이렇게 구현하게 되면 아래와 같이 된다.



: 이러한 구현 방법을 사용하게 되면 2개가 필요했던 request를 하나로 줄임으로써 성능적인 향상을 다소 이룰 수 있게 되고, 마우스오버의 이미지도 첫 이미지를 로드할 때 하나로 묶여서 같이 로드되므로 마우스오버로 인한 깜박임도 없다. 이러한 배너가 하나라면 큰 차이는 없을지 모르지만, 배너가 여러개일수록 성능향상의 폭은 커진다. 물론 구현하는 홈페이지의 성능은 언제나 최적화하면 좋지만 만약 위처럼 구현해놓았는데 배너의 이미지가 자주 바뀐다면 위의 하나의 <img>태그에 들어갈 이미지를 매번 새로 생성해야 하기 때문에, 위의 방법으로 구현한다면 이러한 이미지 생성 작업은 매번 다소 번거로울 수 있을 것이므로 이미지가 잘 바뀌지 않을 배너에 위의 방법을 사용하는 것이 좋을 것이고, 만약 이미지의 사이즈가 크다면 초기의 이미지를 다운 받아야하는 사이즈가 2배가 되므로 다른 방법을 사용하는 것도 방법이다.



* 구현결과

: 위의 각각의 구현결과를 아래의 파일에 정리해놨으니 각각의 구현 방법을 위의 소스와 아래의 파일에서 직접 뜯어보면서 공부해보면 각각의 동작원리를 쉽게 이해할 수 있을 것이다. 아래 파일은 반응형 웹때 사용하려고 미리 이미지들의 크기를 크게 해보았다.


03 css_mouseover_banner[unikys_tistory].html




* 정리

: 다양한 마우스 오버 이미지 배너의 구현 방법들을 살펴봤는데, 각 이미지 배너의 구현 방법은 해당 배너의 중요도나 표시 우선순위 등에 따라서 다르게 구현하면 될 것이다.

    • 중요하지 않은 aside 메뉴나 구석 메뉴의 마우스오버 이미지를 적용하면 - CSS background로 구현하는 것이 유리
    • 배너를 조금 늦게 표시해주거나 첫 페이지뷰의 밖인 아래쪽에 있다면 - CSS background로 구현하는 것이 유리
    • 반응형으로 브라우져 크기나 모바일에 따라 이미지를 다르게 하고 싶다면 - CSS background로 구현하는 것이 유리
    • 빠르게 표시해줘야한다면 - <img> 태그로 구현하는 것이 유리
    • 사용자가 마우스오버를 적게하거나 할 확률이 적다면 - <img> 태그와 자바스크립트로 구현하는 것이 유리
    • 사용자가 마우스오버를 반드시 하거나 페이지 로드 이후 빠르게 마우스 오버를 한다면 - <img> 태그 2개 또는 1개와 css로 구현하는 것이 유리
    • 이미지가 자주 바뀌지 않는 배너라면 - <div>와 <img> 태그 1개로 구현하는 것이 유리
    • 이미지의 사이즈가 크다면 - <img> 태그 2개로 하되 2번째 태그는 onload 끝나고 로드하도록 구현하는 것이 유리


* 다음에는 위의 배너들을 나란히 놓는 것, 또는 배치해보는 것을 할 것이다. 사실 상단의 메뉴를 만들었을 때에 이미 맛보기는 했지만, 이번에는 목표 홈페이지와는 달리 조금 다르게 반응형처럼 동작하도록 살짝 응용해볼 것이다. 반응형웹이라고 하면 엄청 어려운듯 하지만 사실 개발하고 구현하는데에 어려운 것은 별로 없고 가장 중요한 것은 언제나 '기획/설계'이다. 위의 정리 항목 중 3번째에 반응형/모바일을 고려하는 배너인 경우 CSS background로 하면 유리하다는 것 또한 다음글을 보면 이해될 것이다.



- 다음글

2016/06/17 - [밑바닥부터 홈페이지 만들기] HTML과 CSS로 가로 드롭다운 메뉴 만들기

2016/07/?? - 간단한 반응형웹과 모바일용 웹 구현하기



공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함