React기본) React Component Styling 2

lbr·2022년 8월 15일
0

Styled Components (기본)

별도의 library 를 이용합니다.

Styled Component 라는 방식이 있는 것이고, 이것을 지원하는 다양한 library들이 있는데, 그 중에 가장 대표적인 library가 Styled Components 라고 하는 똑같은 이름의 library가 있습니다.

이와 별개로 많이 쓰이는 library가 emotion 이라는 library가 있습니다.
둘 다 같은 방식이지만 약간 사용법이 틀립니다.

Styled Components 라이브러리를 이용하여 component에 style을 적용하는 방법을 알아보겠습니다.

연습 환경

npx create-react-app styled-components-example

npm i styled-components

npm start

연습

//StyledButton.jsx
import styled from 'styled-components';

const StyledButton = styled.button`
  background: transparent;
  border-radius: 3px;
  border: 2px solid palevioletred;
  color: palevioletred;
  margin: 0 1em;
  padding: 0.25em 1em;
  font-size: 20px;
`;

export default StyledButton;

StyledButton은 styled-components 에 의해서 스타일이 적용된 button을 가지고 있게 됩니다.

스타일을 명시하려면 템플릿 스트링을 바로 뒤에 붙여서 표현합니다. 이는 javascript에서 기본적으로 지원되는 방식입니다.

템플릿 스트링 부분은 문자열이기 때문에 css파일에서 작성할 때 처럼 오타를 잡아주지 않습니다. 이 부분을 극복하기 위해 플러그인을 사용한다거나 하지 않으면 조금 어려움이 있을 수 있습니다.

StyledButton 는 현재 스타일이 적용된 일종의 컴포넌트 입니다. 이것을 컴포넌트 처럼 다른 곳으로 가져가서 사용할 수 있습니다.

//App.js

function App() {
  return (
    <StyledButton>버튼</StyledButton>
  );
}

실행하면 button이 출력되고, console 창에서 확인하면 아래처럼 우리가 class를 지정하지 않았음에도 class를 확인할 수 있습니다.

이제 아래처럼 style를 추가하고 html 에서 확인하면,

//StyledButton.jsx
import styled from 'styled-components';

const StyledButton = styled.button`background: transparent;`;

export default StyledButton;

head에 style 태그 한 개가 추가되었습니다.
class 이름이 bNahjN 으로 새로 만들어졌습니다.

button 태그로 가서 확인해 보면 아래처럼 같은 이름의 클래스가 추가되어 있습니다.

정리하면 Styled Components는 클래스 이름이 다른 엘리먼트들과 겹치지 않게 관리하기 위해 style 태그로 style을 자동으로 추가해주고, 클래스 이름을 자동으로 만들어주고, 그 클래스를 컴포넌트에 자동으로 추가해줍니다.

Styled Components (기능)

props의 유무로 디자인 적용 판단 방법

props를 전달해서 그 props에 맞는 디자인을 보여주고 싶은 경우도 많을 것입니다.

//App.js

function App() {
  return (
    <StyledButton primary>버튼</StyledButton>
  );
}

(참고) html문법으로서 html 태그의 속성으로 primary 이렇게 전달하면 primary={true}와 의미가 같습니다.

primary 속성이 (true)있다면 아래의 css 속성을 적용합니다.

//StyledButton.jsx
import styled, { css } from 'styled-components';

const StyledButton = styled.button`
  background: transparent;
  border-radius: 3px;
  border: 2px solid palevioletred;
  color: palevioletred;
  margin: 0 1em;
  padding: 0.25em 1em;
  font-size: 20px;

  ${props => props.primary && 
    css`
      background: palevioletred;
      color: white;
  `}
`;

export default StyledButton;

styled 버튼에 다시 style 을 적용하는 방법

//App.js
import StyledButton from "./components/StyledButton";
import styled from "styled-components";

const PrimaryStyledButton = styled(StyledButton)`
  background: palevioletred;
  color: white;
`;

function App() {
  return (
    <StyledButton primary>버튼</StyledButton>
    <PrimaryStyledButton>버튼</PrimaryStyledButton>
  );
}

