파크로그

Styled-components css() 함수, 왜쓰지?

styled-component 를 사용하면서 props 의 특정 상태에 따라 스타일링을 다르게 하는 경우가 있다.

그런데 이전에 다른 분들이 사용하시는 것을 보면 css() 함수와 함께 사용하는 경우를 여럿 봤다.

 

import styled, { css } from 'styled-components';

const flexMixin = ({ jc, ai }: { jc?: string; ai?: string }) => css`
  display: flex;
  ${jc &&
  css`
    justify-content: ${jc};
  `}
  ${ai &&
  css`
    align-items: ${ai};
  `}
`;

const MyBox = styled.div<{
  flexInfo: {
    jc: string;
    ai: string;
  };
}>`
  ${({ flexInfo }) => flexMixin(flexInfo)};
`;

const PageLayout: React.FC = () => (
  <MyBox flexInfo={{ jc: 'center', ai: 'center' }}>안녕하세요</MyBox>
);

export default PageLayout;

개인적으로 궁금한건 이거였다.

그냥 템플릿 리터럴이 반환되는 거니까 css 메서드 없이 사용해도 동일한 결과값이 나오는데 왜 써야하는거지? 

import styled from 'styled-components';

const flexMixin = ({ jc, ai }: { jc?: string; ai?: string }) => `
  display: flex;
  ${jc &&
  `
    justify-content: ${jc};
  `}
  ${ai &&
  `
    align-items: ${ai};
  `}
`;

const MyBox = styled.div<{
  flexInfo: {
    jc: string;
    ai: string;
  };
}>`
  ${({ flexInfo }) => flexMixin(flexInfo)};
`;

const PageLayout: React.FC = () => (
  <MyBox flexInfo={{ jc: 'center', ai: 'center' }}>안녕하세요</MyBox>
);

export default PageLayout;

 

Styled component 의 공식문서에서는 CSS helper function 을 아래와 같이 설명하고 있다.

궁금한점이 해소되는 핵심적인 부분은 string 을 채울(interpolating) 경우 css function 을 사용할 필요는 없지만, 함수(CSS function)를 사용할 때에는 사용해야된다는 점이었다.

 

공식문서의 예제에 맞춰 고민했던 코드를 다시 고쳐보았다.

 

import styled, { css } from 'styled-components';

const flexMixin = css<{
  flexInfo: {
    jc?: string;
    ai?: string;
  };
}>`
  display: flex;
  ${({ flexInfo: { jc } }) => jc && `justify-content: ${jc};`}
  ${({ flexInfo: { ai } }) => ai && `align-items: ${ai};`}
`;

const MyBox = styled.div<{
  flexInfo?: {
    jc?: string;
    ai?: string;
  };
}>`
  ${({ flexInfo }) => (flexInfo ? flexMixin : {})};
`;

const PageLayout: React.FC = () => (
  <MyBox flexInfo={{ jc: 'center', ai: 'center' }}>안녕하세요</MyBox>
);

export default PageLayout;

flexMixin 은 MyBox 의 Props 를 그대로 전달받아 사용하는 형태이므로, 별도의 Props 를 인수로 넘겨 사용할 필요가 없어졌다.

 

그럼 CSS helper function 을 꼭 CSS helper function 을 interpolating 할 때만 사용해야 할까?

string 만을 interpolating 하더라도, CSS 관련 자동완성기능과 Styled-component highlighting extension 을 사용한다면 오히려 개발생산성에 이점이 있을 것이다.

자동완성 기능 제공

CSS prop

가령 Styled-components 로 스타일링을 하다보면, CSS 의 단 한속성 정도 필요한 애들이 참 난감했다.

별도의 Styled-component 로 만들어 사용해야하나? 인라인 style 을 줘서 쓰나? 아니면 그냥 스타일링 관련 공통으로 쓰일만한 컴포넌트를 하나 만들어 사용할까?

 

스타일링 관련 공통 컴포넌트 ( ex. Box ) 를 만들어 사용하다보니 답도없이 받아야 하는 props 가 커지는 경우도 많았다.

위 CSS helper function 에 대해서 찾아보다 우연히 CSS prop 이라는 방법을 찾았다.

 

CSS Prop 을 사용하기 위해선 Babel Plugin 이 추가로 필요하다.
Typescript 를 사용하는 프로젝트의 경우 코드 한줄을 추가로 작성해야 한다.

 

위 상황과 동일하게, extra component 를 만들 필요 없이 HTML native element 에 css prop 을 주는 방법이다.

아래 두 코드는 완벽히 동일하게 동작한다.

<div
  css={`
    background: papayawhip;
    color: ${props => props.theme.colors.text};
  `}
/>
<Button
  css="padding: 0.5em 1em;"
/>
import styled from 'styled-components';

const StyledDiv = styled.div`
  background: papayawhip;
  color: ${props => props.theme.colors.text};
`

const StyledButton = styled(Button)`
  padding: 0.5em 1em;
`

<StyledDiv />
<StyledButton />

 

css 에 들어갈 값으로는 템플릿 리터럴 이어도 되고, object 여도 된다.

object 인 경우 css 속성 key 를 CamelCase (alignItems) 로 사용해야 한다.

object 를 사용할 때에는 자동완성의 기능을 제공하여 실수를 줄일 수 있고, 외부에서 default 값을 수정하기에도 편리할 것이다.

 

import { ReactNode } from 'react';

const PageLayout: React.FC<{ children: ReactNode; sx?: object }> = (props) => {
  const { children, sx } = props;

  return (
    <main
      css={{
        width: '100vw',
        height: '100vh',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'center',
        alignItems: 'center',
        ...sx,
      }}
      {...props}
    >
      {children}
    </main>
  );
};

export default PageLayout;
profile

파크로그

@파크park

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!