아래 포스팅 참고
Tailwind + Styled Component 1. 세팅하기 (CRA)
Tailwind와 Styled-components가 결함된 문법을 살펴보기 전에, Styled-components의 문법을 살펴보자.
import styled from 'styled-components';
const 스타일드컴포넌트이름 = styled.태그명`
css스타일명 : css스타일 값;
`
// styled-components를 import한다.
import styled from 'styled-components';
// 스타일 컴포넌트를 사용하여 <h1>태그를 렌더링하는 Title 컴포넌트 생성
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
// 스타일 컴포넌트를 사용하여 <section> 태그를 렌더링하는 Wrapper 컴포넌트 생성
const Wrapper = styled.section`
padding: 4em;
background: papayawhip;
`;
// 일반 컴포넌트 사용하는 것과 동일하게 스타일 컴포넌트 사용 (다만, 스타일링 되어있음)
render(
<Wrapper>
<Title>
Hello World!
</Title>
</Wrapper>
);
import styled from 'styled-components'
const Button = styled.button`
font: inherit;
padding: 0.5rem 1.5rem;
border: 1px solid #8b005d;
color: white;
background: #8b005d;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.26);
cursor: pointer;
&:focus {
outline: none;
}
&:hover,
&:active {
background: #ac0e77;
border-color: #ac0e77;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.26);
}
`
1번 ~ 3번은 내가 직접 twin.macro를 사용하며 적응한 유용한 문법들을 정리했다.
생성된 컴포넌트의 하위 요소까지 스타일링 할 수 있는 방법이다. 제일 유용한 방법.
import tw from 'twin.macro'
const Wrapper = tw.div`
flex w-full ...
& {
//...
}
`
tw를 사용하면 &이 작동하지 않는다.
import tw, { styled } from 'twin.macro'
const Wrapper = styled.div`
${tw`flex w-full ...`}
& {
//...
}
`
styled를 사용하면 &이 잘 작동한다!!!!
import tw, { styled, css, theme } from 'twin.macro'
const Input = styled.div`
${css`
-webkit-tap-highlight-color: transparent; /* add css styles */
background-color: ${theme`colors.red.500`}; /* add values from your tailwind config */
${tw`text-blue-500 border-2`}; /* tailwind classes */
&::selection {
${tw`text-purple-500`}; /* style custom css selectors with tailwind classes */
}
`}
`
const Component = () => <Input />
꼭 템플릿 리터럴(${})안에 tw를 쓰고 백틱안에 Tailwind 유틸리티 클래스를 작성해야한다.
단점은 tailwind 자동완성이 안된다!!! ㅠㅠㅠ
자동완성 기능을 사용하고 싶다면 JSX 구문에 className으로 Tailwind를 작성하여 자동완성 기능을 활용한 뒤, Styled component로 옮기는 방법이 있다.
import tw, { styled } from 'twin.macro';
const Btn = styled.div`
${tw`w-full rounded-full flex justify-center items-center h-6`}
${props =>
props.disabled ? tw`bg-grey1 text-grey2` : tw`bg-primary text-white`}
& {
span {
${tw`text-main-bold`}
}
}
`;
function FormSubmitBtn({ disabled, onClick, title }) {
return (
<Btn disabled={disabled} onClick={onClick}>
<span>{title ? title : '다음'}</span>
</Btn>
);
}
템플릿 리터럴 (${}) 안에 props을 사용할 수 있다.
twin.macro의 css를 임포트하여 사용하면 props를 활용하여 CSS 구문 그대로 작성가능하다.
굉장히 유용함
import tw, { styled, css } from 'twin.macro';
const Btn = styled.div`
${props => css`background-image: url(${img});`}
`
Function Button({ img }) {
return (
<Btn img={img}/>
);
}
4번부터는 깃헙 공식문서 그대로 번역하여 정리함
twin.macro를 컴포넌트 파일 상단에 import한다.
import tw from 'twin.macro'
템플릿 리터럴 구문안에 Tailwind CSS의 클래스를 작성하여 스타일을 입힌다.
const Wrapper = tw.section`flex w-full`
const Column = tw.div`w-1/2`
함수형 컴포넌트가 반환하는 JSX코드에 일반 컴포넌트를 사용하는 것과 마찬가지로 태그 안에 넣어 사용한다.
const Component = () => (
// 3. 생성한 컴포넌트를 JSX 코드에 사용
<Wrapper>
<Column></Column>
<Column></Column>
</Wrapper>
)
// 1. twin.macro를 import 한다.
import tw from 'twin.macro'
// 2. 'tw.tagname`tailwind css`
const Wrapper = tw.section`flex w-full`
const Column = tw.div`w-1/2`
const Component = () => (
// 3. 생성한 컴포넌트를 JSX 코드에 사용
<Wrapper>
<Column></Column>
<Column></Column>
</Wrapper>
)
styled를 사용하여 적용하고자 하는 스타일들을 배열에 담는다.
tw와 styled를 컴포넌트 파일 상단에 import한다.
import tw, { styled } from 'twin.macro'
const Component = ({ hasBg }) => (
<Container {...{ hasBg }}>
<Column></Column>
<Column></Column>
</Container>
)
위 코드에서 hasBg라는 prop을 받아 Container라는 컴포넌트에 전달하고 있다.
const Container = styled.div(({ hasBg }) => [
tw`flex w-full`, // 기본적으로 적용될 스타일을 먼저 작성한다.
hasBg && tw`bg-black`, // 조건에 따라 추가될 스타일을 뒤에 작성한다.
])
위 코드에서 단축평가를 통해 hasBg
가 True일 경우 tw
bg-black`` 클래스가 적용되고 있다.
import tw, { styled } from 'twin.macro'
const Container = styled.div(({ hasBg }) => [
tw`flex w-full`, // Add base styles first
hasBg && tw`bg-black`, // Then add conditional styles
])
const Column = tw.div`w-1/2`
const Component = ({ hasBg }) => (
<Container {...{ hasBg }}>
<Column></Column>
<Column></Column>
</Container>
)
여러 변수에 스타일을 저장해놓고 사용하는 방식
const containerVariants = {
light: tw`bg-white text-black`,
dark: tw`bg-black text-white`,
crazy: tw`bg-yellow-500 text-red-500`,
}
객체에 변수에 따른 스타일을 정의하고 있다.
// 함수를 반환하고 있음
const Container = styled.section(() => [
tw`flex w-full`,
({ variant = 'dark' }) => containerVariants[variant],
])
styled의 메서드는 함수를 반환하고 있다. 함수는 여러 스타일을 담은 배열을 반환하고 있으며, prop으로 전달받은 변수 값을 통해 객체에 담긴 스타일을 선택하고 있다.
const Component = () => (
<Container variant="light">
<Column></Column>
<Column></Column>
</Container>
)
Container라는 컴포넌트에 variant라는 prop을 보내고 있으며 그 값은 “light”이다. 이 값에 따라 containerVariants에 정의된 스타일을 선택한다.
import tw, { styled } from 'twin.macro'
const containerVariants = {
// Named class sets
light: tw`bg-white text-black`,
dark: tw`bg-black text-white`,
crazy: tw`bg-yellow-500 text-red-500`,
}
const Container = styled.section(() => [
// Return a function here
tw`flex w-full`,
({ variant = 'dark' }) => containerVariants[variant], // Grab the variant style via a prop
])
const Column = tw.div`w-1/2`
const Component = () => (
<Container variant="light">
<Column></Column>
<Column></Column>
</Container>
)
이전에 만든 컴포넌트를 확장하여 스타일을 복사 혹은 삭제할 수 있다.
const Container = tw.div`bg-black text-white`
// Container 컴포넌트를 확장하여 기존 스타일에 'bg-blue-500'가 오버라이드 됨
const BlueContainer = tw(Container)`bg-blue-500`
// 조건을 추가하여 확장도 가능하다.
const RedContainer = styled(Container)(({ hasBorder }) => [
tw`bg-red-500 text-black`,
hasBorder && tw`border`,
])
const BlueContainerBold = tw(BlueContainer)`font-bold`
2번 이상 확장하여 사용하는 것은 권장하지 않는다.
import tw, { styled } from 'twin.macro'
const Container = tw.div`bg-black text-white`
// Container 컴포넌트를 확장하여 기존 스타일에 'bg-blue-500'가 오버라이드 됨
const BlueContainer = tw(Container)`bg-blue-500`
// 조건을 추가하여 확장도 가능하다.
const RedContainer = styled(Container)(({ hasBorder }) => [
tw`bg-red-500 text-black`,
hasBorder && tw`border`,
])
const Component = () => (
<>
<Container />
<BlueContainer />
<RedContainer hasBorder />
</>
)
기존에 생성한 컴포넌트를 다른 요소(h1, h2, div, a, section 등의 태그)로 재사용할 수 있다.
import tw from 'twin.macro'
const Heading = tw.h1`font-bold`
const Component = () => (
<>
<Heading>I am a H1</Heading>
<Heading as="h2">I am a H2 with the same style</Heading>
</>
)
h1으로 생성한 Heading 컴포넌트가 h2태그로 재사용되고 있다.
다음 글도 부탁드릴게요 개발자님!