bookshelf/INSTRUCTIONS.md at exercises/02-styles · kentcdodds/bookshelf (github.com)
Background
CSS-in-JS 더 알아보기
CSS-in-JS를 사용하면 다음과 같은 것이 가능하다.
- "스타일을 전달하는" 컴포넌트 만들기.
- 컴포넌트에 스타일 적용하기.
Making a styled component with emotion
가장 기본적인 방법
import styled from '@emotion/styled'
const Button = styled.button`
color: turquoise;
`
오브젝트 스타일로 만들기 (kent는 이 방법을 더 좋아한다 함.)
왜 이 방법이 더 좋을까? 함수 적용부터 보면 와닿을 것이다.
(객체 내(코드)에서 함수 적용하기 vs string interpolation 무한 중복하기)
const Button = styled.button({
color: 'turquoise',
})
props를 이용하여 함수 적용도 가능
const Box = styled.div(props => {
return {
height: props.variant === 'tall' ? 150 : 80,
}
})
// or with the string form:
const Box = styled.div`
height: ${props => (props.variant === 'tall' ? '150px' : '80px')};
`
// then you can do:
// <Box >
Using emotion's css prop
styled-component는 코드 재사용시 정말 유리함.
일회용으로 쓸 경우는 불편함. Wrapper나 Container를 막 만들게 됨.
emotion을 사용하면 해당 컴포넌트에 css를 주입할 수 있음.
컴포넌트를 만들 때에는 html만 고려하고, css는 주입하라!
기본적인 css prop 활용법은 다음과 같음.
1. 파일 상단에 해당 라인 추가
/** @jsx jsx */
import {jsx} from '@emotion/core'
import * as React from 'react'
2. 이모션의 css prop을 아래와 같이 사용 가능
// 오브젝트 스타일
function SomeComponent() {
return (
<div
css={{
backgroundColor: 'hotpink',
'&:hover': {
color: 'lightgreen',
},
}}
>
This has a hotpink background.
</div>
)
}
// or with string syntax:
function SomeOtherComponent() {
const color = 'darkgreen'
return (
<div
css={css`
background-color: hotpink;
&:hover {
color: ${color};
}
`}
>
This has a hotpink background.
</div>
)
}
이모션은 커스텀 jsx 함수로 위의 결과를 아래와 같은 컴포넌트로 컴파일함.
function SomeComponent() {
return <div className="css-bp9m3j">This has a hotpink background.</div>
}
실습
스타일드 컴포넌트 만들어보기
src/components/lib.final.js
import styled from '@emotion/styled'
import {Dialog as ReachDialog} from '@reach/dialog'
const buttonVariants = {
primary: {
background: '#3f51b5',
color: 'white',
},
secondary: {
background: '#f1f2f7',
color: '#434449',
},
}
// 첫번째 style객체와, 두번째 함수 호출 리턴 style 객체를 합쳐준다.
const Button = styled.button(
{
padding: '10px 15px',
border: '0',
lineHeight: '1',
borderRadius: '3px',
},
({variant = 'primary'}) => buttonVariants[variant],
)
const Input = styled.input({
borderRadius: '3px',
border: '1px solid #f1f1f4',
background: '#f1f2f7',
padding: '8px 12px',
})
const CircleButton = styled.button({
borderRadius: '30px',
padding: '0',
width: '40px',
height: '40px',
lineHeight: '1',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: 'white',
color: '#434449',
border: `1px solid #f1f1f4`,
cursor: 'pointer',
})
const Dialog = styled(ReachDialog)({
maxWidth: '450px',
borderRadius: '3px',
paddingBottom: '3.5em',
boxShadow: '0 10px 30px -5px rgba(0, 0, 0, 0.2)',
margin: '20vh auto',
'@media (max-width: 991px)': {
width: '100%',
margin: '10vh auto',
},
})
const FormGroup = styled.div({
display: 'flex',
flexDirection: 'column',
})
export {Button, Input, CircleButton, Dialog, FormGroup}
Emotion Macro로 React Devtools 강화
매크로는 바벨 플러그인이 설정 안해도 자동으로 지원해주는 코드 변환 기능.
데브툴에서 emotion styled component를 사용하면 기본적으로 아래와 같이, html elemet로 표기
import를 아래와 같이 바꿔준다.
import styled from '@emotion/styled/macro'
📜 Learn more about macros:
컬러와 미디어 쿼리 적용하기
아래와 같은 방법으로 테마를 한번에 바꾸는 방법도 있음.
UI 표준이 정해져 있다면 해당 방식을 사용하는 것도 좋아 보임.
실습에서는 개별적으로 스타일을 바꿔본다.
https://emotion.sh/docs/theming
src/styles/colors.js
export const base = 'white'
export const text = '#434449'
export const gray = '#f1f2f7'
export const gray10 = '#f1f1f4'
export const gray20 = '#e4e5e9'
export const gray80 = '#6f7077'
export const indigo = '#3f51b5'
export const indigoDarken10 = '#364495'
export const indigoLighten80 = '#b7c1f8'
export const yellow = '#ffc107'
export const green = '#4caf50'
export const danger = '#ef5350'
export const orange = 'orange'
src/styles/media-queries.js
export const large = '@media (min-width: 1200px)'
export const medium = '@media (min-width: 992px) and (max-width: 1199px)'
export const small = '@media (max-width: 991px)'
가져다 쓰기
import * as colors from 'styles/colors'
import * as mq from 'styles/media-queries'
import {Dialog as ReachDialog} from '@reach/dialog'
// 인풋 - 색상
const Input = styled.input({
borderRadius: '3px',
border: `1px solid ${colors.gray10}`,
background: colors.gray,
padding: '8px 12px',
})
// 모달 대화창 - 미디어 쿼리
const Dialog = styled(ReachDialog)({
maxWidth: '450px',
borderRadius: '3px',
paddingBottom: '3.5em',
boxShadow: '0 10px 30px -5px rgba(0, 0, 0, 0.2)',
margin: '20vh auto',
[mq.small]: {
width: '100%',
margin: '10vh auto',
},
})
스피너 만들기 (keyframe, animation)
aria-label이 있어야 화면이 보이지 않는 사람들도 웹을 이용할 수 있음.
import styled from '@emotion/styled/macro'
import {keyframes} from '@emotion/core'
import {FaSpinner} from 'react-icons/fa'
const spin = keyframes({
'0%': {transform: 'rotate(0deg)'},
'100%': {transform: 'rotate(360deg)'},
})
const Spinner = styled(FaSpinner)({
animation: `${spin} 1s linear infinite`,
})
Spinner.defaultProps = {
'aria-label': 'loading',
}
Keyframe Animation Syntax | CSS-Tricks - CSS-Tricks
emotion 더 많이 알아보기
https://emotion.sh/docs/styled
jsx pragma 안쓰는 방법 참고 (아래 요소) - CRA는 안됨. craco같은거 찾아봐야할듯.
/** @jsx jsx */
📜 https://emotion.sh/docs/css-prop
개인적인 소견
emotion.js로 컴포넌트의 재사용성을 높였으나,
css 작성은 역시 너무 저수준의 작업이다.
'FrontEnd' 카테고리의 다른 글
[Epic React][Build an Epic React App][Router][라우터] (0) | 2021.12.31 |
---|---|
[Epic React][실전]Make HTTP Requests (0) | 2021.12.31 |
Intellij ,Webstorm에서 jsconfig.js 사용하기. (0) | 2021.12.31 |
[Epic React][실전] Render a React App (0) | 2021.12.31 |
React Remix 신상 React framework 간단하게 살펴보기 (0) | 2021.12.27 |