tailwind CSS를 사용하여 모던 웹 페이지를 만들어 보고 싶었다.
tailwind는 유틸리티 클래스를 모아놓은 라이브러리라고 볼 수 있다.
유틸리티 클래스란 "다양한 예제로 배우는 CSS 설계 실전 가이드" 라는 책에서 읽었던 헬퍼 클래스와 같다.
예를 들어 이런 거다.
.text-red {
color: red;
}
클래스 이름만으로도 기능을 유추할 수 있다.
따라서 다음과 같이 인라인 방식으로 사용할 수 있다.
<p class="text-red font-bold p-4">가나다라</p>
이런 방식으로 코드를 작성하면 CSS를 따로 작성할 필요가 없다.
즉, CSS를 작성하는 시간을 아낄 수 있다.
단점으로는 유틸리티 클래스들을 미리 알고 있어야 한다는 점이다.
tailwind 공식홈페이지의 좌측 검색란에 CSS의 속성을 검색하면 관련 유틸리티 클래스를 보여준다.
이 곳에 정의되어 있는 클래스만을 사용할 수 있다.
정의되어 있지 않다면 커스텀으로 만들 수 있다.
키워드 값이 아닌 숫자 값을 가지는 프로퍼티는 엄청 많은 값을 가질 수 있으므로 이를 전부 정의할 순 없다.
Padding을 예로 들어 보자.
padding: 0.25rem
은 p-1
로 정의되어 있다.
그럼 padding: 25rem
은 p-100
일까?
그렇지 않다.
25rem은 잘 사용하지 않는 숫자다 보니 정의되어 있지 않다.
하지만 p-[25rem]
처럼 대괄호를 사용하여 적용할 수 있다.
숫자 값의 커스텀은 위의 설명대로 하면 끝이다.
너무 간단하다.
하지만, 애니메이션같은 경우는 어떨까?
애니메이션은 단순한 값만으로 표현될 수 없다.
기존의 CSS에서의 애니메이션은 @keyframe
에서 타임스탬프로 동작이 정의되어야 하고 animatiom
에서 시간 및 여러 정보들을 정의해야 한다.
tailwind에서는 이러한 복잡한 값들에 대해서 커스텀을 할 수 있도록 지원한다.
다음은 tailwind.config.js
에서의 작업이다.
export default {
//...
theme: {
extend: {
//...
animation: {
slideTop: "slide-top 1s cubic-bezier(0.25, 0.46, 0.45, 0.94) both",
},
keyframes: {
"slide-top": {
"0%": {
transform: "translateY(100px)",
},
"100%": {
transform: "translateY(0px)",
},
},
},
//...
},
plugins: [],
};
extend에서 커스텀 값들을 추가할 수 있다.
기존에 제공되는 유틸리티 클래스에 커스텀 값이 추가되는 방식이다.
keyframes에 slide-top
이라는 애니메이션을 만들었고
slide-top 1s cubic-bezier() both
라는 값을 가진 slideTop
라는 커스텀 값을 추가했다.
이제 원하는 html 엘리먼트에서 animate-slideTop
를 추가하면 예상대로 동작한다.
그런데 다양한 브라우저에서 같은 동작을 수행하기 위해 하나의 프로퍼티가 다양한 값을 가지는 경우가 있다.
/* ff 3.6+ */
background: -moz-radial-gradient(circle at 85% 25%, rgba(2, 59, 80, 1) 0%, rgba(6, 10, 30, 1) 100%);
/* safari 5.1+,chrome 10+ */
background: -webkit-radial-gradient(circle at 85% 25%, rgba(2, 59, 80, 1) 0%, rgba(6, 10, 30, 1) 100%);
/* opera 11.10+ */
background: -o-radial-gradient(circle at 85% 25%, rgba(2, 59, 80, 1) 0%, rgba(6, 10, 30, 1) 100%);
/* ie 10+ */
background: -ms-radial-gradient(circle at 85% 25%, rgba(2, 59, 80, 1) 0%, rgba(6, 10, 30, 1) 100%);
/* global 92%+ browsers support */
background: radial-gradient(circle at 85% 25%, rgba(2, 59, 80, 1) 0%, rgba(6, 10, 30, 1) 100%);
이 경우 tailwind.config.js
에서 작업할 수 없고 index.css
에서 추가 할 수 있다.
즉, tailwind css가 지원하지 않는 CSS의 정의는 index.css
에서 가능하다.
@layer base {
.bg-gradient {
/* ff 3.6+ */
background: -moz-radial-gradient(circle at 85% 25%, rgba(2, 59, 80, 1) 0%, rgba(6, 10, 30, 1) 100%);
/* safari 5.1+,chrome 10+ */
background: -webkit-radial-gradient(circle at 85% 25%, rgba(2, 59, 80, 1) 0%, rgba(6, 10, 30, 1) 100%);
/* opera 11.10+ */
background: -o-radial-gradient(circle at 85% 25%, rgba(2, 59, 80, 1) 0%, rgba(6, 10, 30, 1) 100%);
/* ie 10+ */
background: -ms-radial-gradient(circle at 85% 25%, rgba(2, 59, 80, 1) 0%, rgba(6, 10, 30, 1) 100%);
/* global 92%+ browsers support */
background: radial-gradient(circle at 85% 25%, rgba(2, 59, 80, 1) 0%, rgba(6, 10, 30, 1) 100%);
}
}
뿐만 아니라 자주 함께 사용되는 유틸리티 클래스들을 한 그룹으로 묶어 새로운 커스텀 유틸리티 클래스로 만들 수 도 있다.
@layer base {
.text-blue-gradient {
@apply bg-gradient-to-r from-secondary to-third bg-clip-text text-transparent;
}
}
위의 코드는 글자에 gradient 배경색을 입히는 코드이다.
여러 유틸리티 클래스가 함께 사용되어야 원하는 결과가 나온다.
따라서 필요한 유틸리티 클래스를 모아서 text-blue-gradient
라는 새로운 커스텀 유틸리티 클래스를 만들었다.
개인적으로 tailwind CSS를 사용하면서 느꼈던 가장 큰 단점은 해당 엘리먼트가 어떤 것인지 구별하기가 힘들다는 점이다.
이전에 BEM 설계 기법을 사용했기 때문인지 이러한 단점이 더욱 와닿았다.
다음을 비교해보자.
/** BEM 설계 기법*/
<div class="card">
<h3 class="card-title">Hello</h3>
<p class="card-content">...</p>
</div>
/** tailwind CSS */
<div class="w-full p-4 rounded-full bg-white">
<h3 class="font-bold text-xl text-red">Hello</h3>
<p class="text-sm text-black">...</p>
</div>
BEM을 사용할 땐 해당 엘리먼트가 card라는 것이 한 눈에 보인다.
하지만 tailwind CSS는 기능을 중심이므로 해당 엘리먼트가 어떤 것인지 한 눈에 알아보기 힘들다.
tailwind CSS를 사용한 것은 이번이 처음이다.
그렇기때문에 tailwind 공식 홈페이지에서 유틸리티 클래스를 찾아가며 코딩할 수 밖에 없었고 tailwind CSS의 장점인 빠른 코딩을 체감할 수 없었다.
오히려 위에서 언급한 대로 해당 엘리먼트가 어떤 것인지 알아보기 힘들어서 코딩하는 데 더 오랜시간이 걸렸다.
하지만 이는 익숙치 않아서 발생한 문제이므로 만약 tailwind CSS에 익숙해지면 상당한 시간단축이 있을 것으로 예상된다.
이번엔 create-react-app 툴 대신 vite를 사용해서 프로그램을 빌드했다.
vite가 빠르다곤 하지만 체감을 느끼지는 못했다.
물론 vite가 더 빠른건 맞지만 프로젝트의 크기가 큰 편이 아니어서 끽 해봐야 1~2초 차이만 날 뿐이다.
create-react-app에 내장된 webpack도 개발 서버, HMR 및 라이브 리로딩을 지원하기 때문에 개발하면서 바로바로 피드백을 보면서 개발 할 수 있었다.
그렇기에 개발 능률상으로 큰 차이를 느끼지는 못했다.
하지만, webpack과 달리 깔끔한 공식 문서가 마음에 들었고, 스타팅 folder structure의 정리정돈(?)이 내 취향에 가까워서 뭔가 친근감이 들었다.