const AppButton = styld.button`
background: transparent;
color: #0a6cff;
`
const Para = styled.p`
margin-bottom: 10px;
background-color: #3d5afe;
font-size: 1rem;
`;
<AppButton theme={**{ primary: "#f10e60" }**}> ... </AppButton>
styled.button`
background: **${ ({theme}) => theme.primary }**;
`
npm i -D styled-components
React 프로젝트에서 styled-components 모듈에서 styled 를 불러온 후, HTML 표준 컴포넌트 이름을 추가하고 `` 백틱 기호로 감싸서 css 코드를 작성하면 된다
**import styled from 'styled-components';**
const SectionHeader = **styled.h2`
color: #06f;
font-size: 1.45rem;
`;**
같이 쓰면 좋은 플러그인
babel-plugin-styled-components
→ 클래스 이름 읽기 쉬워지게 되어서 디버깅이 용이하다 , 번들 크기도 더 작아짐
npm i -D babel-plugin-styled-components
import styled from 'styled-components';
const Button = styled.button`
color: **${ props => props.reject ? '#f60' : '#06f' }**;
`;
export default Button;
<Button reject>취소</Button> // color: #f60
<Button>취소</Button> // color: #06f
import styled from 'styled-components';
**import Button from './Button';**
// AppButton 확장
export const FillButton = **styled(Button)**`
border: 0;
padding: 0.45em 0.95em 0.6em;
background-color: ${ props => props.reject ? '#026' : '#06f' };
color: ${ props => props.reject ? '#09f' : '#fff' };
font-weight: 600;
`;
import styled from 'styled-components';
export const InputStyled = styled.div`
input[type='checkbox'] {
display: none;
}
input[type='checkbox'] + label {
height: 30px;
display: inline-block;
cursor: pointer;
padding-left: 30px;
line-height: 24px;
background-repeat: no-repeat;
background-image: url('https://platform-site.yanolja.com/icons/checkbox-unselected.svg?inline');
}
input[type='checkbox']:checked + label {
background-image: url('https://platform-site.yanolja.com/icons/checkbox-selected.svg?inline');
}
`;
export const WrapperInput = styled(InputStyled)`
border: 1px solid #e6e6e6;
padding: 25px;
display: flex;
justify-content: space-between;
button {
cursor: pointer;
}
`;
}
// 스타일 컴포넌트
const Container = styled.div`
display: flex;
align-items: center;
justify-content: center;
font: 14px/1 Verdana;
color: ${({ primary }) => primary ?? 'hsla(220, 99%, 50%, 0.89)'};
`;
// 컴포넌트
const Counter = ({ primary }) => (
<Container primary={primary}>{/* ... */}</Container>
);
export default Counter;
const Container = styled.div`
**output** {
user-select: none;
font-size: 40px;
}
`;
<Container>
**<output> 9 </output>**
</Container>
const ControlButton = styled.button`
**:hover, :focus {**
color: #036;
font-weight: 400;
**}**
**:focus {**
outline: none;
**}**
**:disabled {**
filter:grayscale(100%);
cursor: not-allowed;
color: #909090;
font-weight: 300;
**}**
`;
const ControlButton = styled.button`
**&.increase** {
**&::before** {
content: '📤';
}
****}
`
import styled, { css } from 'styled-components';
// CSS 믹스인
const boxMixin = css`
margin: 20px 10px;
border: 0;
padding: 1em;
font-size: 15px;
font-weight: bold;
line-height: 1.7;
color: #fff;
`;
// Box 컴포넌트 ⬅ CSS 믹스인
const Box = styled.div`
**${ boxMixin };**
background: #07f;
`;
// ShadowBox 컴포넌트 ⬅ CSS 믹스인
const ShadowBox = styled.div`
**${ boxMixin };**
background: #41b883;
box-shadow: 0 6px 8px 1px rgba(0,100,30,0.35)
`;
**import 'styled-components/macro';**
<Button **css="padding: 0.5em 1em;"** />
// 위코드를 바벨을 이용하면 이런 형태로 컴파일 해준다
const StyledButton = styled(Button)`
padding: 0.5em 1em;
`
import styled, { **keyframes** } from 'styled-components';
const rotateKeyframes = **keyframes`
0% { transform: translateY(0) }
25% { transform: translateY(-20px) rotate(20deg) }
50% { transform: translateY(10px) }
75% { transform: translateY(-15px) rotate(-20deg) }
100% { transform: translateY(0) }
`;**
// 마법 모자 animation 속성에 rotate 값 설정
const MagicHat = styled.div`
font-size: 100px;
animation: **${rotateKeyframes}** 3s infinite cubic-bezier(0.35, 0.29, 0.4, 0.8);
`;
import { **createGlobalStyle** } from 'styled-components';
const GlobalStyle = **createGlobalStyle`
body {
margin: 0;
font: 1rem/1.5 "Spoqa Han Sans", Sans-Serif;
background: ${ ({darken}) => darken ? '#162442' : '#dee1e6' }
color: ${ ({darken}) => darken ? '#dee1e6' : '#162442' }
}
a img {
border: 0;
}
`;**
React 와 사용하려면 @emotion/react 패키지를 설치해야한다
@emotion/ react의 특징
css prop 지원
style-component, 요소 스타일을 직접 설정 가능
ssr(서버 사이드 렌더링 지원)
테마(theme ) 지원
eslint 지원
npm i -D @emotion/react
styled
React 컴포넌트를 사용하려면 @emotion/styled 패키지를 설치합니다.
npm i -D @emotion/styled
작성하는 방법
import styled from '@emotion/styled';
const Button = styled.button`
color: hotpink;
`;
render(<Button>핫핑크 버튼</Button>);
Babel 플러그인을 설치하면 스타일 압축/최적화 하고, 소스맵을 제공하는 보다 나은 개발자 경험을 제공합니다.
npm i -D @emotion/babel-plugin
.babelrc 파일의 플러그인을 구성한다
{
"plugins": ["@emotion", ...다른플러그인]
}
1)Babel preset
2) JSX Pragma
/** @jsx jsx */
import { jsx } from '@emotion/react';
/** @jsx jsx */
import { jsx } from '@emotion/react';
render(
<div
**css={{
backgroundColor: 'hotpink',
'&:hover': {
color: 'lightpink'
}
}}**
>
핫핑크 배경색
</div>
)
/** @jsx jsx */
import { **css**, jsx } from '@emotion/react';
const color = 'lightpink';
render(
<div
**css={css`
background-color: hotpink;
&:hover {
color: ${color};
}
`}**
>
핫핑크 배경색
</div>
)
/** @jsx jsx */
import { jsx } from '@emotion/react';
const P = props => (
<p
css={{
margin: 0,
fontSize: 12,
lineHeight: 1.5,
fontFamily: 'sans-serif',
color: 'black'
}}
{...props} // <- props 객체는 `className` prop을 포함
/>
);
const ArticleText = props => (
<P
css={{
fontSize: 14,
fontFamily: 'Georgia, serif',
color: 'darkgray'
}}
{...props} // <- props 객체는 `className` prop을 포함
/>
);
const SmallArticleText = props => (
<ArticleText
css={{
fontSize: 10
}}
{...props} // <- props 객체는 `className` prop을 포함
/>
);
import { jsx, **ThemeProvider** } from '@emotion/react';
const theme = {
colors: {
primary: 'hotpink'
}
}
render(
**<ThemeProvider theme={theme}>**
<div css={**theme** => ({ color: **theme.colors.primary** })}>
테마 설정을 토대로 색상 표시
</div>
**</ThemeProvider>**
)
styled
/** @jsx jsx */
import { jsx, **ThemeProvider** } from '@emotion/react';
import styled from '@emotion/styled';
const theme = {
colors: {
primary: 'hotpink'
}
};
const SomeText = styled.div`
color: **${props => props.theme.colors.primary};**
`;
render(
**<ThemeProvider theme={theme}>**
<SomeText>테마 설정을 토대로 색상 표시</SomeText>
**</ThemeProvider>**
);
useThema
/** @jsx jsx */
import { jsx, ThemeProvider, **useTheme** } from '@emotion/react'
const theme = {
colors: {
primary: 'hotpink'
}
};
function SomeText (props) {
**const theme = useTheme();**
return (
<div
css={{ color: **theme.colors.primary** }}
{...props}
/>
)
};
render(
<ThemeProvider theme={theme}>
<SomeText>테마 설정을 토대로 색상 표시</SomeText>
</ThemeProvider>
);
React 컴포넌트 또는 클래스에 선택자를 중첩해 사용하는 방법은 유용하게 쓰인다
/** @jsx jsx */
import { jsx, css } from '@emotion/react';
const paragraph = css`
color: black;
a {
border-bottom: 1px solid currentColor;
cursor: pointer;
}
`;
render(
<p css={paragraph}>
중첩된 요소를 손쉽게 스타일링 할 수 있습니다.
<a>아래 방향에 테두리가 그려진 링크</a>
</p>
);
import { jsx, css } from '@emotion/react'
const paragraph = css`
color: black;
**header &** {
color: green;
}
`
render(
<div>
**<header>
<p css={paragraph}>**
헤더 내부에 위치한 단락은 녹색 글자로 표현됩니다.
**</p>
</header>**
<p css={paragraph}>
이 단락은 헤더에 포함되지 않았으므로 검정색 글자로 표현됩니다.
</p>
</div>
)