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;