본문 바로가기
SPA/React

[React] Tailwind 사용하기 (2) - StyledComponents와 CSS 적용 비교하기

by J4J 2023. 5. 22.
300x250
반응형

안녕하세요. J4J입니다.

 

이번 포스팅은 tailwind 사용하기 두 번째인 styledComponents와 CSS 적용 비교하기에 대해 적어보는 시간을 가져보려고 합니다.

 

 

 

이전 글

 

[React] Tailwind 사용하기 (1) - 개념 및 설정

 

 

반응형

 

 

들어가기에 앞서

 

이전 글에서도 간단하게 확인해 볼 수 있는 것처럼 tailwind에 css를 적용할 땐 tailwind에서 기본적으로 정의해 둔 class 명을 이용해야 합니다.

 

색상, 크기, 여백 등의 모든 css들이 기본적인 css 구조에서 스타일을 적용하기 위해 사용하던 방식과 모두 상이하기에 처음 tailwind를 사용하시는 분들이라면 tailwind 공식 문서를 당분간 필수적으로 참고하시는 것을 추천드립니다.

 

 

 

그리고 이번 글에서는 일반적으로 자주 사용되는 css들에 대해 tailwind에서 사용하는 방법을 styledComponets와 비교해보려고 합니다.

 

동일한 디자인을 적용하기 위해 사용되는 방식의 차이점이 어떻게 변경되는지 간단하게 확인해 보겠습니다.

 

 

 

 

색상

 

// styledComponents

import React from 'react';
import styled, { keyframes } from 'styled-components';

const App = () => {
    return (
        <div>
            {/* 색상 */}
            <div>
                <FontColor>글자 색상</FontColor>
                <BackgroundColor>배경 색상</BackgroundColor>
            </div>
        </div>
    );
};

export default App;

const FontColor = styled.p`
    color: #3b82f6;
`;

const BackgroundColor = styled.p`
    background-color: #ef4444;
`;

 

// tailwind

import React from 'react';

const App = () => {
    return (
        <div>
            {/* 색상 */}
            <div>
                <p className="text-blue-500">글자 색상</p>
                <p className="bg-red-500">배경 색상</p>
            </div>
        </div>
    );
};

export default App;

 

 

 

 

글자 크기, 두께 등

 

// styledComponents

import React from 'react';
import styled, { keyframes } from 'styled-components';

const App = () => {
    return (
        <div>
            {/* 글자 크기, 두께 등 */}
            <div>
                <FontSize>글자 크기</FontSize>
                <FontWeight>글자 두께</FontWeight>
                <LetterSpacing>문자 간격</LetterSpacing>
                <LineHeight>줄 높이</LineHeight>
            </div>
        </div>
    );
};

export default App;

const FontSize = styled.p`
    font-size: 1.125rem;
`;

const FontWeight = styled.p`
    font-weight: bold;
`;

const LetterSpacing = styled.p`
    letter-spacing: -0.05em;
`;

const LineHeight = styled.p`
    line-height: 2rem;
`;

 

// tailwind

import React from 'react';

const App = () => {
    return (
        <div>
            {/* 글자 크기, 두께 등 */}
            <div>
                <p className="text-lg">글자 크기</p>
                <p className="font-bold">글자 두께</p>
                <p className="tracking-tighter">문자 간격</p>
                <p className="leading-8">줄 높이</p>
            </div>
        </div>
    );
};

export default App;

 

 

 

 

여백

 

// styledComponents

import React from 'react';
import styled, { keyframes } from 'styled-components';

const App = () => {
    return (
        <div>
            {/* 여백 */}
            <div>
                <Margin>외부 여백</Margin>
                <Padding>내부 여백</Padding>
            </div>
        </div>
    );
};

export default App;

const Margin = styled.p`
    margin: 1rem;
`;

const Padding = styled.p`
    padding: 1rem;
`;

 

// tailwind

import React from 'react';

const App = () => {
    return (
        <div>
            {/* 여백 */}
            <div>
                <p className="m-4">외부 여백</p>
                <p className="p-4">내부 여백</p>
            </div>
        </div>
    );
};

