올해 10월 초부터 생각했던 사이드 프로젝트를 본격적으로 만들어 보려고 한다 (이번엔 제발 런칭까지....)
리액트를 거의 3년만에 보게 되었는데 뭐 아주 그냥 새롭다. 이야 훅은 또 뭐야? 라떼는 클래스만 있었는데
이번 포스트에서는 리액트에서 스타일 지정하는 방법을 공부해 보았다.
(react modern stack에 빠삭한 지인과의 카톡)
REF : https://react.vlpt.us/styling/03-styled-components.html
- CSS in Js : JS 안에 CSS를 작성하는 것
- 리액트 진영에서 가장 인기 있는 CSS in JS 라이브러리가 바로
styled-components
이다.
설치
yarn add styled-components
사용
styled.태그이름
을 사용해서 바로 Recat component를 만들 수 있다.
import React from 'react';
import styled from 'styled-components';
/**
* Styled Components를 이용해 컴포넌트까지 같이 만든다
*/
const Circle = styled.div`
width: 5rem;
height: 5rem;
background: black;
border-radius: 50%;
`;
export default Circle;
오호.. props를 이용해 css 옵션을 하나만 조정할 수도 있고, 여러 css를 조절할 수도 있다.
const Circle = styled.div`
width: 5rem;
height: 5rem;
background: ${props => props.color || 'black'};
border-radius: 50%;
${props =>
props.huge &&
css`
width: 10rem;
height: 10rem;
`}
`;
<Circle
color="red" huge
/>
신기하네 ㅋㅋㅋㅋㅋ Sass의 lighten()
혹은 darken()
과 같은 유틸 함수를 쓰고 싶다면 polished
라이브러리를 이용할 수 있다.
yarn add polished
import {lighten, darken} from 'polished';
const StyledButton = styled.button`
/* 색상 */
background: #228be6;
&:hover {
background: ${lighten(0.1, '#228be6')};
}
&:active {
background: ${darken(0.1, '#228be6')};
}
`
function Button({ children, ...rest }) {
return <StyledButton {...rest}>{children}</StyledButton>;
}
export default Button;
이렇게 하면 야무지게 적용 완료! 키야 RGB 찾으러 갈 필요가 없네 (흑흑 이런거 볼 때마다 프론트 옛날 사람이 된 것 같다...)
styled components의 ThemeProvider 기능을 사용하면 styled components로 만드는 모든 컴포넌트에서 조회할 수 있는 global 값이 된다고 한다. 오호...
/* Button을 쓰는 쪽 render 코드 */
<ThemeProvider theme={{
rgbColors: {
blue: '#228be6',
gray: '#495057',
pink: '#f06595'
}
}}>
<AppBlock>
<Button>BUTTON</Button>
</AppBlock>
</ThemeProvider>
/* Button 코드 style 부분 */
/* 색상 */
${props => {
const selected = props.theme.rgbColors.blue
return css`
background: ${selected};
&:hover {
background: ${lighten(0.1, selected)};
}
&:active {
background: ${darken(0.1, selected)};
}
`
}};
여기서 이제 props.theme.rgbColors.blue
를 props.theme.rgbColors[props.color]
로 바꿔주고 default prop을 설정해주면 깔끔~ 해진다
/* Button 코드 style 부분 */
${props => {
const selected = props.theme.rgbColors[props.color]
// 나머지는 그대로
}};
/* function Button 아래 부분 */
Button.defaultProps = {
color: 'blue'
};
const selected = props.theme.rgbColors[props.color]
가 보기 불편하면 다음과 같이 바뀔 수 있다.
/* Button 코드 style 부분, 여기서 props 대신 { }로 바뀐다 */
${({ theme, color }) => {
const selected = theme.palette[color];
// 나머지는 그대로
}};
// color를 명시적으로 넣어줌
function Button({ children, color, ...rest }) {
return (
<StyledButton color={color} {...rest}>
{children}
</StyledButton>
);
}
스타일 역시 동적인 부분과 정적인 부분을 분리할 수 있다.
const dynamicStyle = css`
${props => (
// 로직
)}
`
const staticStyle = styled.button`
// 정적인 style 다 넣어놓고~
${dynamicStyle}
`
css를 중첩되게 넣을 수 있다.
const DialogBlock = styled.div`
h3 {}
p {}
`;
// h3과 p에 각각 style이 적용된다
<DialogBlock>
<h3>하하하</h3>
<p>히히</p>
</DialogBlock>
styled-components로 컴포넌트의 스타일을 특정 상황에서 덮어 쓸 수 있다.
이때 해당 컴포넌트에서 className props
를 내부 element에게 전달해주고 있는지 확인이 필요하다.
// Button 컴포넌트가 있을 때
// & + &를 하게 되면, 같은 부모를 가지는 Button 옆에 Button에만 적용된다
const ShortMarginButton = styled(Button)`
& + & {
margin-left: 0.5rem;
}
`;
// CASE 1. className을 명시적으로 전달 중
const Button = ({ className }) => {
return <div className={className}></div>
}
const NewComponent = styled(Button)`
background: black;
`;
// CASE 2. rest로 전달 중
function Button({ children, ...rest }) {
return <StyledButton {...rest}>{children}</StyledButton>;
}
트랜지션 효과를 적용할 때는 @keyframes
를 사용하게 된다. keyframes 규칙은 개발자가 애니메이션 중간중간의 특정 지점들을 거칠 수 있는 키프레임들을 설정함으로써 CSS 애니메이션 과정의 중간 절차를 제어하는 것이다. 이 룰은 브라우저가 자동으로 애니메이션을 처리하는 것 보다 더 세밀하게 중간 동작들을 제어할 수 있다.
styled-components에서 이를 사용할 때는 keyframes
라는 유틸을 써야 한다.
import styled, { keyframes } from 'styled-components';
const fadeIn = keyframes`
from {
opacity: 0
}
to {
opacity: 1
}
`;
const slideUp = keyframes`
from {
transform: translateY(200px);
}
to {
transform: translateY(0px);
}
`;
const DarkBackground = styled.div`
// 기존 CSS는 그대로
animation-duration: 0.25s;
animation-timing-function: ease-out;
animation-name: ${fadeIn};
animation-fill-mode: forwards;
`
const DialogBlock = styled.div`
// 기존 CSS는 그대로
animation-duration: 0.25s;
animation-timing-function: ease-out;
animation-name: ${slideUp};
animation-fill-mode: forwards;
`
이렇게 하면 나타낼 때 트랜지션 효과가 나타나게 된다. 오호 애니메이션 관련 css는 잘 모르는데 신기하다 ㅋㅋㅋ
사라질때를 처리하려면 local prop 들이 더 필요하다고... 오호.. 신기하다. 애니메이션 직접 만질일 있으면 다시 봐야겠다 ㅋㅋㅋ
Global
createGlobalStyle
을 이용하여 CSS 속성을 덮어 쓸 수도 있다.
import styled, { createGlobalStyle } from 'styled-components';
const GlobalStyle = creaetGlobalStyle`
body {
padding: 0;
margin: 0;
}
`
<React.Fragment>
<GlobalStyle> // <-- 추가
<Button>Hello</Button>
<Button danger>Hello</Button>
</React.Fragment>
'개발 공부 기록하기 > 07. react.js & vue.js' 카테고리의 다른 글
리액트 리덕스 정리 (0) | 2020.12.14 |
---|---|
React Router 정리 (0) | 2020.11.18 |
리액트 훅(React Hook) 정리 (0) | 2020.10.19 |
vue에 SASS 적용하기 (0) | 2019.07.23 |
vue 컴포넌트란? / vue export default 간단 정리 (0) | 2019.07.22 |