기억의 실마리
2023. 3. 25. 18:24

Tailwind CSS

Utility First를 지향하는 CSS프레임워크다.

Utility First란 미리 세팅된 유틸리티 클래스를 활용하여 HTML코드 내에서 CSS를 적용시키는 것을 뜻 한다.

CSS의 각 속성들을 직관적인 className으로 표현하여 효율적으로 사용할 수 있게 된다.

일반적으로 필요한 대부분의 CSS속성을 className으로 제공한다.

 

Tailwind CSS의 장점

내가 생각한 가장 큰 장점은 개발을 진행함에 있어 스타일에 대한 CSS className을 고민하지 않아도 되고

Style Sheet를 들여다보지않고 적용되어있는 className으로 보면서 변경, 적용시키기가 손쉬운 점

뽑고 싶다. 이 외에도 여러 장점이 있다.

  • Break Point가 존재하여 반응형 디자인을 쉽게 적용할 수 있다.
  • 기본으로 제공되는 class외에도 직접적으로 커스터마이징을 하여 새로운 CSS속성을 만들어 적용할 수 있다.
  • 반복되는 스타일은 component, class를 추상화 하여 재사용이 가능하다.
  • TailwindCSS Document는 비교적 친절하게 기능을 서술하고 있으며 러닝커브가 낮다.
  • 다크모드를 지원하기 때문에 따로 CSS속성을 지정하는 수고를 덜 수 있다.

 

Tailwind CSS의 단점

내가 생각한 가장 큰 단점은 코드의 가시성이 떨어지는 것과 속성들의 우선수위문제이다.

직관성이 좋은 반면에 가시성이 떨어지는 것이 실수하기 쉬운 요소로 다가오기도 한다.

또한 속성의 우선순위가 출현빈도나 순서에 상관없이 정의한 순서에 따라 적용되기 때문에

유의하며 className을 적용시켜야한다.

  • 정의된 CSS파일의 용량이 매우 커진다. 하지만 반대로 component가 늘어나도 CSS파일 용량이 상대적으로 늘어나지 않는다는 장점이 존재한다. 규모가 큰 프로젝트일수록 용량에 대한 혜택을 볼 수 있다.
  • 특정 prefix는 모든 CSS속성을 지원하지 않는다. hover: 또는 focus: 등 특정 prefix는 일부속성만 사용가능하다.

 

install & init

npm install -D tailwindcss
npx tailwindcss init

Tailwind CSS를 설치 후 적용시킨다.

 

 tailwind.config.js

// tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./src/**/*.{html,js}"],
  theme: {
    extend: {},
  },
  plugins: [],
}

모든 템플릿파일에 대한 경로를 추가하여 config를 적용시킨다.

tailwind.config.js파일은 기본적인 설정 외에도 설정을 커스텀하여 적용시킬 수 있는 config파일이다.

 

아래의 예시와 같이 적용시킬 수 있다.

/** @type {import('tailwindcss').Config} */

// tailwindCSS에서 px정의가 따로 되어있지 않기 때문에 px로 적용하는 경우를 대비한 함수
const createPxEntries = (size) => {
    return {...Array.from(Array(size + 1)).reduce((accumulator, _, i) => {
            return {...accumulator, [`${i}px`]: `${i}px` }
        })
    };
}
// tailwindCSS에서 보다 직관적으로 rem단위를 사용할 수 있도록 font-size: 16px기준으로  px과 동일한 숫자로 통일한 함수
const createRemEntries = (size) => {
    return {...Array.from(Array(size + 1)).reduce((accumulator, _, i) => {
            return {...accumulator, [i]: `${i * 0.0625}rem` }
        })
    };
}

module.exports = {
    content: [
        './src/**/*.{js,jsx,ts,tsx}',
    ],
    theme: {
        extend: {
            screens: {
            
            	// 다양한 mobile-size에 대응하기 위해 추가적인 media-query 생성
                'mobile-md' : '450px',
            },
            fontSize: {...createPxEntries(50), ...createRemEntries(50)},
            
            // spacing은 길이에 대한 모든 className에 적용시킨다.
            spacing: {...createPxEntries(100), ...createRemEntries(100)},
            colors:{
                'primary-300': '#EB5500', // 자주쓰이는 컬러를 지정
                'primary-200': '#FF7A00',
                'primary-100': '#FFE0B0',
            },
        },
    },
    plugins: [
        require('@tailwindcss/line-clamp'), // plug-in 적용도 가능하다.
        require('@tailwindcss/aspect-ratio'),
    ],
}

파일 자체가 js파일이기 때문에 추가적으로 함수를 만들어 적용시킬 수도 있다.

함수를 만들어 적용시켜 줄 때 주의사항은 용량이 커지기 때문에 코드작성시 검색기에 부하가 걸려 느려질 수 있다.

위에서 spacing의 경우 특히나 많은 속성에 관여하기 때문에 필요한 만큼만, 가능하면 적은 수를 적용하는 것이 좋다.

 

globals.css

tailwindCSS 만으로 style속성을 주기 난해한 경우에 쓰일 CSS파일을 만든 후

tailwindCSS의 속성을 같이 사용할 수 있도록 만들 수 있다.

/* globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

 

아래 예시처럼 애매하거나 속성지정이 난해한 경우 @apply를 사용하여 CSS에 tailwindCSS속성을 같이 지정 할 수 있다.

/* globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

input[name=tradeOrder]:checked + label{
    @apply bg-crypto-pale-grey text-crypto-dark transition-all duration-300
}

 

사용예시

import {useNavigate} from "react-router-dom";
import rocket from "../assets/rocket.svg";
import React from "react";

export const HomeIntroContents = (props: {img:string, title:string, summary:string, opt?:string}) => {
    const navigate = useNavigate();
    return (
        <li
            className="cursor-pointer flex w-full p-12 rounded-[16px] bg-crypto-pale-grey text-start text-crypto-dark"
            onClick={() => {return props.img === rocket ? navigate('trades') : navigate('wallets')}}
        >
            <figure className="relative w-52 h-52 rocket-bg rounded-[12px] rocket-gradient mr-16">
                <img src={props.img} className={`${props.opt}`} alt=""/>
            </figure>
            <div className="relative flex flex-col justify-center">
                <h1 className="text-16 font-normal">
                    {props.title}
                </h1>
                <p className="font-normal text-14 text-crypto-cool-grey">
                    {props.summary}
                </p>
            </div>
        </li>
    )
}

className내에서 백틱과 중괄호를 사용하여 `${isShow ? 'visible' : 'invisible'}` 와 같은 조건문을 넣거나 함수를 포함시켜 사용할 수도 있으며 tailwindCSS에 지정된 className이 없는 경우에는 w-[16vh] 와 같이 대괄호를 사용하여 사용자지정 CSS를 적용시킬 수도 있다.

 

마치며...

나는 tailwindCSS의 존재를 알게 된 이후로 사실상 style적용은 모두 tailwindCSS로 하고 있다. 처음엔 낯설게 느껴졌지만 프로젝트를 진행하면서 지속적으로 사용하고 사용성에 대해 저울질을 해본 결과 tailwindCSS의 압승이었다. 앞으로도 채택할 수 있다면 tailwindCSS를 채용하여 프로젝트를 진행할 예정이다.