본문으로 바로가기

폼 필드들 중에 가장 디자인하기 까다로운 것이 select 박스입니다. 이에 대한 현실을 파악하고 대체방안들을 모색해 봅니다.

Select 디자인의 현황

네이티브 select 박스의 디자인상의 한계로 인해 많은 플러그인들에서 select 박스의 구조를 div 와 ul 요소등으로 치환하여 사용한다. 물론 근래의 대부분의 플러그인이 그렇듯이 구버전의 IE에 대한 지원이 부족하다.

그나마 오래전에 개발된 jQuery Selectbox plugin 정도가 구형 IE를 지원한다. 이 플러그인의 CSS를 수정하여 원하는 디자인을 구축하는게 손쉬운 방법일 터이다.

다만, 이와 같이 select 박스를 div와 ul 요소로 치환하는 방법들은 모바일상에서 각각의 기기들이 네이티브로 지원하는 효과를 받을 수 없게된다. 작은 모바일기기에서 많은 옵션을 포함하고 있는 select 박스를 만나게 된다면 대단히 유쾌하지 못한 사용자경험을 체험하게 될 것이다.

네이티브 select 동작

아래에서 플러그인의 사용없이 CSS와 간단한 자바스크립트를 이용한 디자인에 대해 알아본다.

Select CSS를 직접 수정

국내 사정상 차후의 이야기가 될테지만, 모던 브라우저들에서는 select 박스의 외형 변경이 어느 정도 가능하다. 가장 먼저 해야될 것은 브라우저마다 네이티브로 지원하는 제각기 모양이 다른 화살표 모양을 제거하고 이를 하나로 통일하는 것이다.

select 박스의 기본구조는 아래와 같다.

<select>
  <option selected>셀렉트박스</option>
  <option>옵션1</option>
  <option>옵션2</option>
  <option>옵션3</option>
</select>

화살표 모양을 제거하고 새로운 화살표를 추가하는 스타일은 아래와 같다.

select {
  -webkit-appearance: none;  /* 네이티브 외형 감추기 */
  -moz-appearance: none;
  appearance: none;
  background: url(이미지 경로) no-repeat 95% 50%;  /* 화살표 모양의 이미지 */ 
}

/* IE 10, 11의 네이티브 화살표 숨기기 */
select::-ms-expand { 
  display: none;
}

이후 select 박스의 디자인을 취향에 맞게 변경한다. 물론 select 박스 형태만 변경 가능하고, option 쪽의 변경은 불가능하다. 옵션쪽 까지 변경을 원한다면 select 박스 관련 플러그인을 사용할 것을 권한다.

