9월13일 (월) 컴포넌트 디자인

남이섬·2021년 9월 13일
0

Component Driven Development

  • 부품 단위로 UI 컴포넌트를 만들어 나가는 개발

여러 프로젝트 혹은 여러 팀 간에 같은 UI 컴포넌트를 공유
디자인과 개발 단계에서부터 재사용할 수 있는 UI 컴포넌트를 미리 디자인하고 개발

컴포넌트 UI 개발을 위한 Storybook

Component Driven Development 가 트렌드로 자리 잡게 되면서 이를 지원하는 도구 중 하나인 Component Explorer (컴포넌트 탐색기) 가 등장
Component Explorer에는 많은 UI 개발도구가 다양하게 있는데 그중 하나가 Storybook 이다

Storybook 이란 ?

StorybookUI 개발 즉, Component Driven Development를 하기 위한 도구

  • 각각의 컴포넌트들을 따로 볼 수 있게 구성해주어 한 번에 하나의 컴포넌트에서 작업할 수 있다
  • 복잡한 개발 스택을 시작하거나, 특정 데이터를 데이터베이스로 강제 이동하거나, 애플리케이션을 탐색할 필요 없이 전체 UI를 한눈에 보고 개발할 수 있다

Storybook은 재사용성을 확대하기 위해 컴포넌트를 문서화하고,
자동으로 컴포넌트를 시각화하여 시뮬레이션할 수 있는 다양한 테스트 상태를 확인할 수 있다

이를 통해 버그를 사전에 방지할 수 있도록 도와준다
또한 테스트 및 개발 속도를 향상시키는 장점이 있으며, 애플리케이션 또한 의존성을 걱정하지 않고 빌드할 수 있다

Storybook 과 같은 UI 개발 도구를 왜 사용할까 ?

Storybook은 기본적으로 독립적인 개발환경에서 실행된다
개발자는 애플리케이션의 다양한 상황에 구애받지 않고 UI 컴포넌트를 집중적으로 개발 할 수 있다

회사의 내부 개발자들을 위해 문서화(documentation)를 하여 회사의 UI 라이브러리로써 사용하거나,
외부 공개용 디자인 시스템(Design System)을 개발하기 위한 기본 플랫폼으로 사용할 수 있다

Storybook에서 지원하는 주요 기능

  • UI 컴포넌트들을 카탈로그 화하기
  • 컴포넌트 변화를 Stories로 저장하기
  • 핫 모듈 재 로딩과 같은 개발 툴 경험을 제공하기
  • 리액트를 포함한 다양한 뷰 레이어 지원하기

Storybook 설치 및 세팅 방법

# Clone the template
npx degit chromaui/intro-storybook-react-template taskbox
//
cd taskbox
//
# Install dependencies
yarn

story book 공식문서

구조적인 CSS 작성 방법의 발전

구조화된 CSS가 필요하게 된 이유

프로젝트의 규모나 복잡도가 점점 커지고 함께 작업해야할 팀원 수도 많아짐에 따라 CSS를 작성하는 일관된 패턴이 없다는 것은 개발자들에게 가장 큰 걸림돌이 되었고,

또한 모바일이나 태블릿을 비롯한 다양한 디바이스들의 등장으로 웹사이트들이 다양한 디스플레이를 커버해야 하기 때문에 CSS는 더 복잡해지게 되었다

따라서 CSS 작업을 효율적으로 하기 위해 구조화된 CSS의 필요성이 대두되었고, CSS를 구조화하는 방법에 대한 연구가 필요해졌다

CSS 구조화를 위한 다양한 시도

위와 같은 문제점들을 해결하기 위해 CSS 전처리기(CSS Preprocessor) 라는 개념이 등장했다
CSS 전처리기(CSS Preprocessor)CSS가 구조적으로 작성될 수 있게 도움을 주는 도구다

