styled-component 와 css 잘 사용하기

2019. 12. 8. 11:39coding

 React + Redux + Next.js + ant design 조합으로 서비스를 개발하면서 CSS단을 어떤걸로 사용할 지 엄청 많이 고민하다가 Next.js에서는 styled jsx를 기본으로 지원하고 있어서 한번 사용해 봤는데, jsx 태그 안에 스타일 코드가 들어가는게 생각보다 너무 지저분해서 좀 큰 프로젝트를 수행하는데 무리가 있다고 생각했다. 그렇다고 css나 sass를 사용하기에는 리액트에서 편리성이 너무 떨어져서 일단은 styled-component로 결정! styled-component는 컴포넌트 안에서 props를 다이나믹하게 다루기가 진짜 편하다.

Styled-component에서 기본적으로 제일 많이 사용하는것들

1. props 조건부 렌더링
const Button = styled.button`
	background: ${props => props.primary ? "palevioletred" : "white"};
`;

render(
	<Button>Normal</Button>
	<Button primary>Primary</Button>
)


const Input = styled.input`
	color: ${props => props.inputColor || "red"}
`;

render(
	<Input inputColor="purple" />
)

 

2. 스타일 확장해서 사용하기
const Button = styled.button`
	font-size = 1em;
`
const TomatoButton = styled(Button)` //styled() constructor 쓰면 스타일 확장
	color: tomato;
`

 

3. 동적으로 확장해서 사용하기 : as 키워드를 활용한다
const Button = styled.button`
	color: palevioletred;
`
const ReversedButton = props => <Button {...props} chilidren={props.children.split('')} />