사용자가 임의로 만든 style을 가져올 때에는 styled()의 인자로 해당 컴포넌트를 인수로 넘깁니다. styled(StyledButton)

styled가 적용된 컴포넌트를 다른 컴포넌트로 바꾸는 방법

function App() {
  return (
    <StyledButton>버튼</StyledButton>
	<StyledButton as="a" href="/">버튼</StyledButton>
  );
}

두번째 버튼 태그는 이제 button 태그가 아니라 a 태그로 렌더링 됩니다. 실제로 확인해보면 button 태그가 아닌 a태그로 바뀌어 있습니다.

아래처럼 기존의 엘리먼트 뿐만 아니라 as속성에 특정 컴포넌트를 지정하여 그 컴포넌트에 StyledButton의 style을 지정할 수도 있습니다.

const UppercaseButton = (props) => <button { ... props} children={props.children.toUpperCase()} />;

function App() {
  return (
    <StyledButton>버튼</StyledButton>
	<StyledButton as={UppercaseButton}>button</StyledButton>
  );
}

as보다는 더 일반적인 방식

const MyButton = props => <button { ... props} children={`MyButton ${props.children}`} />

const StyledMyButton = styled(MyButton)`
  background: transparent;
  border-radius: 3px;
  border: 2px solid palevioletred;
  color: palevioletred;
  margin: 0 1em;
  padding: 0.25em 1em;
  font-size: 20px;
`;

function App() {
  return (
    <StyledButton>버튼</StyledButton>
    <StyledMyButton>button</StyledMyButton>
  );
}

컴포넌트에서도 class 유무로 서로 다른 css 적용하기

const MyButton = props => <button { ... props} children={`MyButton ${props.children}`} />

const StyledMyButton = styled(MyButton)`
  background: transparent;
  border-radius: 3px;
  border: 2px solid ${(props) => props.color || "palevioletred"};
  color: ${(props) => props.color || "palevioletred"};
  margin: 0 1em;
  padding: 0.25em 1em;
  font-size: 20px;

  :hover {
    border: 2px solid red;
  }

  ::before {
    content: "@";
  }
  
`;

function App() {
  return (
    <StyledButton>버튼</StyledButton>
    <StyledMyButton>button</StyledMyButton>
    <StyledMyButton color="green">button</StyledMyButton>
  );
}

styled의 템플릿 스트링에는
${} 안에 함수를 넣어 props에 따른 원하는 값을 반환하여 적용하는 처리를 해줄 수도 있습니다.
:hover 처리도 가능합니다.
::before와 같은 가상선택자 등 css에서 사용가능한 속성들을 다 사용할 수 있습니다.

글로벌 스타일 적용하기

이처럼
Styled Components 를 사용하면 scope 오염을 방지할 수 있지만, 각각 컴포넌트 별로 style을 적용하다 보면 전역적으로 처리를 하고 싶을 때는 어려움이 있습니다.
그래서 Styled Components 에서도 global로 스타일을 적용할 수 있는 방법을 제공해줍니다.

//App.js
import styled, { createGlobalStyle } from "styled-components";

const GlobalStyle = createGlobalStyle`
  button {
    color: yellow;
  }
`;

function App() {
  return (
    <div className="App">
      <GlobalStyle />
      // ...
      // ...
    </div>
  ); 
}

(추가)

// StyledA.jsx
import styled from "styled-components";

const StyledA = styled.a.attrs((props) => ({
  target: "_BLANK",
}))`
  color: ${props => props.color};
`;

export default StyledA;

attrs((props) => ({})) attrs의 반환값으로 속성을 객체로 반환하면 컴포넌트에 props 객체가 들어온것과 같은 효과를 줄 수 있습니다.

// App.js
function App() {
  return (
    <StyledA href="https://google.com">태그</StyledA>
  ); 
}

StyledA는 href와 target 속성이 적용되어 렌더됩니다.
이제 StyledA가 적용된 컴포넌트는 마치 디폴트로 target: "_BLANK", 속성이 적용된 엘리먼트로 사용할 수 있게 됩니다.

0개의 댓글