본문으로 바로가기

체크박스와 라디오버튼의 정렬과 디자인은 예전부터 골치를 아프게 하는 작업이였습니다. 관련하여 현재 애용되는 디자인 방법과 브라우저 호환성을 확보하는 방법에 대하여 알아봅니다.

체크박스와 라디오버튼 디자인 현황

모던 브라우저들과 IE11은 체크박스와 라디오버튼의 크기정도는 조정할 수 있다. 모바일 브라우저에서는 기본으로 제공되는 체크박스와 라디오버튼의 선택영역이 매우 작게 표시되어 선택의 불편함이 가중되기에 이 크기를 변경하는 것이 추천된다.

webkit 브라우저들에서는 -webkit-appearance: none 과 같이 네이티브 속성값을 제거하여 좀 더 다른 디자인을 구현할 수 있지만, 브라우저 호환이 되지 않는 단점이 있다.

이를 극복하기 위해 checked 속성을 이용하여 체크박스와 라디오를 꾸미는 방법이 활성화되고 있으며, IE8 이하의 브라우저들을 지원하기위해서 폴리필을 추가해야 한다.

checked 속성 폴리필 추가

구형 IE에서 checked 속성을 지원하기 위해 poly-checked를 추가한다. 이 폴리필은 jQuery를 필요로 하며, 모든 CSS파일은 이 스크립트 이전에 포함되어야 한다(IE7까지 지원).

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<!--[if lte IE 8]>
<script src="path/to/poly-checked.min.js"></script>
<![endif]-->
이 밖에도 다른 폴리필도 존재했으나 직접적으로 테스트해보진 않았다.

체크박스 디자인

기본적인 체크박스 디자인의 구조는 아래와 같다.

<div class="checks">
  <input type="checkbox" id="ex_chk">
  <label for="ex_chk">체크박스</label>
</div>

input 요소의 ID값과 label 요소의 for 속성값을 일치시키면 된다.

기본적인 CSS는 아래와 같다.

.checks {position: relative;}

.checks input[type="checkbox"] {  /* 실제 체크박스는 화면에서 숨김 */
  position: absolute;
   width: 1px;
   height: 1px;
   padding: 0;
   margin: -1px;
   overflow: hidden;
   clip:rect(0,0,0,0);
   border: 0
}
.checks input[type="checkbox"] + label {
  display: inline-block;
  position: relative;
  cursor: pointer;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}
.checks input[type="checkbox"] + label:before {  /* 가짜 체크박스 */
  content: ' ';
  display: inline-block;
  width: 21px;  /* 체크박스의 너비를 지정 */
  height: 21px;  /* 체크박스의 높이를 지정 */
  line-height: 21px; /* 세로정렬을 위해 높이값과 일치 */
  margin: -2px 8px 0 0;
  text-align: center; 
  vertical-align: middle;
  background: #fafafa;
  border: 1px solid #cacece;
  border-radius : 3px;
  box-shadow: 0px 1px 2px rgba(0,0,0,0.05), inset 0px -15px 10px -12px rgba(0,0,0,0.05);
}
.checks input[type="checkbox"] + label:active:before,
.checks input[type="checkbox"]:checked + label:active:before {
  box-shadow: 0 1px 2px rgba(0,0,0,0.05), inset 0px 1px 3px rgba(0,0,0,0.1);
}

.checks input[type="checkbox"]:checked + label:before {  /* 체크박스를 체크했을때 */ 
  content: '\2714';  /* 체크표시 유니코드 사용 */
  color: #99a1a7;
  text-shadow: 1px 1px #fff;
  background: #e9ecee;
  border-color: #adb8c0;
  box-shadow: 0px 1px 2px rgba(0,0,0,0.05), inset 0px -15px 10px -12px rgba(0,0,0,0.05), inset 15px 10px -12px rgba(255,255,255,0.1);
}
  • .checks input[type="checkbox"] 에서 checkbox를 숨기고 있는데, IE8에서는 체크박스를 display: none 하거나 visibility: hidden으로 숨기면 :checked 기능 자체가 작동하지 않는다. 이는 아마도 추가한 폴리필의 한계로 추측된다.
  • 체크박스의 모양을 결정하는 .checks input[type="checkbox"] + label:before 부분과 체크박스의 체크상태를 표시하는 .checks input[type="checkbox"]:checked + label:before 부분은 배경이미지를 사용해서 표현해도 된다.

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

글자와 체크박스의 정렬

