Ayden's journal

tailwindCSS v4

선호하는 스타일링 라이브러리에 대한 질문을 받으면, 나는 언제나 '디자인 시스템이 잘 갖춰진 프로젝트라면 tailwindCSS(이하 테일윈드)를, 그렇지 않은 경우라면 moduleCSS를 선택한다'고 답해왔다. 그러나 오늘부터는 이 대답의 결이 조금 달라질 것 같다. 새로운 버전의 테일윈드가 출시되었고, 이 라이브러리의 메인테이너가 내린 많은 결정들이 내 마음에 쏙 들었기 때문이다.

 

Theme variables

이전까지만 해도 테일윈드의 클래스를 입맛대로 수정하려면 tailwind.config.ts를 사용해야 했다. 아래는 내가 실제로 작성했던 설정 파일 일부이다. spacing의 값을 rem으로 덮어쓰기 위해 여러 과정을 거치고 있고, [ 이런 ] 어처구니 없는 문제를 맞닥트리기도 했다.

import type { Config } from "tailwindcss";

const range = (start: number, end: number) => {
  let arr = [];
  let length = end - start;
  for (let i = 0; i <= length; i++) {
    arr[i] = start;
    start++;
  }
  return arr;
};

type Accum = {
  [key: string]: string;
};

const accum: Accum = range(0, 1600).reduce((acc, px) => {
  acc[`${px}`] = `${px / 10}rem`;
  return acc;
}, {} as Accum);

