Beautiful CSS

Making button library

버튼 라이브러리 만들기

Visual Design and Art School Logo Academy of Art University Logo
Related :

교육 카드 개설 현황

Channels :
Units :
Draft :

사이드바 2

Meta Info:

  • 2014년 1월 13일
  • Hyunhwa Jeong
  • 10,503 Views
  • 3 Comments

Table of Contents

버튼 라이브러리 만들기

이 게시물은 2016년 8월 8일 수정판입니다.

이야기에 앞서

CSS3가 보편화 되면서 이미지에 의존해야 했던 예전과 달리, 예쁜 버튼들을 스타일시트에서 쉽게 표현할 수 있게 되었습니다. 물론 아직도 웹 브라우저 호환성 때문에 의도하는 그대로의 모습은 아닐지라도, 다양한 형태와 색상의 버튼을 라이브러리화 할 수 있는 것은 여러모로 편리한 부분입니다. 직접 라이브러리를 만들지 않고도 Bootstrap과 같은 편리한 프레임워크를 사용할 수도 있지만, 원리를 알고 사용하는 것과 모르고 사용하는 것은 큰 차이가 있겠습니다.

이 글에서는 직접 버튼을 라이브러리화 하고, 몇 개의 클래스 조합으로 다양한 버튼을 사용할 수 있는 방법에 대해 알아보려고 합니다.


버튼 라이브러리란?

버튼을 뼈와 살로 나눠 원할 때 마다 환골탈태 시키는 조합서입니다. 여러 웹 사이트를 만들다 보면, 디자인에 따라 색상과 모양이 다른 버튼을 반복적으로 만들게 되는데, 이게 굉장한 노가다입니다. 한번 라이브러리화 해 놓으면 여러 색상 테마를 가진 사이트에 공용으로 사용할 수 있으니, 자기만의 버튼 라이브러리를 가지고 있는 것은 매우 바람직합니다.

a:link span
div
<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년 전만 해도 깨알같은 글씨에 칼 같이 맞춰진 테이블 코딩이 유행이었는데, 사용자의 모니터가 점점 커지고 웹 표준이니 뭐니 여러 트랜드가 합쳐지면서 지금은 사이트의 디자인 자체가 공간을 넓게 사용하고 픽셀 하나 하나의 중요성은 점차 떨어지고 있습니다. 그러다보니 사용하는 버튼의 크기도 매우 다양해졌습니다.

635-01
Github와 같은 사이트에서 다양하게 만날 수 있는 각양각색의 버튼들

그래서 버튼의 기본 골격은 다음과 같이 잡아보도록 합시다.

  • 1차적으로, 버튼의 크기는 아주 작은 크기에서 매우 큰 크기까지 주변 상황에 적절히 대응하기 위해 일일이 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를 확인해야 합니다.

635-02
html5-boilerplate와 같은 대중적인 프레임워크에서 조차 이런 부분이 있습니다.

line-height 문제는 평소에는 없어보이다가, form 요소인 <button>이나 <input>으로 만든 버튼에서 발생합니다.

635-03

한번 html이나 body에 줄 높이를 설정해 버리면, 아무리 자식 태그에서 line-height: normal을 사용해도 무의미하므로 애초부터 조심해야 합니다.


클래스 이름짓기

버튼에서 사용 할 클래스 이름을 지을 때, .btnbutton의 의미를 가장 함축적으로 표현할 수 있는 이상적인 이름입니다. 하지만, 이 이름은 너무 많은 곳에서 사용하고 있어서 충돌 위험이 굉장히 큽니다. 이 이름을 사용하려면 최소한 다음의 조건을 지키세요.

  • 이 버튼 라이브러리는 나만 사용한다.
  • Bootstrap과 같은 외부 라이브러리에서 .btn 클래스를 사용하고 있지는 않은지 확인한다.
  • WordPressXE, 그누보드와 같은 CMS의 코어에서 .btn 클래스를 사용하고 있지는 않은지 확인한다.
  • 사이트에 사용되는 모든 외부 CSS에서 .btn 클래스가 사용되고 있지는 않은지 확인한다.
  • 위에 사용되고 있는 .btn명을 모두 다른 것으로 바꾼다.
635-04
실제로 Bootstrap에서는 버튼 클래스 이름으로 .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 기본 폰트 크기 지정. paddingem 단위가 사용되었기 때문에 폰트 크기는 반드시 px로 정의해야 함.
text-decoration: none 버튼의 글자에 밑줄이 생기지 않도록 처리.
white-space: nowrap 버튼 크기가 작아져도 글자가 줄 바꿈하지 않도록 처리.
cursor: pointer <a> 태그 같은 링크 요소 이외에도 커서가 바뀌도록 처리.

여기서 관심있게 보아야 할 부분은 em 단위가 사용된 padding입니다. 버튼의 여백을 px로 고정하게 되면, 버튼의 글씨가 커지더라도 여백은 함께 늘어나지 않습니다. 하지만 em을 사용하면 폰트 크기에 따라 여백도 함께 늘어납니다. border-radius도 마찬가지입니다. 여기에 사용 된 em 역시 폰트 크기의 영향을 받아, 일일이 값을 지정해 주지 않아도 자연스러운 모서리 처리를 해줍니다.

635-05

em은, 부모나 자기가 가진 속성의 값에 따라 비율로 처리하는 단위입니다. 그래서 잘못 사용하면 얘기치 못한 결과를 낳을 수 있지만, 개념을 잘 이해하고 안전한 상황에서 사용하면 매우 편리한 단위입니다. 여기에 사용된 paddingfont-size의 값에 따라 유기적으로 변화하기 때문에, font-size 만큼은 부모에게 휘둘리지 않을 절대값, 즉 px로 정의되어야 합니다. 아직 empx의 개념이 난해하다면 일단 넘어갑니다.


또 한가지는, 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입니다.

-webkit-와 같은 Prefix는 안붙이나요?

이 예문에서도 그렇지만 이제 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로 고정시킬 때는 웹 브라우저 호환성을 위해 다음의 규칙을 지켜서 작성하는 것이 좋습니다.

  • 버튼의 높이(height)와 줄 높이(line-height)는 동일하게 잡아준다.
  • padding은 위와 아래를 제외한 양 옆만 적용한다.

마치며

이제 코드의 양이 상당히 많아져서, 지금까지 알아 본 버튼 라이브러리를 데모 페이지로 준비하였습니다. 이 데모 페이지를 통해 직접 HTML과 CSS 코드를 확인하고 복사하여 사용할 수 있습니다. 더 멋진 테마를 추가해서 여러분의 작업이 쉽고 즐거워졌으면 하는 바램입니다.

버튼 라이브러리 만들기 데모 페이지

Subscribe
Notify of
guest
3 Comments
Inline Feedbacks
View all comments
dolhim

많이 배워 갑니다. 감사합니다!

송민수

많은 도움이 되었습니다 감사합니다.

김자영

정말 도움 많이 받았습니다. 감사해요!