export default App;

 

 

 

 

너비, 높이

 

// styledComponents

import React from 'react';
import styled, { keyframes } from 'styled-components';

const App = () => {
    return (
        <div>
            {/* 너비, 높이 */}
            <div>
                <Width>너비</Width>
                <MinWidth>최소 너비</MinWidth>
                <Height>높이</Height>
                <MaxHeight>최대 높이</MaxHeight>
            </div>
        </div>
    );
};

export default App;

const Width = styled.p`
    width: 5rem;
`;

const MinWidth = styled.p`
    min-width: 100%;
`;

const Height = styled.p`
    height: 3rem;
`;

const MaxHeight = styled.p`
    max-height: 100%;
`;

 

// tailwind

import React from 'react';

const App = () => {
    return (
        <div>
            {/* 너비, 높이 */}
            <div>
                <p className="w-20">너비</p>
                <p className="min-w-full">최소 너비</p>
                <p className="h-12">높이</p>
                <p className="max-h-full">최대 높이</p>
            </div>
        </div>
    );
};

export default App;

 

 

 

 

레이아웃

 

// styledComponents

import React from 'react';
import styled, { keyframes } from 'styled-components';

const App = () => {
    return (
        <div>
            {/* 레이아웃 */}
            <div>
                <Overflow>Overflow</Overflow>
                <Position>Position</Position>
                <BoxSizing>box sizing</BoxSizing>
            </div>
        </div>
    );
};

export default App;

const Overflow = styled.p`
    overflow: hidden;
`;

const Position = styled.p`
    position: absolute;
    top: 0;
    left: 0;
`;

const BoxSizing = styled.p`
    box-sizing: border-box;
`;

 

// tailwind

import React from 'react';

const App = () => {
    return (
        <div>
            {/* 레이아웃 */}
            <div>
                <p className="overflow-hidden">Overflow</p>
                <p className="absolute top-0 left-0">Position</p>
                <p className="box-border">box sizing</p>
            </div>
        </div>
    );
};

export default App;

 

 

 

 

Border

 

// styledComponents

import React from 'react';
import styled, { keyframes } from 'styled-components';

const App = () => {
    return (
        <div>
            {/* Border */}
            <div>
                <BorderBase>두께 색상 등 기본 스타일</BorderBase>
                <BorderRadius>반경</BorderRadius>
            </div>
        </div>
    );
};

export default App;

const BorderBase = styled.p`
    border: 4px solid #94a3b8;
`;

const BorderRadius = styled.p`
    border: 4px solid black;
    border-radius: 0.375rem;
`;

 

// tailwind

import React from 'react';

const App = () => {
    return (
        <div>
            {/* Border */}
            <div>
                <p className="border-4 border-slate-400 border-solid">두께 색상 등 기본 스타일</p>
                <p className="border-4 border-black border-solid rounded-md">반경</p>
            </div>
        </div>
    );
};

export default App;

 

 

 

 

Flex, Grid

 

// styledComponents

import React from 'react';
import styled, { keyframes } from 'styled-components';

const App = () => {
    return (
        <div>
            {/* Flex, Grid */}
            <div>
                <FlexBase>
                    <p>Flex</p>
                    <p>기본 스타일</p>
                </FlexBase>

                <GridBase>
                    <p>Grid</p>
                    <p>기본 스타일</p>
                </GridBase>
            </div>
        </div>
    );
};

export default App;

const FlexBase = styled.div`
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 0.5rem;
`;

const GridBase = styled.div`
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: center;
    gap: 0.5rem;
`;

 

// tailwind

import React from 'react';

const App = () => {
    return (
        <div>
            {/* Flex, Grid */}
            <div>
                <div className="flex flex-col justify-center items-center gap-2">
                    <p>Flex</p>
                    <p>기본 스타일</p>
                </div>

                <div className="grid grid-cols-2 items-center gap-2">
                    <p>Grid</p>
                    <p>기본 스타일</p>
                </div>
            </div>
        </div>
    );
};

export default App;

 

 

 

 

Transition

 

// styledComponents

