styled-components

박은정·2021년 9월 22일
0

TIL

목록 보기
27/70

tagged 템플릿 리터럴

  1. 백틱을 사용해서 만든 문자열에 → 스타일 정보 입력하는 방식
  2. CSS Module을 배울 때 나온 일반 템플릿 리터럴과 다른점 : 템플릿 안에 JS객체나 함수를 전달할 때 온전히 추출이 가능하다
`hello {{foo: 'bar' }} ${() => 'world'}!`
// 결과 : "hello [object Object] () => 'world'!"

템플릿에 객체를 넣거나 함수를 넣으면 형태를 잃어버린다

  • 객체는 → [object Object]
  • 함수는 함수 내용이 그대로 문자열화
function tagged(...args) {
  console.log(args);
}

tagged`hello ${{foo: 'bar' }} ${() => 'world'}!`

해당 코드를 확인해보면

tagged 탬플릿 리터럴을 사용하면 위와 같은 방식으로 템플릿 사이사이에 들어가는 자바스크립트 객체나 함수의 원본 값을 그대로 추출할 수 있다
styled-components는 이러한 속성을 사용해서 → styled-components로 만든 컴포넌트의 props를 스타일 쪽에서 쉽게 조회할 수 있게 한다

styled.태그명

import styled from 'styled-components';

const MyComponent = styled.div`
  font-size: 2rem;
`;

이렇게 styled.div 뒤에 Tagged 탬플릿 리터럴 문법을 통해 스타일을 넣어주면
해당 스타일이 적용된 div로 이루어진 리애트 컴포넌트가 생성된다

만약 div가 아닌 button이나 input에 스타일링을 하고 싶다면 styled.button 혹은 styled.input 같은 형태로 뒤에 태그명을 넣어주면 된다

styled('태그명') || styled(컴포넌트명)

사용해야 할 태그명이 유동적이거나
특정 컴포넌트 자체에 스타일링을 해주고 싶을 때 사용한다

  1. 태그의 타입을 styled 함수의 인자로 전달
const MuInput = styled('input')`
  background: gray;
`
  1. styled 함수의 인자로 컴포넌트 형식의 값을 넣어준다
const StyledLink = styled(Link)`
  color: blue;
`

이런식으로 컴포넌트를 styled의 파라미터로 넣는 경우에는
해당 컴포넌트에 className props를 최상위 DOM의 className 값으로 설정하는 작업이 내부적으로 되어있어야 한다

const Samplr = ({ className }) => {
  return <div className={className}>Sample</div>;
};

const StyledSample = styled(Sample)`
  font-size: 2rem;
`;

스타일에서 props 조회

styled-components를 사용하면 스타일 쪽에서 컴포넌트에게 전달된 props값을 참조할 수 있다 바로가기 링크를 만들 수 있다

참조하다

  • 복제는 파일을 복사하는 것이고 참조 는 심볼릭 링크(symbolic link) 혹은 바로가기(윈도우)를 만드는 것과 비슷하다
  • 심볼릭 링크를 통해서 만든 파일은 원본 파일에 대한 주소 값이 담겨 있는데, 누군가 심볼릭 링크에 접근하면 → 컴퓨터는 심볼릭 링크에 저장된 원본의 주소를 참조 해서 원본의 위치를 알아내고 원본에 대한 작업을 하게 된다
  • 다시 말해서 원본을 복제한 것이 아니라 원본 파일을 참조(reference)하고 있는 것이다
    덕분에 저장 장치의 용량을 절약할 수 있고, 원본 파일을 사용하고 있는 모든 복제본이 동일한 내용을 유지할 수 있게 된다
  • 참조는 전자화된 세계의 극치라고 할 수 있다.
const Box = styled.div`
  background: ${props => props.color || 'blue'};
  padding: 1rem;
  display: flex;
`;

<Box color="black"></Box>

위의 코드처럼 props로 너헝준 값을 직접 전달할 수 있는데
background값에 props를 조회해서 props.color의 값을 사용하게 했다
그리고 color 값이 주어지지 않았을 때에는 기본적으로 blue 색상으로 설정했다