select {
  width: 200px; /* 원하는 너비설정 */
  padding: .8em .5em; /* 여백으로 높이 설정 */
  font-family: inherit;  /* 폰트 상속 */
  background: url(https://farm1.staticflickr.com/379/19928272501_4ef877c265_t.jpg) no-repeat 95% 50%; /* 네이티브 화살표 대체 */  
  border: 1px solid #999; 
  border-radius: 0px; /* iOS 둥근모서리 제거 */
  -webkit-appearance: none; /* 네이티브 외형 감추기 */
  -moz-appearance: none;
  appearance: none;
}

See the Pen Selectbox Design by Douglas Ham (@uzugoer) on CodePen.

label을 이용한 디자인 변경

폼 필드(input type="text") 디자인 #1에서 사용한 방법으로 label 요소와 select 박스를 감싸는 부모요소를 이용한 디자인 방법이다.

기본 구조는 아래와 같으며, select 요소를 감싸는 부모 요소와 label 요소가 추가된 것을 확인할 수 있다.

<div class="selectbox">
    <label for="ex_select">국적선택</label>
    <select id="ex_select">
        <option selected>국적선택</option>
        <option>한국</option>
        <option>일본</option>
        <option>중국</option>
    </select>
</div>
  • select 요소의 ID 값과 label 요소의 for 속성을 같은 값으로 지정한다(상호작용을 위해).
  • option 요소중에 selected 속성을 가진 텍스트와 label 요소의 텍스트를 일치시킨다.

CSS는 아래와 같다.

.selectbox {
  position: relative;
  width: 200px;  /* 너비설정 */
  border: 1px solid #999;  /* 테두리 설정 */
  z-index: 1;
}

.selectbox:before {  /* 화살표 대체 */
  content: "";
  position: absolute;
  top: 50%;
  right: 15px;
  width: 0;
  height: 0;
  margin-top: -1px;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 5px solid #333;
}

.selectbox label {
  position: absolute;
  top: 1px;  /* 위치정렬 */ 
  left: 5px;  /* 위치정렬 */
  padding: .8em .5em;  /* select의 여백 크기 만큼 */
  color: #999;  
  z-index: -1;  /* IE8에서 label이 위치한 곳이 클릭되지 않는 것 해결 */
}

.selectbox select {
  width: 100%; 
  height: auto;  /* 높이 초기화 */
  line-height: normal;  /* line-height 초기화 */
  font-family: inherit;  /* 폰트 상속 */
  padding: .8em .5em;  /* 여백과 높이 결정 */
  border: 0;
  opacity: 0;  /* 숨기기 */
  filter:alpha(opacity=0);  /* IE8 숨기기 */
  -webkit-appearance: none; /* 네이티브 외형 감추기 */
  -moz-appearance: none;
  appearance: none;
}
  • .selectbox가 실제로 외형을 담당하는 부분이다. 이 부분을 디자인해서 원하는 모양으로 디자인하자.
  • .selectbox:before 부분은 화살표를 대체하고 있지만 원하는 배경을 .selectbox에 설정하고 이를 삭제해도 무방하다.

옵션 선택시 label에 반영하기

select 박스에서 무엇인가 선택했을때, 해당 옵션이 가진 텍스트를 label에 반영하여 실제 select 요소가 작동하는 방식과 같은 기능을 구현한다.

$(document).ready(function() {
  var selectTarget = $('.selectbox select');

   selectTarget.change(function(){
     var select_name = $(this).children('option:selected').text();
     $(this).siblings('label').text(select_name);
   });
});

 

See the Pen Select Design by Douglas Ham (@uzugoer) on CodePen.

IE7까지 크로스브라우징

IE7에서는 select 요소에 padding이 적용되지 않기때문에 위의 코드는 IE8까지 적용된다. IE7까지 지원하려면 paddding을 select 요소가 아닌 .selectbox에 적용하는 방식으로 전환하길 바란다. 다만 이때는 select 요소의 크기가 변경되지 않아 클릭할 수 있는 지역이 보이는 박스 전체의 크기보다 작아진다.

또 다른 방법으론, 애초에 padding을 이용하지 말고, .selectbox, label, select에 같은 크기의 heightline-height 값을 지정하는 것이다.

IE7에서는 :before(가상요소) 를 지원하지 않기때문에 배경이미지를 이용해서 화살표를 표시해야 한다.

.selectbox {
  position: relative;
  width: 200px;
  height: 40px;
  line-height: 40px;
  background: url(https://farm1.staticflickr.com/379/19928272501_4ef877c265_t.jpg) no-repeat 95% 50%;
  border: 1px solid #999;
  z-index: 1;
}

.selectbox label {
  position: absolute;
  top: 0px;
  left: 5px;
  height: 40px;
  line-height: 40px;
  color: #999;
  z-index: -1;
}

.selectbox select {
  width: 100%;
  height: 40px;
  line-height: 40px;
  font-family: inherit;
  border: 0;
  opacity: 0;
  filter:alpha(opacity=0);
  -webkit-appearance: none; /* 네이티브 외형 감추기 */
  -moz-appearance: none;
  appearance: none;
}

보유중인 갤럭시3의 안드로이드 4.4(킷캣)버전의 스톡 브라우저(내장 브라우저)에서 문제가 발견되었다. 부모 요소 및 자신(select 요소 )에 position과 관련된 CSS가 적용되었을때, 포커스가 발생하면 화면이 최상단으로 이동하는 현상이 나타난다.

안드로이드에서 스톡브라우저가 지닌 문제점들은 마치 IE의 구형 브라우저들을 보는듯 하다. 버그가 무궁무진하다. 주변에 스톡 브라우저를 사용하는 사람들을 보면 모바일 크롬브라우저를 사용하기를 권하도록 하자.