이미 만들어둔 컴포넌트에서 기본적인 골격은 유지한 채 일부 스타일만 다르게 만들어야 할 때는 어떻게 해야 할까? 앞서 만든 SButton에서 배경색, 글씨 색만 흰색으로 바꾸고 싶을 때 styled.button 을 하는 것처럼 styled(SButton)을 적용해줄 수 있음. styled()를 이용하면 라이브러리 컴포넌트이든, 내가 직접 만든 컴포넌트든 스타일 확장이 가능함. 이때, 주의할 점은 Styled-Components에서는 클래스명을 이용해 스타일링을 하기 때문에 해당 컴포넌트가 className을 Props로 받을 수 있어야함!
// A. 별도의 컴포넌트를 만들어서 스타일 수정
const SColorButton = ({ className }) => {
return <SBlueButton className={className} />;
}
const SWhiteButton = styled(SColorButton)`
background-color: white;
`;
만약, className을 전달하기 위해 별도의 SColorButton 컴포넌트를 만드는 것이 번거로운 경우에는 attrs()메서드를 이용하는 방법도 있음.
// B. attrs()로 클래스명을 전달받을 수 있도록 만들기
const SColorButton = styled.button.attrs((props) => ({
class: props.className;
}))`
color: white;
background-color: blue;
width: auto;
height: 40px;
`
const SWhiteButton = styled(SColorButton)`
background-color: white;
`;
styled() 이용한 결과
2. 자주 쓰이는 스타일을 변수로 전달하기: css``#
CSS 스타일링을 하다보면 동일한 코드가 계속 반복되는 경우가 많음. 이럴 때 중복된 스타일을 한번에 설정하는 방법은 없을까? 예를 들어, flexbox로 가운데 정렬을 할 때 아래와 같이 세가지 속성은 항상 같이 따라옴.
그렇다면 동일한 스타일을 재활용해야 하는데 HTML 태그는 <div>, <button>, <a> 등으로 모두 다르게 만들어야 한다면 어떨까? CSS를 사용한다면 해당 요소들에 동일한 클래스명을 지정해서 스타일을 적용하는 방법이 있음. Styled-Components에서도 클래스명을 이용할 수도 있겠지만 Styled-Components에서는 스타일까지 모두 컴포넌트화되어 있기 때문에 클래스명으로 전역적인 스타일 설정을 할 수 없음. 이때, as 속성을 이용하면 붕어빵을 찍어내듯이 HTML 태그만 다르고 스타일은 모두 동일한 컴포넌트를 만들어낼 수 있음.
<button> 요소인 SButton의 스타일을 <div> 요소로 바꿔 재사용할 때, as의 속성을 위와 같이 string으로 지정하면 "'string | undefined' 형식은 'undefined' 형식에 할당할 수 없습니다." 와 같은 오류가 뜸. as로 가능한 속성은 HTML 태그뿐인데 그에 비해 string 타입은 너무 범위가 넓기 때문.
Styled-Components 스타일 재사용하기
1. 컴포넌트 스타일 확장하기: styled()`` #
이미 만들어둔 컴포넌트에서 기본적인 골격은 유지한 채 일부 스타일만 다르게 만들어야 할 때는 어떻게 해야 할까? 앞서 만든 SButton에서 배경색, 글씨 색만 흰색으로 바꾸고 싶을 때 styled.button 을 하는 것처럼 styled(SButton)을 적용해줄 수 있음. styled()를 이용하면 라이브러리 컴포넌트이든, 내가 직접 만든 컴포넌트든 스타일 확장이 가능함. 이때, 주의할 점은 Styled-Components에서는 클래스명을 이용해 스타일링을 하기 때문에 해당 컴포넌트가 className을 Props로 받을 수 있어야 함!
만약, className을 전달하기 위해 별도의 SColorButton 컴포넌트를 만드는 것이 번거로운 경우에는 attrs() 메서드를 이용하는 방법도 있음.
2. 자주 쓰이는 스타일을 변수로 전달하기: css`` #
CSS 스타일링을 하다보면 동일한 코드가 계속 반복되는 경우가 많음. 이럴 때 중복된 스타일을 한번에 설정하는 방법은 없을까? 예를 들어, flexbox로 가운데 정렬을 할 때 아래와 같이 세가지 속성은 항상 같이 따라옴.
이런 경우, css Helper 함수를 이용해 별도의 폴더에 스타일 변수를 설정해두고 해당 변수를 import하면 전역에서 해당 스타일을 재사용할 수 있음.
3. HTML 태그만 변경하기: as 속성 #
그렇다면 동일한 스타일을 재활용해야 하는데 HTML 태그는 <div>, <button>, <a> 등으로 모두 다르게 만들어야 한다면 어떨까? CSS를 사용한다면 해당 요소들에 동일한 클래스명을 지정해서 스타일을 적용하는 방법이 있음. Styled-Components에서도 클래스명을 이용할 수도 있겠지만 Styled-Components에서는 스타일까지 모두 컴포넌트화되어 있기 때문에 클래스명으로 전역적인 스타일 설정을 할 수 없음. 이때, as 속성을 이용하면 붕어빵을 찍어내듯이 HTML 태그만 다르고 스타일은 모두 동일한 컴포넌트를 만들어낼 수 있음.
Styled Components에 as 속성으로 어떠한 HTML 요소로 바꿀건지 그 태그명을 지정해주면 됨. 한편, 별도의 React 컴포넌트를 만들지 않고도 attrs() 메서드를 이용해 HTML 태그를 바꿔줄 수 있음.
태그만 변형하고 SButton에서 추가할 스타일이 없다면 뒤에 빈 백틱(``)은 반드시 붙여줘야 유효한 JSX Element이므로 컴파일 에러가 발생하지 않음.
이때, Button 요소에서 기본 텍스트의 크기(User Agent Stylesheet )와 Div 요소의 기본값은 다를 수 있기 때문에 세세한 부분은 직접 확인하면서 스타일을 통일시키는 작업이 필요함.
4. Typescript에서 사용하기
<button> 요소인 SButton의 스타일을 <div> 요소로 바꿔 재사용할 때, as의 속성을 위와 같이 string으로 지정하면 "'string | undefined' 형식은 'undefined' 형식에 할당할 수 없습니다." 와 같은 오류가 뜸. as로 가능한 속성은 HTML 태그뿐인데 그에 비해 string 타입은 너무 범위가 넓기 때문.
따라서, 위와 같이 속성의 범위를 HTML 태그에 한정해서 지정해줘야 함.
[참고]
styled-components not applying style to custom functional react component
Is it possible to pass props to "css" element of styled components?
Using 'as' polymorphic prop of styled-components with typescript
'CSS' 카테고리의 다른 글