import React from 'react';
import styled, { keyframes } from 'styled-components';

const App = () => {
    return (
        <div>
            {/* Transition */}
            <div>
                <Transition>Transition 기본 스타일</Transition>
            </div>
        </div>
    );
};

export default App;

const Transition = styled.p`
    transition: 0.5s ease-out;
`;

 

// tailwind

import React from 'react';

const App = () => {
    return (
        <div>
            {/* Transition */}
            <div>
                <p className="duration-500 ease-out">Transition 기본 스타일</p>
            </div>
        </div>
    );
};

export default App;

 

 

 

 

Hover, Focus 등

 

// styledComponents

import React from 'react';
import styled, { keyframes } from 'styled-components';

const App = () => {
    return (
        <div>
            {/* Hover, Focus 등 */}
            <div>
                <Hover>Hover</Hover>
                <Focus placeholder="Focus" />
            </div>
        </div>
    );
};

export default App;

const Hover = styled.p`
    &:hover {
        color: #0ea5e9;
    }
`;

const Focus = styled.input`
    &:focus {
        color: #0ea5e9;
    }
`;

 

// tailwind

import React from 'react';

const App = () => {
    return (
        <div>
            {/* Hover, Focus 등 */}
            <div>
                <p className="hover:text-sky-500">Hover</p>
                <input className="focus:text-sky-500" placeholder="Focus" />
            </div>
        </div>
    );
};

export default App;

 

 

 

 

반응형

 

// styledComponents

import React from 'react';
import styled, { keyframes } from 'styled-components';

const App = () => {
    return (
        <div>
            {/* 반응형 */}
            <div>
                <Responsive>반응형</Responsive>
            </div>
        </div>
    );
};

export default App;

const Responsive = styled.p`
    @media (min-width: 640px) {
        color: #ef4444;
    }

    @media (min-width: 1024px) {
        color: #3b82f6;
    }
`;

 

// tailwind

import React from 'react';

const App = () => {
    return (
        <div>
            {/* 반응형 */}
            <div>
                <p className="sm:text-red-500 lg:text-blue-500">반응형</p>
            </div>

        </div>
    );
};

export default App;

 

 

 

 

사용자 임의값

 

사용자 임의값은 css를 적용하려고 할 때 tailwind에서 정의해 둔 값이 존재하지 않아 사용자가 임의로 값을 넣어 사용하는 것을 의미합니다.

 

모든 케이스에 대해 tailwind에서 제공해주지 않기 때문에 부분적으로 임의값이 필요한 경우 다음과 같이 적용해 볼 수 있습니다.

 

// styledComponents

import React from 'react';
import styled, { keyframes } from 'styled-components';

const App = () => {
    return (
        <div>
            {/* 사용자 임의값 */}
            <div>
                <FontColorArbitary>글자 색상 임의값</FontColorArbitary>
                <FontSizeArbitary>글자 크기 임의값</FontSizeArbitary>
                <MarginArbitary>외부 여백 임의값</MarginArbitary>
            </div>
        </div>
    );
};

export default App;

const FontColorArbitary = styled.p`
    color: #a3a3a3;
`;

const FontSizeArbitary = styled.p`
    font-size: 7px;
`;

const MarginArbitary = styled.p`
    margin: 5px;
`;

 

// tailwind

import React from 'react';

const App = () => {
    return (
        <div>
            {/* 사용자 임의값 */}
            <div>
                <p className="text-[#a3a3a3]">글자 색상 임의값</p>
                <p className="text-[7px]">글자 크기 임의값</p>
                <p className="m-[5px]">외부 여백 임의값</p>
            </div>
        </div>
    );
};

export default App;

 

 

 

 

하위 요소 조작

 

하위 요소 조작은 부모에 의해 자식의 css가 영향받는 것을 의미합니다.

 

tailwind에서는 "& > p"와 같이 scss 문법을 사용해 볼 수도 있고 tailwind에서 제공해 주는 "group-{modifier}"를 활용해 볼 수 있습니다.

 

