이 게시물은 2016년 8월 8일 수정판입니다.
CSS3가 보편화 되면서 이미지에 의존해야 했던 예전과 달리, 예쁜 버튼들을 스타일시트에서 쉽게 표현할 수 있게 되었습니다. 물론 아직도 웹 브라우저 호환성 때문에 의도하는 그대로의 모습은 아닐지라도, 다양한 형태와 색상의 버튼을 라이브러리화 할 수 있는 것은 여러모로 편리한 부분입니다. 직접 라이브러리를 만들지 않고도 Bootstrap과 같은 편리한 프레임워크를 사용할 수도 있지만, 원리를 알고 사용하는 것과 모르고 사용하는 것은 큰 차이가 있겠습니다.
이 글에서는 직접 버튼을 라이브러리화 하고, 몇 개의 클래스 조합으로 다양한 버튼을 사용할 수 있는 방법에 대해 알아보려고 합니다.
버튼을 뼈와 살로 나눠 원할 때 마다 환골탈태 시키는 조합서입니다. 여러 웹 사이트를 만들다 보면, 디자인에 따라 색상과 모양이 다른 버튼을 반복적으로 만들게 되는데, 이게 굉장한 노가다입니다. 한번 라이브러리화 해 놓으면 여러 색상 테마를 가진 사이트에 공용으로 사용할 수 있으니, 자기만의 버튼 라이브러리를 가지고 있는 것은 매우 바람직합니다.
<input type="submit" class="ct-btn white" value="input" /> <button type="submit" class="ct-btn blue">button</button> <a href="#" class="ct-btn green">a:link</a> <span class="ct-btn yellow">span</span> <div class="ct-btn red">div</div>
버튼의 기본 골격을 갖춰 놓고, 실제로 채색하는 부분은 별도의 클래스로 나눠 HTML 코드 안에서 조합시키는 모듈 방식입니다. 위 예제에서 기본 골격은 .ct-btn
이고, 채색은 .white
, .blue
와 같은 클래스가 맡게 됩니다.
10년 전만 해도 깨알같은 글씨에 칼 같이 맞춰진 테이블 코딩이 유행이었는데, 사용자의 모니터가 점점 커지고 웹 표준이니 뭐니 여러 트랜드가 합쳐지면서 지금은 사이트의 디자인 자체가 공간을 넓게 사용하고 픽셀 하나 하나의 중요성은 점차 떨어지고 있습니다. 그러다보니 사용하는 버튼의 크기도 매우 다양해졌습니다.
그래서 버튼의 기본 골격은 다음과 같이 잡아보도록 합시다.
px
로 정의하지 않고, 부모 요소의 글자 크기나 혹은 버튼의 글자 크기에 의해 유동적으로 변경되게끔 한다.inline-block
을 사용하여 text-align
속성에 따라 정렬할 수 있다.form
요소인 <button>
, <input>
에도 모두 적용되야 한다.Selector
표기를 최적화 함에 따른 웹 브라우저 퍼포먼스 향상 문제는 여기에서 무시합니다. 체감적으로 느껴지지도 않을 뿐더러, 아무리 좋은 코딩 방법이라 하더라도 코드를 작성하는 여러분이 스트레스를 받지 않는 것이 항상 최우선입니다.
이 사이트에서 사용하는 워드프레스 편집기의 기술적인 제약 상, 모든 예제를 CSS 코드로 재현할 수는 없습니다. 이미지가 사용되더라도 예제 코드는 모두 실제로 사용이 가능합니다.
IE6-7에 대한 호환성은 다루지 않습니다. 이들은 고질적인 outline
버그와 float
버그가 있습니다. 이들을 모두 잡으려면 여러분의 코드는 핵(Hack) 투성이가 됩니다. 이 글에서 다루는 호환성의 범위는 IE8 이상, FireFox, Chrome, Safari, Opera 그리고 Mac OS용 FireFox, Chrome, Safari, Opera입니다.
기본 골격을 잡기 위한 첫 단추로, 버튼이 여러 웹 브라우저에서 일률적인 모습과 정렬을 갖도록 하는 호환성입니다. 이 부분은 무척 중요한데, 특히 버튼이<input type="text" />
와 같은 텍스트 입력상자와 함께 사용될 때의 정렬까지 생각을 해야합니다 (예를들면, 검색 상자). 이런데서 1px이라도 삐끗하면 매우 빈티나 보이지요.
<input name="search" type="text" class="ct-input white" value="Type here.." /> <button type="submit" class="ct-btn white">Search</button>
이런 호환성을 유지시키는 가장 중요한 조건은, 절대 html
이나 body
태그에 line-height
속성을 부여해서는 안됩니다. 아예 속성을 정의하지 않던가, 혹은 line-height: normal
을 사용해서 웹 브라우저 기본 값을 사용해야 합니다. 사람들이 많이 사용하는 CSS 리셋 코드중에는 이렇게 line-height: 1.4
혹은 line-height: 100%
와 같이 인위적인 줄 높이를 정의해 놓은 경우가 많기 때문에, 반드시 자기가 사용하는 외부 CSS를 확인해야 합니다.
line-height
문제는 평소에는 없어보이다가, form
요소인 <button>
이나 <input>
으로 만든 버튼에서 발생합니다.
한번 html
이나 body
에 줄 높이를 설정해 버리면, 아무리 자식 태그에서 line-height: normal
을 사용해도 무의미하므로 애초부터 조심해야 합니다.
버튼에서 사용 할 클래스 이름을 지을 때, .btn
은 button의 의미를 가장 함축적으로 표현할 수 있는 이상적인 이름입니다. 하지만, 이 이름은 너무 많은 곳에서 사용하고 있어서 충돌 위험이 굉장히 큽니다. 이 이름을 사용하려면 최소한 다음의 조건을 지키세요.
.btn
클래스를 사용하고 있지는 않은지 확인한다..btn
클래스를 사용하고 있지는 않은지 확인한다..btn
클래스가 사용되고 있지는 않은지 확인한다..btn
명을 모두 다른 것으로 바꾼다.결과적으로, 여러분이나 혹은 여러분이 만든 라이브러리를 사용할 다른 사람을 위해서라도 다른 이름을 짓는 것이 좋겠습니다. 이 글에서는 ct-btn
을 버튼의 클래스 이름으로 사용합니다.
이런 보편적인 클래스 이름은 사실 라이브러리 제작자가 알아서 사용을 피하는 것이 바람직합니다. 가장 편하게 쓸 수 있는 이름은 사이트를 만드는 당사자가 사용할 수 있게끔 배려하는 것이 에티켓이겠죠. 이제 사용자가 많아진 Bootstrap과 같은 메이져급 라이브러리들은 이런 부분도 고려를 좀 했으면 하는 바램입니다.
위에서 버튼을 뼈와 살로 분리한다고 하였습니다. 여기서는 뼈에 해당하는 버튼의 골격을 정의합니다. 색상과 같은 디자인적인 부분은 제외합니다.
button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } .ct-btn { display: inline-block; margin: 5px 0; padding: .5em .75em; border-radius: .25em; box-sizing: content-box; -moz-box-sizing: content-box; background: transparent; outline: 0; vertical-align: middle; font-family: inherit; font-size: 18px; text-decoration: none; white-space: nowrap; cursor: pointer }
1 부터 5번 줄 까지의 구문은, Firefox에서 <button>
과 <input>
태그의 내부 여백을 없애줍니다. 호환성과 관련된 부분이니 꼭 정의해 줍니다.
각 속성을 잠시 살펴보면 다음과 같습니다.
display: inline-block | 버튼 간의 간격을 주고, text-align 속성으로 정렬하며, 부모 요소의 가장자리에 붙어도 여백을 남기지 않게 함. |
---|---|
margin: 5px 0 | 부모 요소가 좁아져서 버튼의 단이 떨어져도 버튼끼리 완전히 붙지 않도록 최소한의 간격을 생성. |
padding: .5em .75em | 버튼의 크기가 커져도 버튼과 글자간의 여백을 자동으로 유지시킴. |
border-radius: .25em | 버튼의 크기에 따라 자동으로 곡선의 정도를 처리. |
box-sizing: content-box | form 요소인 <button> 과 <input> 의 기본 테두리 형태를 content-box로 변경. |
-moz-box-sizing: content-box | 위와 같은 내용으로, Firefox 호환성을 위한 Vendor Prefix. 크롬이나 사파리를 위한 -webkit-은 필요 없음. |
background: transparent | form 요소인 <button> 과 <input> 의 기본 배경색을 없앰. |
outline: 0 | 클릭 시 발생하는 점선 삭제. |
vertical-align: middle | 버튼이 글자나 다른 요소와 정렬할 때 수직상의 중간에 위치하도록 조정. |
font-family: inherit | 버튼의 서체가 부모 요소로부터 상속 받음. 기본 서체 이름을 정해줘도 상관 없음. |
font-size: 18px | 기본 폰트 크기 지정. padding 에 em 단위가 사용되었기 때문에 폰트 크기는 반드시 px 로 정의해야 함. |
text-decoration: none | 버튼의 글자에 밑줄이 생기지 않도록 처리. |
white-space: nowrap | 버튼 크기가 작아져도 글자가 줄 바꿈하지 않도록 처리. |
cursor: pointer | <a> 태그 같은 링크 요소 이외에도 커서가 바뀌도록 처리. |
여기서 관심있게 보아야 할 부분은 em
단위가 사용된 padding
입니다. 버튼의 여백을 px
로 고정하게 되면, 버튼의 글씨가 커지더라도 여백은 함께 늘어나지 않습니다. 하지만 em
을 사용하면 폰트 크기에 따라 여백도 함께 늘어납니다. border-radius
도 마찬가지입니다. 여기에 사용 된 em
역시 폰트 크기의 영향을 받아, 일일이 값을 지정해 주지 않아도 자연스러운 모서리 처리를 해줍니다.
em
은, 부모나 자기가 가진 속성의 값에 따라 비율로 처리하는 단위입니다. 그래서 잘못 사용하면 얘기치 못한 결과를 낳을 수 있지만, 개념을 잘 이해하고 안전한 상황에서 사용하면 매우 편리한 단위입니다. 여기에 사용된 padding
은 font-size
의 값에 따라 유기적으로 변화하기 때문에, font-size
만큼은 부모에게 휘둘리지 않을 절대값, 즉 px
로 정의되어야 합니다. 아직 em
과 px
의 개념이 난해하다면 일단 넘어갑니다.
또 한가지는, form
요소인 <button>
과 <input>
은 다른 요소들과 다르게 단독으로 box-sizing: border-box
성질을 가지고 있습니다. <a>
, <div>
태그들은 border
의 두께를 너비와 높이에 포함시키지만, <button>
과 <input>
태그는 포함시키지 않기 때문에 크기가 달라집니다.
따라서 버튼의 box-sizing
성질을 content-box
혹은 border-box
둘 중 하나로 통일을 시켜주어야 합니다. 이 글에서 IE6-7의 호환을 염두에 두지는 않지만 기왕 하나로 통일할 것이라면 최소한 근사값으로 보여질 수 있도록 content-box
로 통일하였습니다. 이 문제는 평소에 나타나지 않다가, 버튼의 크기를 px
로 고정할 때 나타납니다.
이제 채색 단계입니다. 버튼의 골격이 갖춰지긴 했지만, 스타일링이 안되어 있기 때문에 .ct-btn
클래스 하나만으로는 버튼의 역할을 할 수가 없습니다. 이제부터 기본적인 화이트 색상의 스타일을 만들어 보겠습니다. 기존에 작성한 .ct-btn
클래스 아래에 별도로 다음의 코드를 작성합니다.
.ct-btn.white { color: #666; border: 1px solid #ebebeb; border-bottom-color: #c6c6c6; box-shadow: 0 2px 2px rgba(0, 0, 0, 0.04); background: #fff; background: linear-gradient(to bottom, #ffffff 40%, #f6f6f6 100%); filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#f6f6f6', GradientType=0 );/*IE*/ }
스타일을 가지고 있는 클래스가 .white
입니다. background: #fff
는 CSS3를 지원하지 않는 브라우저의 기본 버튼 배경색입니다. 7번 줄은 W3C의 공식 규칙으로 선언된 배경 명암입니다. 8번 줄은 배경 명암을 사용하지 못하는 IE 브라우저들을 위한 Vendor-specific Property입니다.
이 예문에서도 그렇지만 이제 background
에 대해서는 -webkit-
와 같은 제조사 제공용 Vendor-Prefix는 사용하지 않아도 무방합니다. background
속성은 표준화에 대한 우선순위가 높아 지금은 각 제조사의 웹 브라우저들이 Prefix를 떼고 W3C의 선언을 제대로 구현하고 있습니다. 여러분이 2014년 현재 시점에서 지저분한 Vendor-Prefix에서 해방시킬 수 있는 속성들은 background
, box-shadow
, border-radius
입니다. 의문이 있는 사람은 직접 각 웹 브라우저를 다운로드 받아 직접 테스트 해보기 바랍니다.
Button
이제 HTML 태그에서 .ct-btn
과 .ct-white
를 조합하여 완성된 모양의 버튼을 표현할 수 있습니다. 버튼은 :link
, :visited
와 더불어 마우스가 올라간 상태의 :hover
, 그리고 버튼이 클릭되어 눌렸거나 선택되어진 상태의 :active
가 있습니다. 각 상황별로 버튼의 스타일을 조금씩 다르게 해준다면 좀 더 인터렉티브한 표현이 가능하겠죠. 그래서 다음과 같이 스타일을 수정해 줍니다.
/* 일반적인 버튼의 상황 */ .ct-btn.white, .ct-btn.white:link, .ct-btn.white:visited { color: #666; border: 1px solid #ebebeb; border-bottom-color: #c6c6c6; box-shadow: 0 2px 2px rgba(0, 0, 0, 0.04); background: #fff; background: linear-gradient(to bottom, #ffffff 40%, #f6f6f6 100%); filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#f6f6f6', GradientType=0 );/*IE*/ } /* 마우스오버 */ .ct-btn.white:focus, .ct-btn.white:hover { background: #f4f4f4; background: linear-gradient(to bottom, #fafafa 0%, #fff 100%); filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fafafa', endColorstr='#ffffff', GradientType=0 );/*IE*/ } /* 눌려졌거나 선택 된 상황 */ .ct-btn.white:active, .ct-btn.white.active { text-shadow: 0 1px 0px #fff; border-color: #ebebeb; border-top-color: #ddd; background: #f4f4f4; box-shadow: none }
24번 줄의 .active
는, 메뉴나 네비게이션 버튼을 만들 때 현재 보고 있는 메뉴가 활성 상태임을 알리는 클래스입니다. 예를들어, 게시판 따위의 가장 밑에 위치한 페이지 번호에서 현재 보고 있는 페이지의 번호가 강조되어 있는 것이 그것입니다. 지정해 놓으면 편리합니다.
<button type="submit" class="ct-btn white" style="font-size: 38px">Extream Size</button>
style="font-size: 38px"
과 같이 폰트 크기 속성을 함께 사용하면 어떤 크기라도 표현할 수 있습니다. 만일 인라인 스타일을 싫어하는 사람이라면 별도의 서체와 크기를 가진 클래스를 정의해 놓고 사용할 수도 있죠.
/* CSS */ .en-01 { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 18px; font-weight: bold; } <!-- HTML --> <button type="submit" class="ct-btn white en-01">Custom fonts and size</button>
어떤 경우에는 버튼 크기를 px
로 완전히 고정시키고 싶어하는 사람도 있을겁니다. 사이트 디자인이 단 1px의 오차도 허용하지 않을 만큼 아주 빡빡하다면 더욱 그렇겠지요. 아래 예문은 .large
라는 클래스를 px
로 고정하고 있습니다.
/* CSS */ .ct-btn.large { height: 46px; padding: 0 1em; font-size: 18px; font-weight: 600; line-height: 46px; } <!-- HTML --> <button type="submit" class="ct-btn white large">Fixed Size Button</button>
버튼 크기를 px
로 고정시킬 때는 웹 브라우저 호환성을 위해 다음의 규칙을 지켜서 작성하는 것이 좋습니다.
padding
은 위와 아래를 제외한 양 옆만 적용한다.이제 코드의 양이 상당히 많아져서, 지금까지 알아 본 버튼 라이브러리를 데모 페이지로 준비하였습니다. 이 데모 페이지를 통해 직접 HTML과 CSS 코드를 확인하고 복사하여 사용할 수 있습니다. 더 멋진 테마를 추가해서 여러분의 작업이 쉽고 즐거워졌으면 하는 바램입니다.
버튼 라이브러리 만들기 데모 페이지
많이 배워 갑니다. 감사합니다!
많은 도움이 되었습니다 감사합니다.
정말 도움 많이 받았습니다. 감사해요!