styled Components 패키지는 사용하면 특정 스타일이 첨부된 컴포넌트를 구축할 수 있도록 도와주는 패키지입니다.
특정 스타일이 첨부되는 컴포넌트에서만 영향을 미치고 다른 컴포넌트에는 전혀 영향을 미치지 않습니다.
우선 styled Components 접속하시거나 위의 명령어를 터미널에 입력하여 패키지를 다운로드합니다.
기존 스타일링
import React from 'react';
import './Button.css';
const Button = props => {
return (
<button type={props.type} className="button" onClick={props.onClick}>
{props.children}
</button>
);
};
export default Button;
기존에는 Button 컴포넌트를 생성하여 CSS를 import 해 사용해주었습니다.
styled Components 패키지를 사용하여 기존의 스타일링을 변경해겠습니다.
사용방법
import styled from "styled-components";
우선 styled Components에서 styled를 import 해줍니다.
const Button = styled.button``;
다음으로 기존 방식처럼 상수 Button을 생성해주지만 해당 상수는 더 이상 함수형 컴포넌트를 저장하지 않기 때문에
위의 코드 예시처럼 작성해줍니다.
styled는 styled Components에서 import 한 객체이고 button은 styled 객체의 메서드입니다.
styled 객체가 호출할 수 있는 메서드는 html에 있는 모든 요소에 대한 메서드입니다.
저의 경우 button 컴포넌트를 생성하는 것이 목표이기 때문에 button 메서드를 호출해주었습니다.
styled Components 패키지에서는 button()으로 메서드를 호출하는 대신 뒤에 백 틱( `` )을 붙여 호출합니다.
이렇게 사용한 button 메서드는 새로운 Button 컴포넌트를 반환하게 됩니다.
const Button = styled.button`
.button {
font: inherit;
padding: 0.5rem 1.5rem;
border: 1px solid #8b005d;
color: white;
background: #8b005d;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.26);
cursor: pointer;
}
.button:focus {
outline: none;
}
.button:hover,
.button:active {
background: #ac0e77;
border-color: #ac0e77;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.26);
}
`;
위의 코드처럼 백 틱 사이에는 여러 줄의 문자열을 작성할 수 있습니다.
기존의 import 했던 CSS의 코드를 백 틱 사이에 넣어주었습니다.
여기서 문제는 button 메서드는 Button 컴포넌트를 반환만 하지 클래스를 따로 지정을 해주지 않기 때문에
백 틱 사이의 CSS 코드가 적용이 안된다는 것입니다.
대신 백 틱 사이에 전달한 CSS 코드를 button 메서드에 직접적으로 영향을 주게 할 수 있습니다.
const Button = styled.button`
font: inherit;
padding: 0.5rem 1.5rem;
border: 1px solid #8b005d;
color: white;
background: #8b005d;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.26);
cursor: pointer;
&:focus {
outline: none;
}
&:hover,
&:active {
background: #ac0e77;
border-color: #ac0e77;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.26);
}
`;
위의 코드처럼 선택자를 제거하면 백 틱 사이의 CSS 코드는 메서드가 호출되어 반환하는 Button 컴포넌트에 추가되며
상수 Button까지 영향을 받게 됩니다.
가상 선택자의 경우는 styled Components 패키지에서 지원하는 & 기호와 사용합니다.
& 기호는 생성한 컴포넌트에 대해 가상 선택자를 사용하겠다고 패키지에 선언하는 것을 의미합니다.
즉 "버튼에 focus가 있으면 스타일을 적용해줘"를 의미하게 되는 것입니다.
만약 .button label처럼 button 클래스 안에 있는 label 태그에 접근을 하고 싶은 경우에도 & 기호를 사용해주시면 됩니다.
( & label )
이렇게 생성된 Button 컴포넌트에는 기존에 전달하는 props가 적용되게 됩니다.
기존의 button에는 onClick 속성을 추가해서 type을 설정할 수 있는데
생성된 Button 컴포넌트는 styled Components에 의해 button 메서드가 내부적으로 사용하고 있습니다.
기존 코드
return (
<form onSubmit={formSubmitHandler}>
<div className={`form-control ${!isValid ? "invalid" : ""}`}>
{/* isValid가 false이면 글자색 red, true이면 글자색 black */}
<label>Course Goal</label>
<input type="text" onChange={goalInputChangeHandler} />
</div>
<Button type="submit">Add Goal</Button>
</form>
);
변경 코드
const FormControl = styled.div`
margin: 0.5rem 0;
&.invalid label {
color: red;
}
&.invalid input {
border-color: red;
background-color: salmon;
}
& label {
font-weight: bold;
display: block;
margin-bottom: 0.5rem;
}
& input {
display: block;
width: 100%;
border: 1px solid #ccc;
font: inherit;
line-height: 1.5rem;
padding: 0 0.25rem;
}
& input:focus {
outline: none;
background: #fad0ec;
border-color: #8b005d;
}
`;
return (
<form onSubmit={formSubmitHandler}>
// styled-component 적용--------------------------------------------
<FormControl className={className={!isValid ? "invalid" : ""}}>
//-----------------------------------------------------------------
{/* isValid가 false이면 글자색 red, true이면 글자색 black */}
<label>Course Goal</label>
<input type="text" onChange={goalInputChangeHandler} />
</FormControl>
<Button type="submit">Add Goal</Button>
</form>
);
};
기존 코드에서 className에 전달했던 form-control은 제거해주어도 적용이 되게 됩니다.
기존 코드에서 className에 삼항 연산자로 전달했던
${!isValid ? "invalid" : ""} 는 템플릿 리터럴, 즉 백 틱 없이 전달이 가능해집니다.
동적으로 스타일링하는 또 다른 방법을 아래 코드 예시와 함께 정리해보겠습니다.
return (
<form onSubmit={formSubmitHandler}>
<FormControl invalid={!isValid}>
<label>Course Goal</label>
<input type="text" onChange={goalInputChangeHandler} />
</FormControl>
<Button type="submit">Add Goal</Button>
</form>
);
styled Components 패키지를 사용해 생성한 컴포넌트에 props를 전달해주었습니다.
const FormControl = styled.div`
margin: 0.5rem 0;
& label {
font-weight: bold;
display: block;
margin-bottom: 0.5rem;
color: ${(props) => [props.invalid ? "red" : "black"]};
}
& input {
display: block;
width: 100%;
border: 1px solid ${(props) => (props.invalid ? "red" : "#ccc")};
background: ${(props) => (props.invalid ? "red" : "transparent")};
font: inherit;
line-height: 1.5rem;
padding: 0 0.25rem;
}
& input:focus {
outline: none;
background: #fad0ec;
border-color: #8b005d;
}
`;
${} 사이에는 함수를 받을 수 있고 해당 함수는 전달받은 props를 인자로 받습니다.
전달받은 props, invalid가 false이면 "red"가 적용되고, true이면 기존의 컬러가 적용되게 동적으로 스타일링을 해주었습니다.
이렇게 props에 기반하여 스타일 일부를 동적으로 변경하는 것이 가능합니다.
'React' 카테고리의 다른 글
불 필요한 <div> 제거하기 (Fragment) (0) | 2022.10.03 |
---|---|
CSS 모듈을 사용한 스타일 적용 (0) | 2022.10.02 |
동적으로 클래스 설정하기(State와 삼항연산자) (0) | 2022.10.01 |
동적으로 인라인 스타일 설정하기(State와 삼항연산자) (0) | 2022.10.01 |
여러개의 State 하나로 합치기 (2) | 2022.09.25 |