우리가 흔히 CSS문서를 작성할 때는 많은 반복적인 작업을 요구하고 Color 값을 찾는 일, tag를 닫는 일 등 번거로운 작업 역시 포함이 되어 있다
그 뿐만 아니라 클래스의 상속과 같은 사항으로 점점 CSS 문서는 양이 많아지고 이로 인해 이후 유지관리에 많은 영향을 끼친다
이런 CSS의 문제점들을 프로그래밍 개념(변수, 함수, 상속 등)을 활용하여 해결해 나갈 수 있다

하지만 이 CSS 전처리기(CSS Preprocessor) 자체만으로는 웹 서버가 인지하지 못하기 때문에 각 CSS 전처리기에 맞는 Compiler를 사용해야 하고 컴파일을 하게 되면 실제로 우리가 사용하는 CSS 문서로 변환이 된다

이를 통해 CSS 파일들을 잘 구조화할 수 있게 되었고, 최소한 CSS 파일을 몇 개의 작은 파일로 분리할 수 있는 방법이 생겼다

CSS 전처리기의 등작 - SASS

CSS 전처리기 중에서 가장 유명한 SASS는 Syntactically Awesome Style Sheets 의 약자로 CSS를 확장해 주는 스크립팅 언어

즉, CSS를 만들어주는 언어로서 자바스크립트처럼 특정 속성(ex. color, margin, width 등)의 값(ex. #ffffff, 25rem, 100px 등)을 변수로 선언하여 필요한 곳에 선언된 변수를 적용할 수도 있고, 반복되는 코드를 한번의 선언으로 여러 곳에서 재사용할 수 있도록 해 주는 등의 기능을 가졌다

그래서 SASS는 SCSS 코드를 읽어서 전처리한 다음 컴파일해서 전역 CSS 번들 파일을 만들어 주는 전처리기(preprocessor)의 역할을 한다

하지만 얼마 지나지 않아서 SASS가 ‘CSS의 구조화’를 해결해 주는 것의 장점보다 다른 문제들을 더 많이 만들어낸다는 것이 밝혀진다

결국 전처리기(preprocessor)가 내부에서 어떤 작업을 하는지는 알지 못한 채, 스타일이 겹치는 문제를 해결하기 위해 단순히 계층 구조를 만들어 내는 것에 의지하게 되었고, 그 결과 컴파일된 CSS의 용량은 어마어마하게 커지게 되었다

CSS 사용 예제

.alert {
  bodrder: 1px solid rgba(198, 83, 140, 0.88)
}
.button {
  color: rgba(198, 83, 140, 0.88)
}

SASS 변수 사용 예제

$base-color: rgba(198, 83, 140, 0.88)
.alert {
  bodrder: 1px solid $border-dark
}
.button {
  color: $border-dark
}

반복되는 css 코드가 있다면 변수를 활용해서 재사용이 가능하게 만들어준다
변수를 선언할때는 $기호를 활용한다

CSS 구조화를 위한 다양한 시도

이러한 CSS 전처리기의 문제를 보완하기 위해 BEM, OOCSS, SMACSS 같은 CSS 방법론이 대두되었다
각각의 장단점이 있으나 결국 세 방법론 모두 같은 지향점을 가지고 있다

방법론의 공통 지향점

  • 코드의 재사용
  • 코드의 간결화(유지보수 용이, 쉬운 유지보수)
  • 코드의 확장성(확장 가능)
  • 코드의 예측성(클래스 명으로 의미 예측)

이런 CSS 방법론들은 같이 일하는 팀 동료들의 팀워크와도 연결되기 때문에 여러 팀원이 함께 작업하는 상황에서 CSS 작성에 있어서 방법들을 규칙으로 정해두는 것은 매우 중요한 요소라고 할 수 있다

BEM(Block, Element, Modifier)

BEM이란 Block, Element, Modifier로 구분하여 클래스명을 작성하는 방법이며, Block, Element, Modifier 각각은 __로 구분한다

클래스명은 BEM 방식의 이름을 여러 번 반복하여 재사용할 수 있도록 하며 HTML/CSS/SASS 파일에서도 더 일관된 코딩 구조를 만들어 준다

하지만 이러한 방법론들에서도 문제점이 발생하기 시작한다
클래스명 선택자가 장황해지고, 이런 긴 클래스명 때문에 마크업이 불필요하게 커지며, 재사용하려고 할 때마다 모든 UI 컴포넌트를 명시적으로 확장해야만 했다

또한 SASS와 BEM도 고치지 못했던 몇 가지 문제들은 언어 로직 상에 진정한 캡슐화(encapsulation : 객체의 속성과 행위를 하나로 묶고 실제 구현 내용 일부를 외부에 감추어 은닉하는 개념)의 개념이 없다는 것이었고, 이로 인해 개발자들이 유일한 클래스명을 선택하는 것에 의존할 수 밖에 없었다

Block: 전체를 감싸고 있는 블럭 요소
Element: 블럭이 포함하고 있는 한 조각
Modifier: 블럭 또는 요소의 속성
(블록이나 엘리먼트의 외관이나 상태를 변화가능하게 하는 부분)

//Block // Element  // Modifier
.header_navigation--navi-text {
  color: red;
}

CSS-in-JS의 등장 styled-Component

어플리케이션으로 개발 방향이 진화하면서 컴포넌트 단위의 개발은 캡슐화의 중요성을 불러왔다
하지만 CSS는 컴포넌트 기반의 방식을 위해 만들어진 적이 한번도 없었다
결국 CSS도 컴포넌트 영역으로 불러들이기 위해서 CSS-in-JS가 탄생해서 이 문제를 정확하게 해결한다

CSS-in-JS에는 대표적으로 Styled-Component가 있다

Styled-Component는 기능적(Functional) 혹은 상태를 가진 컴포넌트들로부터 UI를 완전 분리해 사용할 수 있는 아주 단순한 패턴을 제공한다

CSS 방법론들의 특징, 장단점 overview

컴포넌트 기반 CSS 작성에 적합한 Styled-Component

Styled-Component

Styled ComponentReact 의 컴포넌트 기반 개발 환경에서 스타일링을 위한 CSS의 성능 향상을 위해 탄생하였다
Styled Component 를 사용하면 기존 CSS 문법으로도 스타일 속성이 추가된 React 컴포넌트를 만들 수 있다

예를 들어 Styled Component 를 이용하여 어플리케이션 내에 다른 웹페이지로 이동하는 기능을 가진 Button 을 하나 만든다면 아마도 아래 코드와 같을 것이다
하나하나 살펴보면 우리가 기존에 학습한 JavaScript (React) & CSS 와 크게 다르지 않다
JavaScript에서 변수를 선언하듯이(혹은 React 에서 컴포넌트를 만들듯이) Button 을 만들고, tag 의 속성을 정의하고 (여기서는 a tag), back-ticks (``) 안에 기존 CSS 문법을 이용하여 스타일 속성을 정의해 주는 것 뿐이다

const Button = styled.a`
  display: inline-block;
  border-radius: 3px;
  padding: 0.5rem 0;
  margin: 0.5rem 1rem;
  width: 11rem;
`;

Styled Component 와 비슷한 기능을 가진 CSS-in-JS 라이브러리로 emotion과 styled-jsx가 있지만, 이 중에서 현재 가장 인기있는 라이브러리는 Styled Component 다

Styled Component 의 특징

Automatic critical CSS
Styled Component 는 화면에 어떤 컴포넌트가 렌더링 되었는지 추적해서 해당하는 컴포넌트에 대한 스타일을 자동으로 삽입한다
따라서 코드를 적절히 분배해 놓으면 사용자가 어플리케이션을 사용할 때 최소한의 코드만으로 화면이 띄워지도록 할 수 있다

No class name bugs
Styled Component 는 스스로 유니크한 className 을 생성한다
이는 className 의 중복이나 오타로 인한 버그를 줄여준다

Easier deletion of CSS
기존에는 더 이상 사용하지 않거나 삭제한 컴포넌트에 해당하는 스타일 속성을 제거하기위해 CSS 파일 안의 className을 이리저리 찾아야 했다
하지만 Styled Component 는 모든 스타일 속성이 특정 컴포넌트와 연결되어 있기 때문에 만약 컴포넌트를 더 이상 사용하지 않아 삭제할 경우 이에 대한 스타일 속성도 함께 삭제된다

Simple dynamic styling
className을 일일이 수동으로 관리할 필요 없이 React 의 props 나 전역 속성을 기반으로 컴포넌트에 스타일 속성을 부여하기 때문에 간단하고 직관적이다

Painless maintenance
컴포넌트에 스타일을 상속하는 속성을 찾아 다른 CSS 파일들을 검색하지 않아도 되기 때문에 코드의 크기가 커지더라도 유지보수가 어렵지 않다

Automatic vendor prefixing
개별 컴포넌트마다 기존의 CSS 를 이용하여 스타일 속성을 정의하면 될 뿐이다
이외의 것들은 Styled Component 가 알아서 처리해 줍니다.

Styled Component 라이브러리를 설치

# with npm
$ npm install --save styled-components
//
# with yarn 
$ yarn add styled-components

Styled Component 에서는 package.json에 다음 코드를 추가하도록 권장하고 있다
아래의 코드를 추가하면 여러 버전의 Styled Component가 설치되어 발생하는 문제를 줄여준다

{
  "resolutions": {
    "styled-components": "^5"
  }
}

Getting Started

Styled Componenttagged template literals 라는 ES6 문법을 이용한다
컴포넌트를 만들 때에 해당 문법을 사용하여 컴포넌트의 스타일 속성을 정의하면 별도의 CSS 파일 없이도 스타일 속성을 지닌 컴포넌트를 만들 수 있다

예제
<Title><Wrapper> 라는 컴포넌트에 스타일 속성을 정의한 후 React 에서 컴포넌트를 사용하는 것과 동일하게 리턴문 안에서 해당 컴포넌트들을 사용하고 있다
예제 코드 안의 주석을 주의 깊게 살펴 보면 <h1> tag 의 스타일 속성은 styled.h1 , <section> tag 의 스타일 속성은 styled.section 를 사용하고 있다
이렇게 Styled Component 를 이용하면 스타일을 정의함과 동시에 해당 스타일을 가진 컴포넌트를 만들 수 있다

import styled from "styled-components";
// <h1> 태그를 렌더링 할 title component를 만듭니다.
const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;
// <section> 태그를 렌더링 할 Wrapper component를 만듭니다.
const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;
export default function App() {
  // 일반적으로 컴포넌트를 사용하는 것처럼 Title과 Wrapper를 사용하시면 됩니다!
  return (
    <Wrapper>
      <Title>Hello World!</Title>
    </Wrapper>
  );
}

Adapting based on props $ Extending Styles

Styled Component 는 스타일 속성을 지닌 컴포넌트를 정의할 때에 함수를 전달하고, 그 함수 안에서 props 를 사용할 수도 있다

<Button> 컴포넌트의 background 와 color 속성은 primary 라는 props 의 전달 여부에 따라 컬러값을 정의하고 있다

// Button component
...
  background: ${(props) => (props.primary ? "palevioletred" : "white")};
  color: ${(props) => (props.primary ? "white" : "palevioletred")};
...
// App component
...
  <Button>Normal</Button>
  <Button primary>Primary</Button>
...

또한 같은 스타일 속성을 지닌 여러개의 컴포넌트들 중 몇 개의 컴포넌트에는 약간의 변화를 주고 싶은 경우도 있을 것이다
이때에는 상속받고자 하는 스타일 속성을 지닌 컴포넌트를 tyled() 로 감싼 뒤, 변경하고 싶은 속성만 새로 정의해 주면 기존 속성을 확장하여 사용할 수 있다

import "./styles.css";
import styled from "styled-components";
//
const Button = styled.button`
  /* Adapt the colors based on primary prop */
  background: ${(props) => (props.primary ? "palevioletred" : "white")};
  color: ${(props) => (props.primary ? "white" : "palevioletred")};
//
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;
//
const Tomato = styled(Button)`
  color: tomato;
  border-color: tomato;
`;
//
export default function App() {
  return (
    <div className="App">
      <Button>Normal</Button>
      <Button primary>Primary</Button>
      <Tomato>Tomato</Tomato>
    </div>
  );
}

Passed props

이번에는 아래 Input 컴포넌트의 color 속성을 주목해서 살펴본다
props 로 color 속성이 전달된 Input 컴포넌트는 해당 color 속성이 글자색에 적용되고, props 가 전달되지 않은 Input 컴포넌트는 기본 색상(여기서는 빨간색)이 적용된 것을 확인할 수 있다
이처럼 컴포넌트에 props 로 스타일 속성이 전달된다면 해당 컴포넌트는 props 로 전달된 속성을 우선 적용하며, 전달되는 속성이 없다면 기본으로 설정된 속성을 적용한다
이는 Styled Component 가 개발자에 의해 설정된 속성과 기본 속성을 구분할 수 있기 때문이다

import styled from "styled-components";
//
// Styled Component로 만들어진 Input 컴포넌트 입니다.
const Input = styled.input`
  padding: 0.5em;
  margin: 0.5em;
  color: ${(props) => props.inputColor || "red"};
  background: papayawhip;
  border: none;
  border-radius: 3px;
`;
//
export default function App() {
  return (
    <div>
      {/* 아래 Input 컴포넌트는 styled component인 Input 컴포넌트에 지정된 inputColor(red)가 적용되었습니다.  */}
      <Input defaultValue="김코딩" type="text" />
      {/* 아래 Input 컴포넌트는 props로 전달된 커스텀 inputColor(blue)가 적용되었습니다. */}
      <Input defaultValue="박해커" type="text" inputColor="blue" />
    </div>
  );
}

DOM reference를 잘 활용할 수 있는 useRef

지금까지 React를 공부하면서 익혔던 내용을 돌이켜보면, React만 가지고 거의 대부분의 프론트엔드 요구사항을 구현할 수 있었다
DOM 지식이 필요 없다고 생각하실 지도 모르지만 React로 모든 개발 요구 사항을 충족할 수는 없다 아래와 같이 DOM 엘리먼트의 주소값을 활용해야 하는 경우 특히 그렇다

  • focus
  • text selection
  • media playback
  • 에니메이션 적용
  • d3.js, greensock 등 DOM 기반 라이브러리 활용

React는 이런 예외적인 상황에서 useRef으로 DOM 노드, 엘리먼트, 그리고 리액트 컴포넌트 주소값을 참조할 수 있다

ex

const 주소값을_담는_그릇 = useRef(참조자료형)
// 이제 주소값을_담는_그릇 변수에 어떤 주소값이든 담을 수 있습니다.
return (
    <div>
      <input ref={주소값을_담는_그릇} type="text" />
        {/* React에서 사용 가능한 ref라는 속성에 주소값을_담는_그릇을 값으로 할당하면*/}
        {/* 주소값을_담는_그릇 변수에는 input DOM 엘리먼트의 주소가 담깁니다. */}
        {/* 향후 다른 컴포넌트에서 input DOM 엘리먼트를 활용할 수 있습니다. */}
    </div>
  );

이 주소값은 컴포넌트가 re-render 되더라도 바뀌지 않는다, 이 특성을 활용하여 아래의 제한된 상황에서 useRef를 활용할 수 있다

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

제시된 상황 제외한 대부분의 경우 기본 리액트 문법을 벗어나 useRef를 남용하는 것은 부적절하고, React의 특징이자 장점인 선언적 프로그래밍 원칙과 배치되기 때문에, 조심해서 사용해야 한다

useRef에서 초기값을 null로 하는 이유

초기값설정에 있어서 의문이 들 수 있다,
초기값을 왜 null로 해야하지?
초기값을 undefined로 하면 안되나? 등

아마 초기값 설정을 안하면 undefined로 자동 설정이 될 것이다

왜 굳이 null로 초기값을 설정하냐고 물어본다면

초기값은 나중에 대처 될 값을 위해 지금은 없는 값으로 설정해준거다
즉 초기값은 지금 null이라는 값이지만 null이라는 값자리에 다른 값이 대처 될꺼야 라는 거다

그럼 값이라는 공간이 있고 그 공간에 다른 값으로 대처가 가능하다는 거다

하지만 undefined로 설정을 해놓는다고 생각해보자 초기값은 값이 아예없어 라고 해석하면 좀 더 이해가 빠르다

즉, null은 지금 값은 없지만 언제든 대처가능한 값이 오게 자리를 만들어 놓은거고
undefined는 자리가 없고 값도 없다라고 생각하자

Styled-Component for Advanced

Styled Component 와 React Component

Styled Component 는 각 element 와 해당 element 에 대한 스타일 규칙의 조합이다

import React from 'react'
import styled from 'styled-components'

const StyledCounter = styled.div`
  /* ... */
`
const Paragraph = styled.p`
  /* ... */
`
const Button = styled.button`
  /* ... */
`

function Counter () {
  const [count, setCount] = useState(0)

  const increment = () => {
    setCount(count + 1)
  }
  const decrement = () => {
    setCount(count - 1)
  }

  return (
    <StyledCounter>
        <Paragraph>{count}</Paragraph>
        <Button onClick={increment}>+</Button>
        <Button onClick={decrement}>-</Button>
      </StyledCounter>
  )
}

export default Counter;

위의 예시 코드와 같이
<StyledCounter /> 컴포넌트에는 styled 라는 접두사가 추가되어 있다
이것을 통해 React 컴포넌트인 <Counter/> 와 Styled Component 인 <StyledCounter /> 가 컴포넌트 이름으로 인해 서로 충돌하지 않고 React Developer Tools 및 Web Inspector 에서 쉽게 구분될 수 있다

Styled Component의 정의는 render 메소드 밖에 정의한다

Styled Component 의 정의는 리턴문 밖에서 이루어져야 한다
만약 Styled Component 가 리턴문 안에서 정의되면 컴포넌트가 리렌더링 될 때마다 스타일 속성을 지닌 컴포넌트가 매번 새로 정의되고, 이는 렌더링 속도 저하에 큰 영향을 끼친다

/* Best Practice */

const StyledWrapper = styled.div`
  /* ... */
`

const Wrapper = ({ message }) => {
  return <StyledWrapper>{message}</StyledWrapper>
}

/* Bad Practice */

const Wrapper = ({ message }) => {
  // WARNING: THIS IS VERY VERY BAD AND SLOW, DO NOT DO THIS!!!
  const StyledWrapper = styled.div`
    /* ... */
  `

  return <StyledWrapper>{message}</StyledWrapper>
}

Pseudoelements, pseudoselectors, and nesting

MDN, Pseudo-classes and pseudo-elements

Pseudo-Element란?

선택자에 추가하는 키워드로, 선택한 요소의 지정된 부분에 스타일을 입힐 수 있다

가상클래스처럼 선택자(selector)에 추가되며, 존재하지 않는 요소를 존재하는 것처럼 부여하여 문서의 특정 부분 선택이 가능하다


Styled Component 는 중첩 스타일링을 위해 SCSS 와 같은 전처리 기능을 자동으로 지원한다 중첩 스타일링을 하기 위해서는 ampersand(&) 기호를 사용하면 된다

import styled from "styled-components";
import React from "react";

const Thing = styled.div`
  color: blue;

  &:hover {
    color: red; // <Thing> when hovered
  }

  & ~ & {
    background: tomato; // <Thing> as a sibling of <Thing>, but maybe not directly next to it
  }

  & + & {
    background: lime; // <Thing> next to <Thing>
  }

  &.apple {
    background: orange; // <Thing> tagged with an additional CSS class ".apple"
  }

  .banana & {
    border: 1px solid; // <Thing> inside another element labeled ".banana"
  }

  .blueberry {
    background-color: yellow; // an element labeled ".blueberry" inside <Thing> without ampersand(&)
  }
`;

export default function App() {
  return (
    <React.Fragment>
      <Thing>기본 Thing Styled-Component입니다.</Thing>
      <Thing>
        Thing Styled-Component와 붙어 있는 Thing Styled-Component입니다. (& + &)
      </Thing>
      <Thing className="apple">
        Thing Styled-Component에 apple 클래스를 적용한 예제입니다. (&.apple)
      </Thing>
      <div>기본 div 태그입니다.</div>
      <Thing>Thing Styled-Component의 형제 컴포넌트입니다. (& ~ &)</Thing>
      <div className="banana">
        <Thing>
          banana 클래스를 가진 엘리먼트를 부모로 가진 Thing
          Styled-Component입니다. (.banana &)
        </Thing>
      </div>
      <Thing>
        <span className="blueberry">
          ampersand(&)를 사용하지 않은 예제입니다.
        </span>
      </Thing>
    </React.Fragment>
  );
}

만약 ampersand(&) 를 사용하지 않으면 평범한 후손 셀렉터처럼 동작한다
이처럼 ampersand(&)는 컴포넌트 안에서 적용되는 CSS 규칙을 확장해 줌으로써, 특히 순수 CSS 와 Styled Component 를 혼용해서 사용해야 하는 경우에 각 스타일 간의 충돌을 피하는 데에 유용하게 사용할 수 있다

import styled from "styled-components";
import React from "react";

const Thing = styled.div`
  color: blue;

  .something {
    border: 2px solid orangered;
    margin: 5px;
    padding: 3px;
  }
  #something-else {
    border: 2px solid black;
    margin: 5px;
    padding: 3px;
  }
