$ npm install styled-components
// /src/styled.ts
import styled, { css } from 'styled-components'
const Width = css`
width: 100%;
`
export const Icon = styled.img`
width: 200px;
`
export const P = styled.p`
color: #848187;
text-align: center;
${Width};
`
export const Label = styled.label`
color: #e1c6f7;
${Width};
`
사용하려는 컴포넌트들을 모두 export 하고, 사용하려는 .tsx
파일에서 import * as S from './Styled'
로 import 하면 컴포넌트 앞에 S.
만 붙여서 사용할 수 있다.
// /src/App.tsx
import * as S from './Styled'
export default function App() {
return (
<div>
<S.Icon src='' />
<S.P>
회원이 아니신가요? <S.a>회원가입 하기</S.a>
</S.P>
<S.Label>
이메일
<input placeholder='study@code.com' />
</S.Label>
<S.Label>
비밀번호
<input placeholder='비밀번호' />
</S.Label>
</div>
)
}
Nesting : CSS 규칙 안에서 CSS 규칙을 만드는 것
⇨ :& 선택자, ${ 컴포넌트 } 선택자 를 사용해서 표현 가능
styled.button``
안에 &:hover{ }
, &:active{ }
, &::placeholder{}
등을 작성한다
import styled from 'styled-components';
const Button = styled.button`
background-color: #6750a4;
border: none;
color: #ffffff;
padding: 16px;
&:hover,
&:active {
background-color: #463770;
}
`;
import styled from 'styled-components';
const Icon = styled.img`
width: 16px;
height: 16px;
`;
const StyledButton = styled.button`
background-color: #6750a4;
border: none;
color: #ffffff;
padding: 16px;
& ${Icon} {
margin-right: 4px;
}
&:hover,
&:active {
background-color: #463770;
}
`;
function Button({ children, ...buttonProps }) {
return (
<StyledButton {...buttonProps}>
<Icon src={nailImg} alt="nail icon" />
{children}
</StyledButton>
);
}
export default Button;
<StyledButton />
컴포넌트 안의 <Icon />
에만 margin-right 적용
&
생략 가능
${ } 안에 함수형으로 쓰면서 파라미터로 컴포넌트의 props 를 넘겨받을 수 있다
const SIZES = {
large: 24,
medium: 20,
small: 16
};
const Button = styled.button<{size: number, round?: boolean}>`
font-size: ${({size}) => SIZES[size]}px;
${({ round }) => round && `border-radius: 9999px;`}
`;
const export function MyBtn(){
return (
<>
<Button size={20}>My Button</Button>
<Button size={20} round={true}>My Button</Button>
</>
}
import styled from 'styled-components'
const Input = styled.input<{ error?: boolean }>`
border-bottom: 2px solid ${({ error }) => (error ? `#f44336` : `#eeeeee`)};
background-color: ${({ theme }) => theme.backgroundColor};
color: ${({ theme }) => theme.color};
/* error가 있고 focus 됐을 때 적용 */
${({ error }) => !error && `
&:focus {
border-bottom: 2px solid #7760b4;
}
`};
&::placeholder {
color: #c4c5cd;
}
`
export default Input
Styled Components로 만들어진 컴포넌트를 상속하려면 styled() 함수를 사용하면 된다.
import styled from 'styled-components';
const Button = styled.button`
background-color: #6750a4;
border: none;
color: #ffffff;
padding: 16px;
`;
const SubmitButton = styled(Button)`
background-color: #de117d;
display: block;
margin: 0 auto;
width: 200px;
&:hover {
background-color: #f5070f;
}
`;
Styled Components는 내부적으로 className을 따로 생성하고, 자체적으로 생성된 className이 있는 부분에 styled() 함수의 스타일이 입혀진다.
그런데, JSX 문법으로 직접 만든 컴포넌트는 styled() 함수가 적용될 className에 대한 정보가 없어, 스타일이 적용되지 않는다.
따라서, Styled Components를 사용하지 않고 직접 만든 컴포넌트는 className 값을 Prop으로 따로 내려줘야 styled() 함수를 사용할 수 있다.
// TermsOfService.tsx
function TermsOfService({ className }) {
return (
<div className={className}>
...
</div>
);
}
import styled from 'styled-components';
import TermsOfService from './TermsOfService';
function App() {
return (
<div>
<StyledTermsOfService />
<SubmitButton className={'submitBtn'}>계속하기</SubmitButton>
</div>
);
}
export default App;
const StyledTermsOfService = styled(TermsOfService)`
background-color: #ededed;
border-radius: 8px;
padding: 16px;
margin: 40px auto;
width: 400px;
`;
직접 만든 컴포넌트에 className Prop을 따로 내려주는 건 syled() 함수가 적용될 부분의 className을 별도로 정해주는 것
<div>
태그에 className을 내려줬기 때문에 styled(TermsOfService)에서 작성한 코드는 TermsOfService 안에 있는 <div>
태그에 적용된다.
스타일 상속을 하려면 styled() 함수를 사용하면 되는데, styled.tagname으로 만든 컴포넌트는 styled() 함수로 바로 상속하면 되고, Styled Components를 사용하지 않고 직접 만든 컴포넌트에는 클래스 이름
을 내려준 후에 styled() 함수로 상속하면 된다
중복되는 CSS 코드들을 변수처럼 저장해서 여러 번 다시 사용
import styled, { css } from 'styled-components';
const SIZES = {
large: 24,
medium: 20,
small: 16
};
const fontSize = css`
font-size: ${({ size }) => SIZES[size] ?? SIZES['medium']}px;
`;
const Button = styled.button`
...
${fontSize}
`;
const Input = styled.input`
...
${fontSize}
`;
함수를 삽입하지 않는 단순한 문자열이라면 일반적인 템플릿 리터럴도 가능하지만, css 함수를 사용하도록 습관화하는 것이 좋다.
const boxShadow = `
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
`;
const boxShadow = css`
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
`;