const config: Config = {
  content: [
    "./pages/**/*.{js,ts,jsx,tsx,mdx}",
    "./components/**/*.{js,ts,jsx,tsx,mdx}",
    "./utils/**/*.{js,ts,jsx,tsx,mdx}",
  ],
  theme: {
    spacing: {
      ...accum,
    },

 

새로운 버전의 테일윈드는 @theme이라는 사용자 정의 앳룰을 제공한다. 이와 함께 추가된 테마 변수를 사용하면 손쉽게 새로운 클래스를 생성하거나 기존의 클래스를 덮어쓸 수 있다.

예를 들어보자. 이전 버전에서 나는 0부터 1600까지의 spacing을 정의하기 위해서 실제로 1601개의 클래스 네임을 생성해야 했다. 하지만 새로운 버전에서는 --spacing 테마 변수 하나로 이를 정의할 수 있다. 아래는 클래스 내부에서 크기를 계산할 때 --spacing 테마 변수를 추종하는 일부 속성을 나열한 것이다.

// css
@theme {
  --spacing: 0.1rem; 
}

// class definition
w-<number> | width: calc(var(--spacing) * <number>);
min-w-<number> | min-width: calc(var(--spacing) * <number>);
max-w-<number> | max-width: calc(var(--spacing) * <number>);

h-<number> | height: calc(var(--spacing) * <number>);
min-h-<number> | min-height: calc(var(--spacing) * <number>);
max-h-<number> | max-height: calc(var(--spacing) * <number>);

p-<number> | padding: calc(var(--spacing) * <number>);
m-<number> | margin: calc(var(--spacing) * <number>);

gap-<number> | gap: calc(var(--spacing) * <value>);

leading-<number> | line-height: calc(var(--spacing) * <number>)

 

이와 관련된 더 자세한 내용은 공식 문서의 [ theme variables ]에서 확인할 수 있으며, 참고로 남겨놓자면 --spacing 테마 변수의 기본 값은 0.25rem이며 아쉽게도 font-size는 --spacing 테마 변수를 추종하지 않는다(까비 아깝소).

 

Dynamic Utility Values

이전 버전에서는 정적인 값만 지원되었으나, 4.0부터는 동적으로 계산된 값도 사용할 수 있다. 참고로 css 변수를 사용할 때는 대괄호가 아니라 소괄호를 사용해야 한다.

<div class="hover:bg-[hsl(200,100%,50%)] active:scale-[1.25]">

<div class="hover:bg-[hsl(200,100%,50%)] active:scale-(--large-scale)">

 

opacity

기존에는 배경이나 글자 등의 투명도를 조절하기 위해 `bg-opacity-*` 등의 클래스를 사용해야 했다. 새로운 버전의 테일윈드에서는 분수(fraction) 형태로 이를 조절할 수 있게 되었다.

bg-black/50
text-black/50
border-black/50
placeholder-black/50

 

container query

지난 버전에서는 플러그인으로 제공되었던 컨테이너 쿼리가 새로운 버전에 공식적으로 포함되었다. container-name도 사용할 수 있으며, `--container-*` 테마 변수를 사용해 컨테이너의 크기에 따라 동적으로 스타일을 변경시킬 구간을 추가할 수 있다. 컨테이너 쿼리가 추가된 것은 좋지만 anchor position 관련 스타일은 없는 게 조금 아쉽긴 하다.

<div class="@container/main">
  <!-- ... -->
  <div class="flex flex-row @sm/main:flex-col">
    <!-- ... -->
  </div>
</div>

컨테이너 쿼리 길이 단위를 사용하려면 대괄호를 써야한다.

<div class="@container">
  <div class="w-[50cqw]">
    <!-- ... -->
  </div>
</div>

 

data attributes

data-* 속성은 표준이 아닌 속성이나 추가적인 DOM 속성과 같은 다른 조작을 하지 않고도, 의미론적 표준 HTML 요소에 추가 정보를 저장할 수 있게 한다. 테일윈드에서는 세 가지 방식으로 이 속성에 대한 스타일링을 지원한다.

// data-*의 존재 유무
<div data-active class="data-active:border-purple-500">
  <!-- ... -->
</div>

// 특정 data-* 값 일치
<div data-size="large" class="data-[size=large]:p-8">
  <!-- ... -->
</div>

// custom-variant 사용
@custom-variant data-checked (&[data-ui~="checked"]);

<div data-ui="checked active" class="data-checked:underline">
  <!-- ... -->
</div>

 

open

새로운 버전에는 <details>나 <dialog>, popover API가 open 상태일 때 조건부로 스타일링하기 위해 상태 기반 유틸리티 클래스 open이 추가되었다.

<div>
  <button popovertarget="my-popover">Open Popover</button>
  <div popover id="my-popover" class="opacity-0 open:opacity-100 ...">
    <!-- ... -->
  </div>
</div>

 

자식 및 자손 선택자

<li class="py-4 first:pt-0 ...">

<li class="py-4 last:pb-0 ...">

<li class="py-4 only:py-0 ...">

<li class="py-4 odd:py-0 ...">

<li class="py-4 even:py-0 ...">
<div class="nth-3:underline">

<div class="nth-last-5:underline">

<div class="nth-of-type-4:underline">

<div class="nth-last-of-type-6:underline">

<div class="nth-[2n-1]:underline">
<a href="#" class="mr-2 first-of-type:mr-6 ...">

<a href="#" class="mr-2 last-of-type:mr-6 ...">

<a href="#" class="mr-2 only-of-type:mr-6 ...">

 

tailwindCSS in next.js 15

이 포스트를 쓰고 있는 현재까지도 next.js는 4버전이 아니라 3.4.1 버전의 테일윈드를 사용하고 있다. 따라서 업데이트를 해주어야 하는데, 그 방식은 아래와 같다. 설치되어있는 tailwind.config.js 파일의 경우 4버전에서는 더이상 쓸모가 없으므로 삭제해주면 된다.

// Tailwind CSS 설치
npm install tailwindcss@next @tailwindcss/postcss@next -D

// postcss 파일 수정
/** @type {import('postcss-load-config').Config} */
const config = {
  plugins: {
    '@tailwindcss/postcss': {},
  },
};

export default config;

// globals.css 수정
@import 'tailwindcss';

@theme {}

블로그의 정보

Ayden's journal

Beard Weard Ayden

활동하기