`;

export default function App() {
  return (
    <>
      <Thing>
        <div className="something">className을 가지고 있습니다.</div>
        <div id="something-else">id를 가지고 있습니다.</div>
      </Thing>
    </>
  );
}

TailWind CSS

Tailwind CSS
Tailwind Cheat sheet

최근에는 또 새로운 방식으로 CSS를 구성하는 방법들이 떠오르고 있고,
Utility-first CSS로서 각 class가 담당할 스타일을 미리 정의하고 필요한 class들을 조합해서 적용하는 식으로 사용하는 방법이다

기본 HTML, CSS 코드작성 예시

<div class="chat-notification">
  <div class="chat-notification-logo-wrapper">
    <img class="chat-notification-logo" src="/img/logo.svg" alt="ChitChat Logo">
  </div>
  <div class="chat-notification-content">
    <h4 class="chat-notification-title">ChitChat</h4>
    <p class="chat-notification-message">You have a new message!</p>
  </div>
</div>

<style>
  .chat-notification {
    display: flex;
    max-width: 24rem;
    margin: 0 auto;
    padding: 1.5rem;
    border-radius: 0.5rem;
    background-color: #fff;
    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 
		0 10px 10px -5px rgba(0, 0, 0, 0.04);
  }
  .chat-notification-logo-wrapper {
    flex-shrink: 0;
  }
  .chat-notification-logo {
    height: 3rem;
    width: 3rem;
  }
  .chat-notification-content {
    margin-left: 1.5rem;
    padding-top: 0.25rem;
  }
  .chat-notification-title {
    color: #1a202c;
    font-size: 1.25rem;
    line-height: 1.25;
  }
  .chat-notification-message {
    color: #718096;
    font-size: 1rem;
    line-height: 1.5;
  }
</style>

Tailwind CSS를 활용한 코드 작성 예시

<div class="max-w-sm mx-auto flex p-6 bg-white rounded-lg shadow-xl">
  <div class="flex-shrink-0">
    <img class="h-12 w-12" src="/img/logo.svg" alt="ChitChat Logo">
  </div>
  <div class="ml-6 pt-1">
    <h4 class="text-xl text-gray-900 leading-tight">ChitChat</h4>
    <p class="text-base text-gray-600 leading-normal">You have a new message!</p>
  </div>
</div>

CSS는 프로젝트를 하면서 익혀봐야 할 꺼같다, 지금 현재 너무 방대하고, 구현하는 방법이 너무 여러가지라 나에게 맞는 방법과 코드를 익힐 필요성이 있다

profile
즐겁게 살자

0개의 댓글