Tailwind
์ ํธ๋ฆฌํฐ ๊ธฐ๋ฐ์ CSS ํ๋ ์์ํฌ
โข
Tailwind vs Boostrap
โข
์ฌ์ฉ ๋ฐฉ๋ฒ
1.
CDN ๋ฐฉ์
2.
Node.js CLI ๋ฐฉ์
3.
React ์ธํ
โข
๊ธฐ๋ณธ ์ฌ์ฉ
โฆ
๋ฉ์ธ ํ๋ฉด
โฆ
๋ก๊ทธ์ธ ํ๋ฉด
Tailwind vs Boostrap
ํญ๋ชฉ | Tailwind CSS | Bootstrap |
์คํ์ผ๋ง ์ ๊ทผ ๋ฐฉ์ | ์ ํธ๋ฆฌํฐ ํด๋์ค ๊ธฐ๋ฐ | ์ปดํฌ๋ํธ ๊ธฐ๋ฐ |
์ปค์คํฐ๋ง์ด์ง | ์ค์ ํ์ผ์ ํตํ ์ ํธ๋ฆฌํฐ
ํด๋์ค ํ์ฅ ๋ฐ ์์ | SCSS ๋ณ์์ ๋ฏน์ค์ธ์ผ๋ก
์ปค์คํฐ๋ง์ด์ง ๊ฐ๋ฅ |
๋ฏธ๋ฆฌ ์ ์๋ ์ปดํฌ๋ํธ | ์์ | ๋ฒํผ, ์นด๋, ๋ค๋น๊ฒ์ด์
๋ฐ ๋ฑ ์ ๊ณต |
CSS ํ์ผ ํฌ๊ธฐ | JIT ๋ชจ๋๋ก ์ค์ ์ฌ์ฉ๋ ํด๋์ค๋ง ๋น๋ | ๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ ์คํ์ผ ํฌํจ |
๋ฐ์ํ ๋์์ธ | ๋ฐ์ํ ์ ํธ๋ฆฌํฐ ํด๋์ค (sm:, md:, ๋ฑ) | ๋ฏธ๋์ด ์ฟผ๋ฆฌ ๊ธฐ๋ฐ ํด๋์ค (col-md-6 ๋ฑ) |
ํ์ต ๊ณก์ | ์ ํธ๋ฆฌํฐ ํด๋์ค์ ์กฐํฉ์ ์ตํ์ผ ํจ | ์ปดํฌ๋ํธ ์ฌ์ฉ๋ฒ์ ๋ฐฐ์ฐ๊ธฐ ์ฌ์ |
๋์์ธ ์์คํ
| ์ง์ ๊ตฌ์ถ ํ์ | ํ๋ฆฌ์
์คํ์ผ ์ ๊ณต |
์ฌ์ฉ ์ฌ๋ก | ๋ง์ถคํ ๋์์ธ,
๋์์ธ ์์คํ
๊ตฌ์ถ์ ์ ํฉ | ์ผ๊ด๋ ์คํ์ผ ์ ์ง,
๋น ๋ฅธ ์ด๊ธฐ ๊ฐ๋ฐ์ ์ ํฉ |
๋ฐ์ํ ๊ทธ๋ฆฌ๋ ์์คํ
| ์ ํธ๋ฆฌํฐ ํด๋์ค ์กฐํฉ | 12-์ปฌ๋ผ ๊ทธ๋ฆฌ๋ ์์คํ
|
์ํ ๋ณํ ์ง์ | ์ํ๋ณ ์ ํธ๋ฆฌํฐ ํด๋์ค (ํธ๋ฒ, ํฌ์ปค์ค ๋ฑ) | ์ํ๋ณ ์ ํธ๋ฆฌํฐ ํด๋์ค ์ ๊ณต |
๋คํฌ ๋ชจ๋ ์ง์ | ์ ํธ๋ฆฌํฐ ํด๋์ค ์ ๊ณต | ์ง์ ๊ตฌํ ํ์ |
์ฌ์ฉ ๋ฐฉ๋ฒ
1.
CDN ๋ฐฉ์
2.
Node.js CLI ๋ฐฉ์
3.
React ์ธํ
CDN ๋ฐฉ์
1.
CDN script ์ถ๊ฐ
2.
์ค์
3.
์ฝ๋
CDN script ์ถ๊ฐ
<script src="https://cdn.tailwindcss.com"></script>
HTML
๋ณต์ฌ
์ค์
<!-- ์ค์ -->
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#262626',
secondary: '#38BDF8',
}
}
}
}
</script>
HTML
๋ณต์ฌ
์ฝ๋
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- CDN script ์ถ๊ฐ -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- ์ค์ -->
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#262626',
secondary: '#38BDF8',
}
}
}
}
</script>
</head>
<body class="text-white flex flex-col items-center justify-center gap-10 min-h-screen">
<div class="max-w-lg mx-auto bg-secondary p-6 rounded-lg shadow-md">
<h1 class="text-2xl font-bold mb-4">Hello, Tailwind!</h1>
<p>tailwind ์ค์ ์ผ๋ก ํ
๋ง ์ปฌ๋ฌ๋ฅผ ์ค์ ํ๊ณ ์ฌ์ฉํด๋ด
๋๋ค.</p>
<button class="mt-4 bg-primary text-white py-2 px-4 rounded">Primary Button</button>
</div>
<div class="max-w-lg mx-auto bg-primary p-6 rounded-lg border shadow-md">
<h1 class="text-2xl font-bold mb-4">Hello, Tailwind!</h1>
<p>tailwind ์ค์ ์ผ๋ก ํ
๋ง ์ปฌ๋ฌ๋ฅผ ์ค์ ํ๊ณ ์ฌ์ฉํด๋ด
๋๋ค.</p>
<button class="mt-4 bg-secondary text-white py-2 px-4 rounded">Secondary Button</button>
</div>
</body>
</html>
HTML
๋ณต์ฌ
Node.js CLI ๋ฐฉ์
1.
tailwind ์ค์น
2.
tailwind.config.js ์ค์ ํ์ผ ์์ฑ
3.
tailwind.config.js ์ค์
4.
input.css ์์ฑ
5.
output.css ๋น๋
6.
html ์์ฑ
tailwind ์ค์น
npm install -D tailwindcss
Bash
๋ณต์ฌ
tailwind.config.js ์ค์ ํ์ผ ์์ฑ
npx tailwindcss init
Bash
๋ณต์ฌ
tailwind.config.js ์ค์
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{html,js}"],
theme: {
extend: {
colors: {
primary: '#262626',
secondary: '#38BDF8',
}
}
},
plugins: [],
}
JavaScript
๋ณต์ฌ
input.css ์์ฑ
๋ค์ ์ง์์๋ฅผ ์ฌ์ฉํ์ฌ, tailwind ์ ์คํ์ผ ๋ ์ด์ด๋ฅผ ์ถ๊ฐํฉ๋๋ค.
@tailwind base;
@tailwind components;
@tailwind utilities;
CSS
๋ณต์ฌ
โข
@tailwind base;:
โฆ
์ด ์ง์์ด๋ Tailwind์ ๊ธฐ๋ณธ ์คํ์ผ์ ํฌํจํฉ๋๋ค. ๊ธฐ๋ณธ ์คํ์ผ์ ๋ธ๋ผ์ฐ์ ์ ๊ธฐ๋ณธ ์คํ์ผ์ ๋ฆฌ์
ํ๊ณ , ์ผ๊ด๋ ๊ธฐ์ด ๋์์ธ์ ์ ๊ณตํ๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก๋ ์คํ์ผ์ ์ผ๊ด์ฑ์ ์ ์งํ๊ณ ๊ธฐ๋ณธ์ ์ธ ํ์ดํฌ๊ทธ๋ํผ ์คํ์ผ์ ์ค์ ํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
โข
@tailwind components;:
โฆ
์ด ์ง์์ด๋ Tailwind์ ์ปดํฌ๋ํธ ์คํ์ผ์ ๊ฐ์ ธ์ต๋๋ค. Tailwind์์ ์ปดํฌ๋ํธ๋ ์์ฃผ ์ฌ์ฉํ๋ ์คํ์ผ ์ธํธ๋ฅผ ๋งํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๋ฒํผ, ํผ, ์๋ฆผ ๋ฑ์ ์คํ์ผ์ด ํฌํจ๋ฉ๋๋ค. ๋ฌผ๋ก ์์ ๋ง์ ์ปค์คํ
์ปดํฌ๋ํธ๋ฅผ ์ ์ํ ์๋ ์์ต๋๋ค.
โข
@tailwind utilities;:
โฆ
์ด ์ง์์ด๋ Tailwind์ ์ ํธ๋ฆฌํฐ ํด๋์ค๋ฅผ ํฌํจํฉ๋๋ค. ์ ํธ๋ฆฌํฐ ํด๋์ค๋ HTML ์์์ ์ง์ ์ ์ฉํ์ฌ ์คํ์ผ์ ์ง์ ํ๋ ๋ฎ์ ์์ค์ ํด๋์ค๋ค์
๋๋ค. ์๋ฅผ ๋ค์ด, ํจ๋ฉ, ๋ง์ง, ํ
์คํธ ์์, ๋ฐฐ๊ฒฝ ์์ ๋ฑ์ ์คํ์ผ์ ์ค์ ํ ์ ์๋ ํด๋์ค๋ค์
๋๋ค.
output.css ๋น๋
npx tailwindcss -i ./src/input.css -o ./src/output.css --watch
Bash
๋ณต์ฌ
html ์์ฑ
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- ๋น๋๋ CSS ํฌํจํ๊ธฐ -->
<link href="./output.css" rel="stylesheet">
</head>
<body class="text-white flex flex-col items-center justify-center gap-10 min-h-screen">
<div class="max-w-lg mx-auto bg-secondary p-6 rounded-lg shadow-md">
<h1 class="text-2xl font-bold mb-4">Hello, Tailwind!</h1>
<p>tailwind ์ค์ ์ผ๋ก ํ
๋ง ์ปฌ๋ฌ๋ฅผ ์ค์ ํ๊ณ ์ฌ์ฉํด๋ด
๋๋ค.</p>
<button class="mt-4 bg-primary text-white py-2 px-4 rounded">Primary Button</button>
</div>
<div class="max-w-lg mx-auto bg-primary p-6 rounded-lg border shadow-md">
<h1 class="text-2xl font-bold mb-4">Hello, Tailwind!</h1>
<p>tailwind ์ค์ ์ผ๋ก ํ
๋ง ์ปฌ๋ฌ๋ฅผ ์ค์ ํ๊ณ ์ฌ์ฉํด๋ด
๋๋ค.</p>
<button class="mt-4 bg-secondary text-white py-2 px-4 rounded">Secondary Button</button>
</div>
</body>
</html>
HTML
๋ณต์ฌ
React ์ธํ
1.
React ํ๋ก์ ํธ ์์ฑ
2.
tailwind ์ค์น
3.
tailwind.config.js ์ค์ ํ์ผ ์์ฑ
4.
tailwind.config.js ์ค์
5.
index.css ์์ฑ
6.
ํ๋ก์ ํธ ๋น๋
7.
์ปดํฌ๋ํธ ์์ฑ
React ํ๋ก์ ํธ ์์ฑ
npx create-react-app tailwind-app
cd tailwind-app
Bash
๋ณต์ฌ
tailwind ์ค์น
npm install -D tailwindcss
Bash
๋ณต์ฌ
tailwind.config.js ์ค์ ํ์ผ ์์ฑ
npx tailwindcss init
Bash
๋ณต์ฌ
tailwind.config.js ์ค์
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {
colors: {
primary: '#262626',
secondary: '#38BDF8',
}
}
},
plugins: [],
}
JavaScript
๋ณต์ฌ
index.css ์์ฑ
/* tailwind ์ง์์ ์ถ๊ฐ */
@tailwind base;
@tailwind components;
@tailwind utilities;
/* index.css ๊ธฐ๋ณธ ์ฝ๋ */
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
CSS
๋ณต์ฌ
ํ๋ก์ ํธ ๋น๋
npm run start
Bash
๋ณต์ฌ
์ปดํฌ๋ํธ ์์ฑ - App.js
import React from 'react';
const App = () => {
return (
<div className="text-white flex flex-col items-center justify-center gap-10 min-h-screen">
<div className="max-w-lg mx-auto bg-secondary p-6 rounded-lg shadow-md">
<h1 className="text-2xl font-bold mb-4">Hello, Tailwind!</h1>
<p>tailwind ์ค์ ์ผ๋ก ํ
๋ง ์ปฌ๋ฌ๋ฅผ ์ค์ ํ๊ณ ์ฌ์ฉํด๋ด
๋๋ค.</p>
<button className="mt-4 bg-primary text-white py-2 px-4 rounded">Primary Button</button>
</div>
<div className="max-w-lg mx-auto bg-primary p-6 rounded-lg border shadow-md">
<h1 className="text-2xl font-bold mb-4">Hello, Tailwind!</h1>
<p>tailwind ์ค์ ์ผ๋ก ํ
๋ง ์ปฌ๋ฌ๋ฅผ ์ค์ ํ๊ณ ์ฌ์ฉํด๋ด
๋๋ค.</p>
<button className="mt-4 bg-secondary text-white py-2 px-4 rounded">Secondary Button</button>
</div>
</div>
);
};
export default App;
JavaScript
๋ณต์ฌ
๊ธฐ๋ณธ ์ฌ์ฉ
โข
๊ธฐ๋ณธ ์ค์
โข
๋ฉ์ธ ํ๋ฉด
โข
๋ก๊ทธ์ธ ํ๋ฉด
๊ธฐ๋ณธ ์ค์
โข
ํ๋ก์ ํธ ์์ฑ
โข
tailwind
โข
react-router
โข
ํ๋ก์ ํธ ๊ตฌ์กฐ
โข
์ปดํฌ๋ํธ
ํ๋ก์ ํธ ์์ฑ
npx create-react-app basic-app
Bash
๋ณต์ฌ
tailwind
npm install -D tailwindcss
npx tailwindcss init
Bash
๋ณต์ฌ
react-router
npm install react-router-dom
Bash
๋ณต์ฌ
ํ๋ก์ ํธ ๊ตฌ์กฐ
์ปดํฌ๋ํธ
โข
Header.jsx
โข
Footer.jsx
Header.jsx
import React from 'react';
import { Link } from 'react-router-dom';
const Header = () => {
return (
<header className="bg-gray-800 text-white p-4">
<div className="container mx-auto flex justify-between items-center">
<Link to="/"><h1 className="text-xl font-bold">ALOHA CLASS</h1></Link>
<nav>
<Link to="/" className="mx-2 hover:underline">Home</Link>
<Link to="/login" className="mx-2 hover:underline">Login</Link>
</nav>
</div>
</header>
);
};
export default Header;
JavaScript
๋ณต์ฌ
Footer.jsx
import React from 'react';
const Footer = () => {
return (
<footer className="bg-gray-800 text-white p-4">
<div className="container mx-auto text-center">
<p>© 2024 ALOHA CLASS. All rights reserved.</p>
</div>
</footer>
);
};
export default Footer;
JavaScript
๋ณต์ฌ
๋ฉ์ธ ํ๋ฉด
โข
Main.jsx
import React from 'react'
import Header from '../components/Header'
import Footer from '../components/Footer'
import { Link } from 'react-router-dom'
const Main = () => {
return (
<div className='min-h-screen flex flex-col'>
<Header />
<main className="flex-1 container">
<Section />
</main>
<Footer />
</div>
)
}
export default Main
export const Section = () => {
return (
<section className="p-40 shadow-lg">
<div className="container mx-auto text-center">
<h2 className="text-3xl font-bold mb-4">๋ฉ์ธ ํ๋ฉด</h2>
<p className="mb-6">์๋
ํ์ธ์~! React x Tailwind ๊ธฐ๋ณธ ํ๋ก์ ํธ์
๋๋ค.</p>
<Link to="/login">
<button className="bg-yellow-400 text-gray-800 py-2 px-6 rounded-lg hover:bg-yellow-500">
Login
</button>
</Link>
</div>
</section>
)
}
JavaScript
๋ณต์ฌ
๋ก๊ทธ์ธ ํ๋ฉด
โข
Login.jsx
import React from 'react';
import Header from '../components/Header';
import Footer from '../components/Footer';
const Login = () => {
return (
<div className="min-h-screen flex flex-col">
<Header />
<main className="flex-1 flex items-center justify-center bg-gray-100">
<div className="bg-white p-8 rounded-lg shadow-md w-full max-w-sm">
<h2 className="text-2xl font-bold mb-6 text-center">Login</h2>
<form>
<div className="mb-4">
<label htmlFor="username" className="block text-sm font-medium text-gray-700">์์ด๋</label>
<input
type="text"
id="username"
name="username"
required
className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
placeholder="์์ด๋๋ฅผ ์
๋ ฅํ์ธ์."
/>
</div>
<div className="mb-6">
<label htmlFor="password" className="block text-sm font-medium text-gray-700">๋น๋ฐ๋ฒํธ</label>
<input
type="password"
id="password"
name="password"
required
className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
placeholder="โขโขโขโขโขโขโขโข"
/>
</div>
<button
type="submit"
className="w-full py-2 px-4 bg-blue-500 text-white font-semibold rounded-lg shadow-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
>
๋ก๊ทธ์ธ
</button>
</form>
</div>
</main>
<Footer />
</div>
);
};
export default Login;
JavaScript
๋ณต์ฌ
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import './index.css';
import Main from './pages/Main';
import Login from './pages/Login';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Router>
<Routes>
<Route path="/" element={<Main />} />
<Route path="/login" element={<Login />} />
</Routes>
</Router>
);
JavaScript
๋ณต์ฌ