위에서 소개한 CSS에서는 글자와 체크박스의 정렬을 .checks input[type="checkbox"] + label:before 부분의 vertical-align 속성과 margin 속성을 이용해 정렬했다. 이것은 거의 모든 브라우저에서 이상없이 작동되나, 모바일 크롬 브라우저에서는 정렬되지 못하고 체크박스의 최상단에 글자가 달라붙는 경우가 생길수 있다.

원인은 파악하지 못하였으며, 모바일 크롬브라우저의 버그로 추측하고 있다.

물론, 글자와 체크박스 사이의 정렬을 vertical-align 속성과 margin 에 의존하지 말고 position: absolute를 이용하여 크로스 브라우징이 가능하다. 다만, 이 경우 글자크기와 체크박스의 크기가 변경될때 마다 다시 위치값을 정렬해야 하는 수고를 해야 된다.

수정된 코드는 아래와 같다.

.checks {position: relative;}

.checks input[type="checkbox"] {  /* 실제 체크박스는 화면에서 숨김 */
  position: absolute;
   width: 1px;
   height: 1px;
   padding: 0;
   margin: -1px;
   overflow: hidden;
   clip:rect(0,0,0,0);
   border: 0
}
.checks input[type="checkbox"] + label {
  display: inline-block;
  position: relative;
  padding-left: 30px;  /* 글자와 체크박스 사이의 간격을 변경 */
  cursor: pointer;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}
.checks input[type="checkbox"] + label:before {  /* 가짜 체크박스 */
  content: '';
  position: absolute;
  left: 0;
  top: -4px;  /* 이 값을 변경해서 글자와의 정렬 */
  width: 21px;  /* 체크박스의 너비를 지정 */
  height: 21px;  /* 체크박스의 높이를 지정 */
  line-height: 21px; /* 세로정렬을 위해 높이값과 일치 */
  text-align: center;  
  background: #fafafa;
  border: 1px solid #cacece;
  border-radius : 3px;
  box-shadow: 0px 1px 2px rgba(0,0,0,0.05), inset 0px -15px 10px -12px rgba(0,0,0,0.05);
}
.checks input[type="checkbox"] + label:active:before,
.checks input[type="checkbox"]:checked + label:active:before {
  box-shadow: 0 1px 2px rgba(0,0,0,0.05), inset 0px 1px 3px rgba(0,0,0,0.1);
}

.checks input[type="checkbox"]:checked + label:before {  /* 체크박스를 체크했을때 */ 
  content: '\2714';  /* 체크표시 유니코드 사용 */
  color: #99a1a7;
  text-shadow: 1px 1px #fff;
  background: #e9ecee;
  border-color: #adb8c0;
  box-shadow: 0px 1px 2px rgba(0,0,0,0.05), inset 0px -15px 10px -12px rgba(0,0,0,0.05), inset 15px 10px -12px rgba(255,255,255,0.1);
}

라디오버튼 디자인

기본적으로 체크박스 디자인과 유사하며, 대부분의 코드가 중복 사용된다. 기본 구조는 아래와 같다.

<div class="checks">
  <input type="radio" id="ex_rd2"> 
  <label for="ex_rd2">체크박스</label> 
</div>

CSS도 체크박스와 마찬가지인데, 이도 모바일 크롬 브라우저를 고려해서 글자와 라디오버튼의 정렬을 position: absolute를 이용했다.

.checks {position: relative;}
.checks input[type="radio"] {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip:rect(0,0,0,0);
  border: 0;
}
.checks input[type="radio"] + label {
  display: inline-block;
  position: relative;
  padding-left: 30px;
  cursor: pointer;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}
.checks input[type="radio"] + label:before {
  content: '';
  position: absolute;
  left: 0;
  top: -4px;
  width: 21px;
  height: 21px;
  text-align: center;
  background: #fafafa;
  border: 1px solid #cacece;
  border-radius: 100%;
  box-shadow: 0px 1px 2px rgba(0,0,0,0.05), inset 0px -15px 10px -12px rgba(0,0,0,0.05);
}
.checks input[type="radio"] + label:active:before,
.checks input[type="radio"]:checked + label:active:before  {
  box-shadow: 0 1px 2px rgba(0,0,0,0.05), inset 0px 1px 3px rgba(0,0,0,0.1);
}
.checks input[type="radio"]:checked + label:before {
  background: #E9ECEE;
  border-color: #adb8c0;
}
.checks input[type="radio"]:checked + label:after {
  content: '';
  position: absolute;
  top: 1px;
  left: 5px;
  width: 13px;
  height: 13px;
  background: #99a1a7;
  border-radius: 100%;
  box-shadow: inset 0px 0px 10px rgba(0,0,0,0.3);
}

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

이 예제들을 이용해서 다양한 체크박스와 라디오버튼을 만들수 있기를 바랜다.