props에 따른 조건부 스타일링

  • 일반 CSS 클래스를 사용해서 조건부 스타일링을 해야할 때에는 className을 사용해서 조건부스타일링을 했지만
  • styled-components 에서는 props를 이용해서 간단하게 조건부 스타일링을 처리할 수 있다
  • 단순 변수의 형태가 아니라 여러 줄의 스타일 구문을 조건부로 설정해야 하는 경우에는 css를 불러와야 한다
  • &:hover 처럼 & 문자를 이용해서 자기자신 선택할 수 있다
import styled, { css } from 'styled-components';

const Button = styled.button`
  background: white;
  color: black;
  border-radius: 4px;
  (코드생략)

  &:hover {
    background: rgba(255, 255, 255, 0.9);
}

  ${props =>
    props.inverted &&
      css`
        background: none;
        border: 2px solid whitel
        color: white;
        &:hover {
          background: white;
          color: black;
        }
  `};

  & + button {
    margin-left: 1rem;
}
`;

<Button>안녕하세요</Button>
<Button inverted={true}>테두리만</Button>

리액트에서 props 전송하는 두가지 방법

  1. 일반 텍스트 전달 : "" 따옴표 사용
<제목 색상="blue"></제목>
  1. 변수나 자료형 전달 : {} 중괄호 사용
<제목 색상={'red'}></제목>

스타일 코드 여러 줄을 props에 따라 넣어줄 때에는 css 를 styled-components 에 불러와야 하긴한데

${props =>
    props.inverted &&
      css`
        background: none;
        border: 2px solid whitel
        color: white;
        &:hover {
          background: white;
          color: black;
        }
  `};

css를 사용하지 않고 바로 문자열에 넣어도 작동은 되긴하지만

  • 해당 내용이 그저 문자열로만 취급되기 때문에 vs code 확장프로그램에서 syntax highlighting이 제대로 이루어지지 않는다
  • Tagged 탬플릿 리터럴이 아니기 때문에 함수를 받아 사용하지 못해 해당 부분에서는 props 값을 사용하지 못한다
  • 여러 줄의 코드에서 props를 참조하지 않는다면 굳이 css를 불러와서 사용하지 않아도 상관없디만 props를 참조한다면 반드시 css로 감싸 주어서 Tagged 템플릿 리터럴을 사용해야 한다
${props =>
  props.inverted &&
  `
        background: none;
        border: 2px solid whitel
        color: white;
        &:hover {
          background: white;
          color: black;
        }
  `};

반응형 디자인

const Box = styled.div`
  background: ${props => props.blue || 'blue'};
  padding: 1rem;
  display: flex;
  width: 1024px;
  margin: 0 auto;
  @media (max-width: 1024) {
    width: 768px;
  }
  @media (max-width: 768) {
    width: 100%;
  }
`;
background: ${props => props.blue || 'blue'};

이렇게 props로 넣어준 값을 직접 전달할 수 있다

  @media (max-width: 1024) {
    width: 768px;
  }
  @media (max-width: 768) {
    width: 100%;
  }

기본적으로는 가로크기 1024pxz에 가운데 정렬을 하고 가로크기가 작아짐에 따라 크기를 줄이고 768px 미만이 되면 marin을 없애고 꽉 채운다

반응형 디자인 반복하는 함수만들기

이러한 작업을 여러 컴포넌트에서 반복한다면 귀찮을 수 있지만 함수화해서 만든다면 간편하게 사용할 수 있다
media를 한번 선언하고 사용하면 스타일 쪽의 코드가 간단해진다
지금은 media를 StyledComponrnt.js에서 만들었다면 실제 개발환경에서는 아예 다른 파일로 모듈화한 다음 → 여기저기서 불러와 사용하는 방식이 훨씬 편하다

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

const sizes = {
  dexktop: 1024,
  tablet: 768,
};

// size 객체에 따라 자동으로 media 쿼리 함수를 만들어준다
const media = Object.keys(sizes).reduce((acc, label) => {
  acc[label] = (...arg) => css`
    @media (max-width: ${sizes[label] / 16}em) {
      ${css(...args)};
    }
  `;

  return acc;
}, {});

const Box = styled.div`
  background: ${props => props.color || 'blue'};
  padding: 1rem;
  display: flex;
  width: 1024px;
  margin: 0 auto;
    ${media.desktop`width: 768px;`}
    ${medai.tablet`width: 100%;`}
`;

`

profile
새로운 것을 도전하고 노력한다

0개의 댓글