[ 살펴보기 ] Tailwind - Presets
![[ 살펴보기 ] Tailwind - Presets](https://cdn.hashnode.com/res/hashnode/image/upload/v1726037357068/7f65bdf5-7346-4d14-87db-7bcc3111f2e2.jpeg)
만약 여러 project에 공통으로 적용하고 있는 color palette가 있다면 preset으로 따로 빼놓고 각 프로젝트마다 해당 preset을 적용하여 사용할 수 있다.
Tailwind에서 preset이란 단순히 tailwind configuration obejct를 말한다. 다음 예제를 살펴보자.
import type { Config } from "tailwindcss";
const PRESET_BASE: Pick<Config, "theme"> = {
theme: {
extend: {
colors: {
indigo: {
light: "#9fa8da",
DEFAULT: "#3f51b5",
dark: "#303f9f",
},
deepPurple: {
light: "#b39ddb",
DEFAULT: "#673ab7",
dark: "#512da8",
},
teal: {
light: "#80cbc4",
DEFAULT: "#009688",
dark: "#00796b",
},
},
},
},
};
export default PRESET_BASE;
만약 위의 예제와 같이 특정 color를 extend하는 기본 preset이 있다면 project tailwind.config.ts 파일에서 위의 preset을 추가해 사용할 수 있다. ( preset 파일의 이름은 preset-base.ts라고 가정하고 presets directory에 위치한다고 가정한다 )
import type { Config } from "tailwindcss";
const config: Config = {
...
presets: [require("./presets/preset-base")],
};
export default config;
우리가 적용한 preset은 tailwind의 default theme color를 override하는 것이 아닌 extend를 통해 color를 확장했으므로 tailwind가 default로 제공하는 color와 preset에서 설정한 color를 함께 사용할 수 있다.
<div className="text-orange-500">Test Orange</div>
<div className="text-indigo-dark">Test Indigo</div>
<div className="text-teal-light">Test Teal</div>
여기서 주의할 점은 만약 preset file안에 presets property를 empty array로 설정하면 preset 내용이 기존 tailwind configuration 파일을 완전히 대체한다. 즉, default configuration에 선언한 어떤 property도 실제로 적용되지 않는다.
// preset-base.ts
import type { Config } from "tailwindcss";
const PRESET_BASE: Pick<Config, "theme" | "presets"> = {
presets: [], // presets property 추가
theme: {
extend: {
colors: {
indigo: {
light: "#9fa8da",
DEFAULT: "#3f51b5",
dark: "#303f9f",
},
deepPurple: {
light: "#b39ddb",
DEFAULT: "#673ab7",
dark: "#512da8",
},
teal: {
light: "#80cbc4",
DEFAULT: "#009688",
dark: "#00796b",
},
},
},
},
};
export default PRESET_BASE;
// tailwind-config.ts
import type { Config } from "tailwindcss";
const config: Config = {
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
"./src/*",
],
presets: [require("./presets/preset-base")],
theme: {
extend: {
colors: {
deepCyan: {
light: "#80deea",
DEFAULT: "#00bcd4",
dark: "#0097a7",
},
},
},
},
};
export default config;
위의 예제에서 preset-base의 presets에 empty array를 설정했으므로 해당 preset의 내용이 기존 configuration을 완전히 대체한다. 즉, configuration에 설정한 content property와 extend를 통해 적용한 color 역시 실제로 적용되지 않는다.
만약 configuration 파일에 presets property를 empty array로 설정해도 tailwind의 default style을 모두 disable하는 효과가 나타난다. 의도한 게 아니라면 해당 부분을 주의하자.
Merge logic
Configuration에서 preset을 적용하고 있을 때 둘 다 같은 property를 가지고 있으면 어떻게 될까? property에 따라 merge logic이 다르게 적용되므로 기본적인 merge logic을 알아두면 좋다.
우선 다음 property들은 configuration에서 선언된 값이 우선시 된다.
contentdarkModeprefiximportantvariantOrderseparatorsafelist
Theme
configuration과 preset 둘 다에 theme property가 있으면 shallow merge가 발생한다. configuration과 presest의 theme property에 동일한 property가 존재하면 configuration theme의 property가 preset theme의 property를 대체한다.
// preset-base.ts
import type { Config } from "tailwindcss";
const PRESET_BASE: Pick<Config, "theme"> = {
theme: {
colors: {
indigo: {
light: "#9fa8da",
DEFAULT: "#3f51b5",
dark: "#303f9f",
},
deepPurple: {
light: "#b39ddb",
DEFAULT: "#673ab7",
dark: "#512da8",
},
},
},
};
export default PRESET_BASE;
// tailwind.config.ts
import type { Config } from "tailwindcss";
const config: Config = {
...
presets: [require("./presets/preset-base")],
theme: {
colors: {
cyan: {
light: "#80deea",
DEFAULT: "#00bcd4",
dark: "#0097a7",
},
},
},
};
export default config;
만약 위와 같이 configuration에서 theme.color가 설정되어 있고 preset에서도 theme.color가 설정되어 있으면 configuration의 color가 preset의 color를 완전히 대체한다. 즉, preset의 color를 적용되지 않는다.
다만 extend property는 예외다. 만약 configuration과 preset 모두 extend property를 사용하고 있다면 두 곳 모두의 값이 합쳐져 적용된다. 다만 extend에서도 서로 중복되는 propery key가 있다면 configuration의 설정이 최종 적용된다.
// preset-base.ts
import type { Config } from "tailwindcss";
const PRESET_BASE: Pick<Config, "theme"> = {
theme: {
extend: {
colors: {
indigo: {
light: "#9fa8da",
DEFAULT: "#3f51b5",
dark: "#303f9f",
},
deepPurple: {
light: "#b39ddb",
DEFAULT: "#673ab7",
dark: "#512da8",
},
},
},
},
};
export default PRESET_BASE;
// tailwind.config.ts
import type { Config } from "tailwindcss";
const config: Config = {
...
presets: [require("./presets/preset-base")],
theme: {
extend: {
colors: {
cyan: {
light: "#80deea",
DEFAULT: "#00bcd4",
dark: "#0097a7",
},
},
},
},
};
export default config;
위와 같이 extend가 configuration과 preset 모두 존재하면 둘 다 합쳐서 적용된다.
<div className="text-indigo-dark">Test Text</div>
<div className="text-cyan-dark">Test Text</div>
Plugins
Configuration과 preset 둘 다에 plugins이 설정되어 있으면 둘 다 모두 적용된다.
// preset-base.ts
import type { Config } from "tailwindcss";
const PRESET_BASE: Pick<Config, "theme" | "plugins"> = {
plugins: [require("@tailwindcss/typography")],
theme: {
extend: {
colors: {
indigo: {
light: "#9fa8da",
DEFAULT: "#3f51b5",
dark: "#303f9f",
},
deepPurple: {
light: "#b39ddb",
DEFAULT: "#673ab7",
dark: "#512da8",
},
},
},
},
};
export default PRESET_BASE;
// tailwind.config.ts
import type { Config } from "tailwindcss";
const config: Config = {
...
presets: [require("./presets/preset-base")],
plugins: [require("@tailwindcss/forms")],
theme: {
extend: {
colors: {
cyan: {
light: "#80deea",
DEFAULT: "#00bcd4",
dark: "#0097a7",
},
},
},
},
};
export default config;
위의 예제와 같이 configuration과 preset 둘 다에 plugins property가 있는 경우 둘 다 merge되어 적용된다. 즉, 어디에 선언되어 있는 plugins이든 project에서 사용가능하다.
<article className="prose">
<h1>Garlic bread with cheese: What the science tells us</h1>
<p>
For years parents have espoused the health benefits of eating garlic
bread with cheese to their children, with the food earning such an
iconic status in our culture that kids will often dress up as warm,
cheesy loaf for Halloween.
</p>
<p>
But a recent study shows that the celebrated appetizer may be linked
to a series of rabies cases springing up around the country.
</p>
</article>
<input type="checkbox" className="rounded text-pink-500" />
다만 corePlugin은 일반 plugin과 좀 다르게 merge가 적용된다. 만약 corePlugin이 configuration과 preset 둘 다 object로 지정되어 있다면 둘 다 merge되어 함께 적용된다.
// preset-base.ts
import type { Config } from "tailwindcss";
const PRESET_BASE: Pick<Config, "theme" | "corePlugins"> = {
corePlugins: {
cursor: false,
},
theme: {
extend: {
colors: {
indigo: {
light: "#9fa8da",
DEFAULT: "#3f51b5",
dark: "#303f9f",
},
deepPurple: {
light: "#b39ddb",
DEFAULT: "#673ab7",
dark: "#512da8",
},
},
},
},
};
export default PRESET_BASE;
// tailwind.config.ts
import type { Config } from "tailwindcss";
const config: Config = {
...
presets: [require("./presets/preset-base")],
corePlugins: {
float: false,
},
theme: {
extend: {
colors: {
cyan: {
light: "#80deea",
DEFAULT: "#00bcd4",
dark: "#0097a7",
},
},
},
},
};
export default config;
위와 같은 경우에는 configuration의 corePlugins과 preset의 corePlugins 모두 merge되어 적용된다. 하지만 configuration에서 corePlugins을 array 형식으로 선언하면 configuration의 corePlugins이 preset의 corePlugins을 대체하여 configuration의 corePlugins만 적용된다.
Preset을 한 곳에 모두 정의하여 관리할 수도 있지만 color, screen, space등 용도에 맞게 분산해서 관리할 수도 있다. 용도에 맞게 여preset을 분산해서 운용한다면 아래와 같이 presets array에 여러개의 preset을 전달해줄 수 있다.
import type { Config } from "tailwindcss";
const config: Config = {
...
presets: [
require("./presets/preset-color"),
require("./presets/preset-screen"),
],
corePlugins: {
float: false,
},
theme: {
extend: {
colors: {
cyan: {
light: "#80deea",
DEFAULT: "#00bcd4",
dark: "#0097a7",
},
},
},
},
};
export default config;
주의해야 할 점은 만약 preset에 중복되는 property가 있다면 마지막에 선언된 preset의 property가 최종 적용된다. ( extend property 제외, extend property는 위에서 설명한 방식대로 적용된다 )
![[ 살펴보기 ] RDB - Relationships](https://cdn.hashnode.com/res/hashnode/image/upload/v1739711556668/48dc9e84-a621-42aa-9c9f-5fc5c436f0ec.jpeg)
![[ 살펴보기 ] MySQL - Data types](https://cdn.hashnode.com/res/hashnode/image/upload/v1739593589113/530f8704-4d27-42c9-a451-bb5c63150b99.jpeg)
![[ 살펴보기 ] TypeORM - Transactions, Migration](https://cdn.hashnode.com/res/hashnode/image/upload/v1739106042581/980b8133-61d4-406a-a026-65be9c28eace.jpeg)
![[ 살펴보기 ] TypeORM - Relations](https://cdn.hashnode.com/res/hashnode/image/upload/v1738666874402/b688bd0b-b6bb-4f43-87d8-c1b46b59f1b7.jpeg)
![[ 살펴보기 ] TypeORM - Basics](https://cdn.hashnode.com/res/hashnode/image/upload/v1738666803591/bef5df17-7dc7-4123-ae55-004d5042df39.jpeg)