이안의 평일코딩

[CSS in JS] Styled-Components란? 본문

Front-end/CSS & SASS

[CSS in JS] Styled-Components란?

이안92 2021. 3. 9. 18:19
반응형

 

 Styled-Components란?

 

CSS보다 더 강력한 추상화로 자바스크립트를 사용해 스타일을 선언하고 유지보수가 가능하게 해주는 대표적인 CSS-in-JS 라이브러리다. 컴포넌트 단위로 추상화되어 모듈성을 갖는다. CSS는 명시적 정의가 없어서 부모 요소에서 자동으로 상속되는 속성이 있지만 CSS-in-JS의 경우 부모 요소 속성이 상속되지 않으므로 진정한 분리 법칙을 따른다.

 

App.js

import "./App.css";
import { Fragment } from "react";

function App() {
  return (
    <div className="App">
      <Fragment>
        <button className="button button--success">Hello</button>
        <button className="button button--danger">Hello</button>
      </Fragment>
    </div>
  );
}

App.css

.button{
    border-radius: 50px;
    padding: 5px;
    min-width: 120px;
    color: white;
    font-weight: 600;
    -webkit-appearance: none;
    cursor: pointer;
}

.button:active,
.button:focus {
    outline: none;
}

.button--success{
    background-color:#2ecc71;
}

.button--danger {
    background-color: #e74c3c;
}

CSS파일을 별도로 두어 import해오는 고전적인 방식이다.

 

 Styled-Components 적용하기

 

그럼 이제 styled-components를 이용해보자.

yarn add styled-components

 

App.js (App.css가 필요없다)

import styled from 'styled-components';

function App() {
  return (
    <div className="App">
      <Container>
        <Button success>Hello</Button>
        <Button danger>Hello</Button>
      </Container>
    </div>
  );
}

const Button = styled.button`
  border-radius: 50px;
  padding: 5px;
  min-width: 120px;
  color: white;
  font-weight: 600;
  -webkit-appearance: none;
  cursor: pointer;
  &:active,
  &:focus {
    outline: none;
  }
  background-color: ${props => props.danger ? "#e74c3c" : "#2ecc71"}
`;

export default App;

 

 createGlobalStyle, withComponent(extend), keyframes

 

App.js

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

// 전역스타일
const GlobalStyle = createGlobalStyle`
  body{
    padding:0;
    margin:0;
  }
`;

function App() {
  return (
    <div className="App">
      <Container>
        <GlobalStyle />
        <Button success>Hello</Button>
        <Button danger rotationTime={5}>Hello</Button>
        <Anchor href="http://google.com">Go to google</Anchor>
      </Container>
    </div>
  );
}

const Container = styled.div`
  height:100vh;
  width:100%;
  background-color:#FBD786;
`

const Button = styled.button`
  border-radius: 50px;
  border: none;
  padding: 5px;
  min-width: 120px;
  color: white;
  font-weight: 600;
  -webkit-appearance: none;
  cursor: pointer;
  &:active,
  &:focus {
    outline: none;
  }
  background-color: ${props => (props.danger ? "#e74c3c" : "#2ecc71")};
  ${props => {
    if(props.danger){
      return css`animation: ${rotation} ${props.rotationTime}s linear infinite`;
    }
  }};
`;

// extend
const Anchor = styled(Button.withComponent("a"))`
  text-decoration:none;
`;

// Animations
const rotation = keyframes`
  from{
    transform: rotate(0deg);
  }
  to{
    transform: rotate(360deg);
  }
`;

export default App;

createGlobalStyle: 어플리케이션에 전체적으로 적용하고 싶은 속성들이 있을 때

styled(컴포넌트명.withComponent("a")): extend처럼 그대로 상속하고 싶을 때

keyframes: 애니메이션을 이용할 때 css와 함께 써준다

 

 attrs, mixin

 

App.js

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

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

// mixin 생성
const awesomeCard = css`
  box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0 , 0, 0, 0.08);
  background-color: white;
  border-radius: 10px;
  padding: 20px;
`;

// Attributes
const Input = styled.input.attrs({
  required: true
})`
  border: none;
  ${awesomeCard}; // mixin 적용
`;

function App() {
  return (
    <div className="App">
      <Container>
        <GlobalStyle />
        <Input placeholder="입력하세요."/>
      </Container>
    </div>
  );
}

const Container = styled.div`
  height:100vh;
  width:100%;
  background-color:#FBD786;
`;

export default App;

attrs: Attributes 속성을 부여하고 싶을 때

mixin: CSS 그룹화하여 여러 곳에서 쓰고 싶을 때

 

 theme, nesting

 

theme.js

const theme = {
    mainColor: "#74b9ff",
    dangerColor: "#ff7675",
    successColor: "#55efc4"
}

export default theme;

App.js

import styled, { createGlobalStyle, ThemeProvider } from 'styled-components';
import theme from './theme';

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

function App() {
  return (
    <div className="App">
      <ThemeProvider theme={theme}> // theme
        <Container>
          <GlobalStyle />
          <Form />
        </Container>
      </ThemeProvider>
    </div>
  );
}

const Card = styled.div`
  background-color: ${props => props.theme.dangerColor}; // theme 적용
`;

const Container = styled.div`
  height:100vh;
  width:100%;
  background-color: ${props => props.theme.successColor};
  // nesting
  ${Card}{
    background-color: blue;
  }
`

const Button = styled.button`
  border-radius:30px;
  border:none;
  padding:25px 15px;
  background-color: ${props => props.theme.mainColor};
`;

const Form = () => (<Card><Button>Hello</Button></Card>)

export default App;

theme: Redux처럼 글로벌하게 색상의 정의가 필요할 때

nesting: 특정 부모 컴포넌트에서 자식 컴포넌트 스타일 속성을 부여하고 싶을 때

 

해당 소스코드

github.com/ianlee92/Styled-Components-practice

 

ianlee92/Styled-Components-practice

Contribute to ianlee92/Styled-Components-practice development by creating an account on GitHub.

github.com

 

반응형

'Front-end > CSS & SASS' 카테고리의 다른 글

Tailwind CSS란?  (0) 2022.07.30
[CSS] 우선순위 배치 Navbar 가장 최상단으로 올리기  (0) 2021.05.12
SASS/SCSS 기초 문법 총정리  (0) 2021.01.01
국비 CSS - 화면분할  (0) 2020.09.17
국비 CSS - DB연동  (0) 2020.09.15
Comments