render(
	<Button>Normal</Button>
	<Button as={ReversedButton>Custom Button</Button>
)

 

4. select 패턴에서는 ampersand(&)를 잘 활용하기
const Button = styled.button`
	color: blue;
	&:hover {
		color: red;
	}
	& ~ & {
		color: tomato; // 건너서 있을때 -> <Button> <div> <Button>
  }
	& + & {
		color: lime; // 바로 옆에 있을때
	}
	&.something {
		color: orange; //className 이 something 일때 (&. 없이 쓰면 자식요소에만 적용)
	}
	&& {
		color: blue; //전역 스타일 무시
	}
`

 

5. additional props를 전달해서 쓸때 (ant design과 같은 라이브러리 사용시 매우유용함)
const Input = styled.input.attrs(props => ({
	size: props.size || "1em",
}))`
	color: red;
	margin: ${props => props.size};
`
render(
	<Input size="2em" /> //prop 전달할때
)

 

6. 테마 적용하기
const Button = styled.button`
	color: ${props => props.theme.main};
`
Button.defaultProps = {
	theme: {
		main: "red"
	}
}

const theme = {
	main: "green"
};

render(
	<ThemeProvider theme={theme}> //자식요소에 theme 적용
		<Button>Themed</Button>
	</ThemeProvider>
)

 

7. mixin (전체 재사용하기)
const card = css` //css 메소드 사용
	border-radius: 10px;
	paddding: 20px;
`

//css메소드는 컴포넌트 새로 안만들고 쓸때 자주 사용
<div
	css={`
		background: red,
	`}
/>

const InputCheckbox = styled.input.attrs({
	type: 'checkbox',
	checked: true,
})`
	border-radius: 5px;
	${card} //css 추가
`

 

8. createGlobalStyle (전역에서 사용하기)
import styled, { createGlobalStyle } from 'styled-components';

const GlobalStyle = createGlobalStyle`
	body {
		padding: 0;
	}
`

render(
	<React.Fragment>
		<GlobalStyle>
		<Button>Hello</Button>
	</React.Fragment>

 

 

em과 rem 헷갈리는 부분 정리

  • px 값은 브라우저에서 절대값
  • em과 rem은 폰트에 상대적인 값 → 브라우저가 px값으로 변환할때 다름
  • 보통 브라우저는 16px로 1rem은 16px라 보면됨
  • em 단위는 지정된 요소의 폰트 크기를 기준으로 만듬
  • rem 단위는 html 요소의 폰트 크기 (루트 폰트크기) 를 기준으로 함
  • em 단위는 상위 부모 요소로부터 상속받으면서 달라질 수 있음 → 다른 요소의 폰트 크기에 따라 그 크기가 변하는 곳에 주로 사용 (Navigation 같은곳)
  • rem 단위는 부모로 상속은 안되지만 브라우저 설정에 따라 달라짐 → 꼭 em 크기를 사용안해도 되면 rem을 사용하는 것이 낫다.
  • 레이아웃 구성할때는 픽셀단위로 일단 하고 나중에 rem으로 환산하는것이 편함
  • rem 사용하는 경우 media query에도 무조건 rem 사용할것
  • 컬럼 여러개 레이아웃인 경우 rem과 em 말고 % 사용하는게 좋음

 

flexbox 전체적으로 정리

  1. 부모요소 flex container + 자식요소 flex item
    1. flex container
      1. flex-direction (자식요소 정렬 방향)
        1. row : 왼쪽에서 오른쪽 수평방향 정렬
        2. column : 위에서 아래 수직 정렬
      2. flex-wrap
        1. wrap : flex item의 전체 크기가 컨테이너보다 크면 줄을 바꿔서 배치
        2. nowrap : flex item의 전체 크기가 컨테이너보다 크면 컨테이너 넘어감
      3. justify-content (수평 정렬)
        1. space-between: flex item을 일정한 간격으로 정렬 (1 1 1)
        2. flex-start: 주축의 시작부분 기준으로 정렬 (111 )
        3. flex-end: 주축 끝부분 기준으로 정렬 ( 111)
        4. space-around : 중앙 기준으로 간격 정렬 ( 1 1 1 )
        5. center: 중앙 기준으로 모아서 정렬 ( 111 )
      4. align-items (수직 정렬)
        1. stretch : flex item 높이를 늘려서 전체 높이 채운다
        2. flex-start: 시작 부분을 기준으로 정렬 (위에다붙임)
        3. center: 요소의 중앙을 기준으로 맞춰서 정렬 (align-items: center, justify-content: center, margin: auto → 정중앙에 정렬)
        4. flex-end: 끝부분 기준으로 정렬 (밑에다붙임)
      5. align-content (justify content랑 비슷한 수직 정렬 → 보통 여러줄로 나열되어있을때 사용)
    2. flex item
      1. flex (flex-grow, flex-shrink, flex-basis 합친것)
        1. flex: 1 이면 flex-grow 1, flex-shrink 1, flex-basis 0과 같음 (기본)
        2. flex: none 이면 flex: 0 0 auto 와 같음 (크기 고정하려면 flex: none 속성 적용해야한다)
      2. flex-grow
        1. 0 : 컨테이너의 크기가 커져도 원래 크기로 유지
        2. 1 : 원래 크기에 상관없이 컨테이너를 채우도록 커짐
      3. flex-shrink
        1. 0 : 컨테이너의 크기가 자식 크기보다 작아져도 크기 줄어들지 않고 원래 크기로 유지
        2. 1 : 컨테이너의 크기가 자식 크기보다 작아지면 컨테이너 크기에 맞춰서 줄어든다
      4. flex-basis (기본값 auto)
        1. px, %, em, rem 사용 가능, 사용 시 item 크기 고정
        2. 0 : 절대적 flex item이 되어서 container 기준으로 크기가 고정되어서 flex (1:1:1), 0px 처럼 단위도 함께 설정해야함
        3. auto : 콘텐츠 크기 기준으로 크기 결정 (안의 콘텐츠가 커지면 다른 박스를 밀어냄)
      5. order
    3. flexbox내의 margin 조절해서 고정
      1. margin-right : auto → 왼쪽 고정 (margin이 오른쪽으로 밀어냄, 로고같은것)
      2. margin-left : auto → 오른쪽 고정
      3. margin : 0 auto → 수평 중앙에 위치
      4. margin-bottom : auto → 위쪽 고정
      5. margin-top: auto → 아래쪽 고정 (푸터같은것)
      6. margin : auto 0 : 수직 중앙에 위치