안녕하세요?
오늘은 지금까지 쭉 관심있게 지켜본 Tailwind CSS 에 대해 공부해 볼까 합니다.
Tailwind CSS 가 최근 가장 핫한 CSS 유틸인데요.
React 로 UI 디자인은 보통 Material-UI, Bootstrap, Ant Design 등으로 많이 만드는데요.
최근에는 좀더 가벼운걸 찾는 추세라 Tailwind CSS 가 뜨고 있습니다.
Tailwind CSS 는 일반적으로 CSS 헬퍼 유틸(Helper Utilities)이라고 하는데요.
예를 들어 일반적으로 CSS로 마진을 부여할 때는
margin-right : "20px"
이렇게 쓰는데요, Tailwind CSS에서는 좀 더 간편하게 줄여서 다음과 같이 씁니다.
mr-10
헬퍼 유틸이라 줄임말이 많습니다.
그래서 처음에는 헷갈릴 수 있는데 계속 사용하다 보면 쉽게 이해할 수 있을 겁니다.
그럼 오늘은 NextJS를 이용해서 React에서 반응형 메뉴를 만들어 보겠습니다.
영어로는 Responsive Navbar Menu라고 하죠.
완성형을 한번 볼까요?
위 스크린샷은 큰 화면에서 보이는 메뉴이고,
위 스크린샷은 모바일용 즉, 작은 화면일 경우 보여지는 메뉴입니다.
요즘은 다들 이런걸 쓰고 있죠.
그럼 시작해 볼까요?
1. NextJS 템플릿 만들기 with Tailwind CSS
npx create-next-app -e with-tailwindcss nextjs-tailwind
이렇게 실행하면 nextjs-tailwind 라는 폴더에 tailwindcss 가 적용된 NextJS 템플릿 앱이 설치됩니다.
폴더로 들어가 볼까요?
cd nextjs-tailwind
ls -l
tailwind.config.js 가 기본 적용되어 있습니다.
그리고 postcss 에서 tailwindcss 를 적용시키고 있습니다.
그래서 NextJS앱에 TailwindCSS 를 적용할려고 노력할 필요가 없이 완성된 TailwindCSS + NextJS 앱이 완성된거죠.
그럼 본격적인 코딩에 들어가 볼까요?
우리는 한번 만들어 놓으면 계속 쓸 수 있는 컴포넌트를 만들기 원하죠.
그래서 components 폴더 밑에 Navbar.js 파일로 저장하겠습니다.
그리고 index.js 앱에 다음과 같이 Navbar를 불러오면 됩니다.
import Head from "next/head";
import Navbar from "../components/Navbar";
export default function Home() {
return (
<div>
<Head>
<title>Tailwind Navbar Tutorial</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<Navbar />
{/* content goes here */}
<div className="py-32 text-center">
<div className="text-4xl font-extrabold">Navbars in Tailwind!</div>
</div>
</div>
);
}
index.js 파일에는 Head 로 title을 지정했고
Navbar 를 로드 했고
그 밑에 본문을 넣었습니다.
본문은 div 태그로 py-32과 text-center 를 CSS class로 넣었습니다.
TailwindCSS 를 처음 보시는 건데요.
py-32는 padding Y axis 8rem 이란 뜻입니다.
그리고 text-center 는 text-align : center 란 뜻입니다.
패딩을 수직방향으로 py-32로 크게 주고 있고 텍스트는 중간에 위치한다는 얘기입니다.
그리고 text-4xl은
font-size: 2.25rem
line-height: 2.5rem
이란 뜻입니다.
xl은 extra-large 란 뜻이고 크기를 나타내는 단어입니다.
sm, md, lg, xl, 2xl, 4xl, 6xl 등이 있습니다.
font-extrabold는 font-weight: 800 이란 뜻입니다.
font를 굉장히 두껍게 하라는 뜻이죠.
TailwindCSS 를 맛보기로 좀 보셨는데요, 쉽게 추측할 수 있을 거 같죠.
Visual Studio Code에서 꼭 Tailwind CSS IntelliSense 를 설치하시기 바랍니다.
TailwindCSS 작업할 때 매우 쉽게 작업할 수 있고, 만약 해당 클래스가 있는지 없는지 intellisense를 통해 사전에 체크할 수 있어 코딩하기 꽤 편합니다.
일단 Navbar 컴포넌트를 주석처리 했을 때 보이는 화면입니다.
크기와 폰트가 꽤 마음에 드네요.
그럼 본격적으로 Navbar 컴포넌트를 만들어 보겠습니다.
2. /components/Navbar.js
import React from "react";
const Navbar = () => {
return (
<nav className="bg-gray-100">
<div className="max-w-6xl mx-auto px-4 border border-red-400">
<div className="flex justify-between">
{/* 메뉴 */}
<div>
<div>메뉴1</div>
<div>메뉴2</div>
</div>
{/* 메뉴2 */}
<div>sign</div>
</div>
</div>
</nav>
);
};
export default Navbar;
Navbar 는 전체적으로 nav 태그로 전체를 감싸고 있고,
그 안 에 다시 div 태그로 또 전체를 감싸고 있습니다.
nav 태그로 밖을 감싸는 이유는 이게 navbar란 뜻이죠.
이렇게 하는게 좋은 습관이라고 하더라구요.
두번째 div 클래스를 좀 살펴 볼까요?
className="max-w-6xl mx-auto px-4 border border-red-400"
TailwindCSS 헬퍼 유틸인데요.
max-w-6xl 은 max width 6 extra large 입니다.
최대 크기를 나타내는거죠.
그리고 mx-auto는 마진 왼쪽 오른쪽을 자동으로 설정하는 겁니다.
꽤 중요합니다.
그리고, 마지막 border 관련 두개의 클래스는 나중에 지울겁니다. 지금은 테스트 중이라 넣은겁니다.
그다음으로 우리의 메뉴는 2개의 div로 구성됩니다.
첫번째 div는 메뉴1과 메뉴2를 포함하고 있고 두번째 div 는 login, signup 부분입니다.
이렇게 전체적인 틀을 짜 놓고 작업하시는게 좋습니다.
그런데 메뉴 두개를 감싸는 div에 classname으로 flex, justify-between을 넣었습니다.
이렇게 하면 첫번째 div, 두번째 div가 수평으로 배열되고 또한 양 끝쪽으로 자연스럽게 배열됩니다.
만약 flex를 넣지 않으면 div 는 기본적으로 block 스타일이라 수평 width 모두를 차지하게 되고 수직으로 나타나게 될겁니다. 아래처럼요.
그럼 다시 flex, justify-between를 넣겠습니다.
자 이제, 왼쪽 메뉴 부분을 작업해 볼까요?
<div>
<div>
<a href="#" className="flex items-center py-5 px-2 text-gray-700">
<span className="font-bold">Home</span>
</a>
</div>
<div>
<a
href="#"
className="py-5 px-3 text-gray-700 hover:text-gray-900"
>
Features
</a>
<a
href="#"
className="py-5 px-3 text-gray-700 hover:text-gray-900"
>
Pricing
</a>
</div>
</div>
각각 메뉴1, 메뉴2에 a 링크를 넣었습니다.
먼저 메뉴1에는 Home 이란 링크를 넣었구요.
메뉴2에는 Features, Pricing 이란 a 링크를 넣었습니다.
그런데 Home 부분과 그다음 부분이 수직으로 배열되어 있네요.
네 맞습니다. div 태그는 display가 기본적으로 block이기 때문입니다.
div 같은 태그는 display : block 이고, p, a 태그 같은 경우는 display: inline 입니다.
디스플레이 block는 수평방향으로 width를 모두 쓰고,
디스플레이 inline은 해당 영역만 width를 씁니다.
그런데 display: flex 라고 하면 기본적으로 flex-direction: row 가 되어 block 인데 row 방향 즉, 엑셀에서 "열"이라고 하죠.
그래서 수평방향으로 배열하게 됩니다.
이 차이점을 꼭 기억해 두기 바랍니다.
그래서 이 두개의 메뉴를 감싸는 상위 div에 flex를 지정하면 됩니다.
아래 코드 첫줄을 보시면 됩니다.
<div className="flex space-x-4"> // 여기가 고친 부분입니다.
<div>
<a href="#" className="flex items-center py-5 px-2 text-gray-700">
<span className="font-bold">Home</span>
</a>
</div>
<div>
<a
href="#"
className="py-5 px-3 text-gray-700 hover:text-gray-900"
>
Features
</a>
<a
href="#"
className="py-5 px-3 text-gray-700 hover:text-gray-900"
>
Pricing
</a>
</div>
</div>
그런데 Home은 수직으로 가운데로 보이고 그다음 Features Pricing은 상단에 놓여졌네요.
왜 그럴까요?
바로 Home 을 감싸고 있는 Div 는 flex, items-center 항목이 있기 때문입니다.
두번째 메뉴부분도 같은걸 적용해 볼까요?
// 두번째 메뉴를 감싸는 div에도 flex, items-center, space-x-1을 적용했습니다.
<div className="flex items-center space-x-1">
<a
href="#"
className="py-5 px-3 text-gray-700 hover:text-gray-900"
>
Features
</a>
<a
href="#"
className="py-5 px-3 text-gray-700 hover:text-gray-900"
>
Pricing
</a>
</div>
계속 space-x-1 같은게 나오는데요. TailwindCSS의 헬퍼 유틸입니다. x는 수평방향 간격을 조절하는 거구요.
y는 수직방향 간격을 조절하는 겁니다.
굉장히 유용하니 계속 나올 겁니다.
이제 뭔가 메뉴같이 나오는데요.
Home 부분에 로고를 하나 넣을까 싶습니다.
TailwindCSS에서 추천하는 메뉴는 SVG 아이템을 이용한 다음 사이트 아이콘을 많이 추천합니다.
여기서 괜찮은 걸 골라 "Copy JSX"를 고르면 React 코드에 넣을 수 있는 코드를 바로 복사하여 붙혀넣을 수 있습니다.
첫번째 메뉴 코드입니다.
// a tag 밑에 svg 로 로그 그림을 넣었습니다.
<div>
<a href="#" className="flex items-center py-5 px-2 text-gray-700">
<svg
xmlns="http://www.w3.org/2000/svg"
// svg에도 CSS 클래스를 적용할 수 있습니다.
className="h-5 w-5 mr-2 text-blue-400"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M9.504 1.132a1 1 0 01.992 0l1.75 1a1 1 0 11-.992 1.736L10 3.152l-1.254.716a1 1 0 11-.992-1.736l1.75-1zM5.618 4.504a1 1 0 01-.372 1.364L5.016 6l.23.132a1 1 0 11-.992 1.736L4 7.723V8a1 1 0 01-2 0V6a.996.996 0 01.52-.878l1.734-.99a1 1 0 011.364.372zm8.764 0a1 1 0 011.364-.372l1.733.99A1.002 1.002 0 0118 6v2a1 1 0 11-2 0v-.277l-.254.145a1 1 0 11-.992-1.736l.23-.132-.23-.132a1 1 0 01-.372-1.364zm-7 4a1 1 0 011.364-.372L10 8.848l1.254-.716a1 1 0 11.992 1.736L11 10.58V12a1 1 0 11-2 0v-1.42l-1.246-.712a1 1 0 01-.372-1.364zM3 11a1 1 0 011 1v1.42l1.246.712a1 1 0 11-.992 1.736l-1.75-1A1 1 0 012 14v-2a1 1 0 011-1zm14 0a1 1 0 011 1v2a1 1 0 01-.504.868l-1.75 1a1 1 0 11-.992-1.736L16 13.42V12a1 1 0 011-1zm-9.618 5.504a1 1 0 011.364-.372l.254.145V16a1 1 0 112 0v.277l.254-.145a1 1 0 11.992 1.736l-1.735.992a.995.995 0 01-1.022 0l-1.735-.992a1 1 0 01-.372-1.364z"
clipRule="evenodd"
/>
</svg>
<span className="font-bold">Home</span>
</a>
</div>
SVG 벡터 아이콘은 굉장히 가벼운 아이콘입니다. 그리고 SVG도 HTML 태그이기 때문에 위 코드처럼 SVG에 class를 지정했습니다.
mr-5는 margin right 5 라는 뜻이고요.
text-blue-400은 텍스트 컬러를 뜻합니다.
3. 두번째 메뉴 구성하기
이제 두번째 메뉴쪽입니다.
{/* 메뉴2 */}
<div className="flex items-center space-x-1">
<a href="#" className="py-5 px-3">
Login
</a>
<a
href="#"
className="py-2 px-3 bg-yellow-400 hover:bg-yellow-300 text-yellow-900 hover:text-yellow-800 rounded transition duration-300"
>
Signup
</a>
</div>
두번째 메뉴를 보시면 앞에서 공부했던게 계속 반복해서 나오고 있어 이제는 뭔가 익숙한데요.
두번째 signup 링크를 볼까요?
bg-yelllow-400 이라고 백그라운드 컬러를 지정한겁니다.
그리고 hover:bg-yellow-300은 마우스 커서가 호버일때를 지정한거구요.
text-yellow-900과 hover-yellow-800도 같은 뜻입니다.
그리고 rounded 를 넣어 버튼 모서리를 둥글게 만들었구요.
transition duration-300을 넣어 hover 애니메이션을 조금 넣었습니다.
이제 완성 되었네요.
이제 맨 처음 넣었던 빨간색 border를 삭제하고 다시 볼까요?
멋진 Navbar가 완성되었습니다.
3. 반응형 메뉴 Navbar 만들기
이제 스마트폰에서 볼 수 있는 모바일용 반응형 Navbar를 만들기 위해 코드를 추가해야 되는데요.
스크린 사이즈를 줄여 볼까요?
폭이 좁은 모바일용에서는 메뉴가 너무 많습니다.
그래서 보통 모바일용은 햄버거 메뉴(≡)를 많이 쓰고요.
햄버거 메뉴를 클릭했을 때 세부 메뉴가 나타나는 식으로 만듭니다.
우리도 같은 방식으로 만들어 볼까요?
모바일용을 만들기 위해서 우리가 쓸 TailwindCSS 헬퍼 유틸은 바로 hidden 입니다.
hidden 은 CSS 코드가 바로 display: none 입니다.
즉 화면에 보여주지 말라는 뜻이죠.
그리고 TailWindCSS 가 제공하는 화면크기에 따른 브레이크 포인트를 이용할 건데요.
바로 sm, md, lg, xl, 2xl입니다.
// tailwind.config.js
module.exports = {
theme: {
screens: {
'sm': '640px',
// => @media (min-width: 640px) { ... }
'md': '768px',
// => @media (min-width: 768px) { ... }
'lg': '1024px',
// => @media (min-width: 1024px) { ... }
'xl': '1280px',
// => @media (min-width: 1280px) { ... }
'2xl': '1536px',
// => @media (min-width: 1536px) { ... }
}
}
}
TailwindCSS는 위 코드처럼 화면 크기에 따라서 기본적인 브레이크 포인트를 제공합니다.
그래서 최종적으로 우리가 사용할 코드는 바로 md 브레이크 포인트입니다.
그럼 기존 코드에서 모바일용 화면크기가 되었을 때 안 보여져야 하는 부분이 어디일까요?
바로 Home 빼고 모두 안 보여져야 합니다.
그래서 Feacture와 Pricing 을 묶은 div와, Login, Signup을 묶은 div에 지정되어 있는 flex 스타일을 다음과 같이 바꿔야 합니다.
<div className="hidden md:flex items-center space-x-1">
hidden 을 추가했고 그 다음에 md:flex 라고 추가했습니다.
무슨 뜻일까요?
hidden 앞에 sm,md,lg 등 브레이크 포인트가 없습니다.
이 뜻은 기본이란 뜻이고요. 그러니까 sm부터 시작한다는 뜻입니다.
그리고 두번째 md:flex라고 적은 부분은 바로 md 크기부터는 flex라는 뜻입니다.
종합적으로 해석해 보면 sm 크기일 때는 hidden 즉 ,display: none 이고,
md 크기부터는 flex 즉, display: flex입니다.
결과적으로 sm 크기일 경우 안보여지고 md 크기 이후에는 flex 로 보여진다는 얘기죠.
위 스크린샷은 브라우저 사이즈를 줄였을 때의 모습입니다.
역시 Feacture와 Pricing 을 묶은 div와, Login, Signup을 묶은 div가 사라졌습니다.
그럼, 오른쪽 끝에는 뭐가 나와야 할까요?
바로 햄버거 메뉴(≡)입니다.
햄버거 메뉴도 HeroIcons 사이트에서 추가합시다.
{/* 메뉴2 */}
<div className="hidden md:flex items-center space-x-1">
<a href="#" className="py-5 px-3">
Login
</a>
<a
href="#"
className="py-2 px-3 bg-yellow-400 hover:bg-yellow-300 text-yellow-900 hover:text-yellow-800 rounded transition duration-300"
>
Signup
</a>
</div>
{/* mobile menu */}
<div className="md:hidden flex items-center">
<button>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 6h16M4 12h16M4 18h16"
/>
</svg>
</button>
</div>
햄버거 메뉴(≡)를 위치시킬 코드상의 위치는 Signup 이 있는 div 아래이고 거기에 모바일용 메뉴를 위한 햄버거 메뉴(≡) div 코드를 추가합시다.
div 안에는 햄버거 메뉴가 있고 그 햄버거 메뉴를 버튼으로 감쌌습니다.
왜냐하면 나중에 button 을 눌렀을때 onClick을 적용하기 위해서죠.
여기서 왜 a 태그가 아닌 버튼 태그를 골랐을까요?
그 이유는 a 태그는 다른 곳으로 이동하는 뜻이고, button 은 현상태에서 뭔가를 한다는 뜻이라서 button으로 추가했습니다.
그리고 div 내용이 위에서 본 hidden 이랑 반대입니다.
<div className="md:hidden flex items-center">
즉, md 이상일 때는 hidden이고 그 밑으로는 flex라는 뜻입니다.
그래서 다음과 같이 보이게 됩니다.
자 그럼, 햄버거 메뉴(≡)를 눌렀을 때 나오는 메뉴를 넣어줘야 하는데요.
다음과 같은 곳에 넣어주시면 됩니다.
{/* mobile menu items */}
<div className={classNames("md:hidden", { hidden: !menuToggle })}>
<a href="#" className="block py-2 px-4 text-sm hover:bg-gray-200">
Pricing
</a>
<a href="#" className="block py-2 px-4 text-sm hover:bg-gray-200">
Features
</a>
</div>
</nav>
클로징 nav 태그인 </nav> 바로 위에 넣었습니다.
md:hidden 태그에 의해 sm일때만 보여집니다.
이제 완성된거 같은데요.
뭔가 문제가 있습니다.
햄버거 메뉴를 클릭했을 때 모바일 메뉴가 나타나고 사라지게 해야 합니다.
이렇게 할려면 자바스크립트를 써야하는데요.
우리는 React를 쓰고 있기 때문에 useState Hook을 이용하겠습니다.
그리고 classNames란 패키지를 쓸건데요. 다음과 같이 실행해서 설치해 주시기 바랍니다.
npm install classnames
먼저, useState 훅을 만들어 봅시다.
import React, { useState } from "react";
import classNames from "classnames";
const Navbar = () => {
const [menuToggle, setMenuToggle] = useState(false);
Navbar.js 파일의 맨 처음입니다.
menuToggle이란 State를 만들었고 기본값은 false입니다.
햄버거 메뉴를 눌렸냐 안 눌렸냐를 나타내는 State입니다.
그럼 이 코드를 햄버거 메뉴에 적용해 볼까요?
{/* mobile menu */}
<div className="md:hidden flex items-center">
<button
onClick={() => setMenuToggle(!menuToggle)}
>
{menuToggle ? (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M6 18L18 6M6 6l12 12"
/>
</svg>
) : (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 6h16M4 12h16M4 18h16"
/>
</svg>
)}
</button>
</div>
button onClick 이벤트에는 setMenuToggle을 이용해서 menuToggle State를 토글하고 있습니다.
그리고 menuToggle에 따라 햄버거 메뉴인지 X 메뉴인지를 보여주고 있습니다.
그럼, 이제 햄버거 메뉴를 클릭했을 때 아래에 있는 모바일 메뉴를 보였다가 사라지게 만드는 기능을 추가해 볼까요?
{/* mobile menu items */}
<div className={classNames("md:hidden", { hidden: !menuToggle })}>
<a href="#" className="block py-2 px-4 text-sm hover:bg-gray-200">
Pricing
</a>
<a href="#" className="block py-2 px-4 text-sm hover:bg-gray-200">
Features
</a>
</div>
아까 설치한 classNames 란 패키지입니다.
위 코드를 보시면 md:hidden 은 기본적으로 들어가 있고,
hidden 은 menuToggle이 반대일 때 적용된다는 뜻입니다.
그래서 최종적으로 다음과 같은 그림이 나오게 됩니다.
최종적으로 햄버거 메뉴 버튼과 X버튼을 누르면 모바일 메뉴가 보여지거나 사라지게 됩니다.
여기까지가 반응형 모바일 Navbar 만들기였습니다.
TailwindCSS 의 기능은 이 처럼 처음 배우기가 어렵지만 한번 익혀 놓으면 아주 강력한 도구가 될거 같습니다.
참고로 최종 코드입니다.
/components/Navbar.js
import React, { useState } from "react";
import classNames from "classnames";
const Navbar = () => {
const [menuToggle, setMenuToggle] = useState(false);
return (
<nav className="bg-gray-100">
<div className="max-w-6xl mx-auto px-4">
<div className="flex justify-between">
{/* 메뉴 */}
<div className="flex space-x-4">
<div>
<a href="#" className="flex items-center py-5 px-2 text-gray-700">
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5 mr-2 text-blue-400"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M9.504 1.132a1 1 0 01.992 0l1.75 1a1 1 0 11-.992 1.736L10 3.152l-1.254.716a1 1 0 11-.992-1.736l1.75-1zM5.618 4.504a1 1 0 01-.372 1.364L5.016 6l.23.132a1 1 0 11-.992 1.736L4 7.723V8a1 1 0 01-2 0V6a.996.996 0 01.52-.878l1.734-.99a1 1 0 011.364.372zm8.764 0a1 1 0 011.364-.372l1.733.99A1.002 1.002 0 0118 6v2a1 1 0 11-2 0v-.277l-.254.145a1 1 0 11-.992-1.736l.23-.132-.23-.132a1 1 0 01-.372-1.364zm-7 4a1 1 0 011.364-.372L10 8.848l1.254-.716a1 1 0 11.992 1.736L11 10.58V12a1 1 0 11-2 0v-1.42l-1.246-.712a1 1 0 01-.372-1.364zM3 11a1 1 0 011 1v1.42l1.246.712a1 1 0 11-.992 1.736l-1.75-1A1 1 0 012 14v-2a1 1 0 011-1zm14 0a1 1 0 011 1v2a1 1 0 01-.504.868l-1.75 1a1 1 0 11-.992-1.736L16 13.42V12a1 1 0 011-1zm-9.618 5.504a1 1 0 011.364-.372l.254.145V16a1 1 0 112 0v.277l.254-.145a1 1 0 11.992 1.736l-1.735.992a.995.995 0 01-1.022 0l-1.735-.992a1 1 0 01-.372-1.364z"
clipRule="evenodd"
/>
</svg>
<span className="font-bold">Home</span>
</a>
</div>
<div className="hidden md:flex items-center space-x-1">
<a
href="#"
className="py-5 px-3 text-gray-700 hover:text-gray-900"
>
Features
</a>
<a
href="#"
className="py-5 px-3 text-gray-700 hover:text-gray-900"
>
Pricing
</a>
</div>
</div>
{/* 메뉴2 */}
<div className="hidden md:flex items-center space-x-1">
<a href="#" className="py-5 px-3">
Login
</a>
<a
href="#"
className="py-2 px-3 bg-yellow-400 hover:bg-yellow-300 text-yellow-900 hover:text-yellow-800 rounded transition duration-300"
>
Signup
</a>
</div>
{/* mobile menu */}
<div className="md:hidden flex items-center">
<button onClick={() => setMenuToggle(!menuToggle)}>
{menuToggle ? (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M6 18L18 6M6 6l12 12"
/>
</svg>
) : (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 6h16M4 12h16M4 18h16"
/>
</svg>
)}
</button>
</div>
</div>
</div>
{/* mobile menu items */}
<div className={classNames("md:hidden", { hidden: !menuToggle })}>
<a href="#" className="block py-2 px-4 text-sm hover:bg-gray-200">
Pricing
</a>
<a href="#" className="block py-2 px-4 text-sm hover:bg-gray-200">
Features
</a>
</div>
</nav>
);
};
export default Navbar;
'코딩 > React' 카테고리의 다른 글
TailwindCSS 강좌 3편 - Card 만들기 (6) | 2021.10.16 |
---|---|
Tailwind CSS 강좌 2편 - 반응형 Sidebar Navbar 만들기 (0) | 2021.10.13 |
NextJS Prisma DB로 블로그 시스템 만들기 2편 (0) | 2021.10.08 |
NextJS Prisma DB로 블로그 시스템 만들기 (1) | 2021.10.06 |
카카오 네이버 구글 커스텀 로그인 화면 만들기 NextAuth React Next (0) | 2021.10.05 |