"group-{modifier}"는 부모 상태 기반의 스타일 적용을 의미하며 사용하는 방법은 부모 class에 group 또는 group/{name}의 형태를 작성해 주고 자식 class에 영향받고자 하는 부모 class의 group명을 이용하여 원하는 기능을 넣어주시면 됩니다.

 

// styledComponents

import React from 'react';
import styled, { keyframes } from 'styled-components';

const App = () => {
    return (
        <div>
            {/* 하위 요소 조작 */}
            <div>
                <ChildSelector>
                    <p>Selector 사용</p>
                </ChildSelector>
                <ChildParentSingle>
                    <p>Parent 기반 - 단일 사용</p>
                </ChildParentSingle>
                <ChildParentMultiple1>
                    <ChildParentMultiple2>
                        <p>Parent 기반 - 복수 사용1</p>
                        <p>Parent 기반 - 복수 사용2</p>
                    </ChildParentMultiple2>
                </ChildParentMultiple1>
            </div>
        </div>
    );
};

export default App;

const ChildSelector = styled.div`
    & > p:nth-of-type(2n-1) {
        color: #3b82f6;
    }
`;

const ChildParentSingle = styled.div`
    &:hover {
        & > p {
            color: #ef4444;
        }
    }
`;

const ChildParentMultiple1 = styled.div`
    &:hover {
        & > div > p:nth-of-type(1) {
            color: #ef4444;
        }
    }
`;

const ChildParentMultiple2 = styled.div`
    &:hover {
        & > p:nth-of-type(2) {
            color: #3b82f6;
        }
    }
`;

 

// tailwind

import React from 'react';

const App = () => {
    return (
        <div>
            {/* 하위 요소 조작 */}
            <div>
                <div className="[&>p:nth-child(2n-1)]:text-blue-500">
                    <p>Selector 사용</p>
                </div>
                <div className="group">
                    <p className="group-hover:text-red-500">Parent 기반 - 단일 사용</p>
                </div>
                <div className="group/aaa">
                    <div className="group/bbb">
                        <p className="group-hover/aaa:text-red-500">Parent 기반 - 복수 사용1</p>
                        <p className="group-hover/bbb:text-blue-500">Parent 기반 - 복수 사용2</p>
                    </div>
                </div>
            </div>
        </div>
    );
};

export default App;

 

 

 

 

애니메이션

 

tailwind에서 기본적으로 제공해 주는 애니메이션이 있지만 사용자가 원하는 애니메이션을 추가하기 위해서는 tailwind 설정 파일인 tailwind.config.js에 정의해줘야 합니다.

 

애니메이션 또한 공통화하여 사용되기 때문에 한번 정의를 하면 여러 파일들에 재사용이 가능하다는 점 참고해 주시면 됩니다.

 

// styledComponents

import React from 'react';
import styled, { keyframes } from 'styled-components';

const App = () => {
    return (
        <div>
            {/* 애니메이션 */}
            <div>
                <Animation>애니메이션</Animation>
            </div>
        </div>
    );
};

export default App;

const animationKeyframes = keyframes`
    0%, 100% {
        font-size: 3rem;
    }

    50% {
        font-size: 1rem;
    }
`;

const Animation = styled.p`
    animation: 0.5s ease-out ${animationKeyframes};
`;

 

// tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
    content: ['./src/**/*.{js,ts,jsx,tsx}'],
    theme: {
        extend: {
            keyframes: {
                animationKeyframes: {
                    '0%, 100%': { fontSize: '3rem' },
                    '50%': { fontSize: '1rem' },
                },
            },

            animation: {
                addAnimation: '0.5s ease-out animationKeyframes',
            },
        },
    },
    plugins: [],
};


// tailwind

import React from 'react';

const App = () => {
    return (
        <div>
            {/* 애니메이션 */}
            <div>
                <p className="animate-addAnimation">애니메이션</p>
            </div>
        </div>
    );
};

export default App;

 

 

 

 

 

 

 

 

이상으로 tailwind 사용하기 두 번째인 styledComponents와 CSS 적용 비교하기에 대해 간단하게 알아보는 시간이었습니다.

 

읽어주셔서 감사합니다.

 

 

 

728x90
반응형

댓글