[React] styled-components로 다크모드 만들기 (placeholder, after, before...)
들어가며
현재 리액트로 만든 노트 앱에 styled-components 라이브러리를 활용하여 다크모드를 추가하고 있다.
theme.js를 만들어 컬러칩을 설정했고, 라이트모드, 다크모드마다 색을 다르게 적용했다.
이 중 input 태그(검색어 입력란)에 placeholder의 색을 바꾸려고 한다.
styled-components으로 input::placeholder 색상 바꾸기
보통 css에서 placeholder의 색상을 수정할 때는 after, before와 같은 방법으로 가상 선택자를 지정할 수 있다.
css에서는 콜론이 두개(::placehoder) 쓰이고, styled-components도 동일하게 사용한다.
//css
input::placeholder { color:#333}
//style-components
&::placeholder {color:#333}
styled-components에서는 &를 사용하여 선택자를 지정해준다.
&는 현재 요소라는 뜻이다. 여기서는 thing이라고 뜻한다.
// Thing 컴포넌트 위에 마우스가 올라갈때
&:hover
// Thing의 바로 옆은 아니지만 형제요소일 때
& ~ &
// Thing이 바로 옆에 붙어있을 때
& + &
// Thing이 something이라는 클래스를 갖고있을 때
&.something
// something-else라는 클래스를 가진 친구안에 있을 때
.something-else &
styled-components로 placeholder를 꾸미는 방법은 두가지가 있다.
1. 디자인만 적용하기
const StyledInput =styled.input`
color:${(p)=>p.theme.colors.defaultFont}; // input value 색상
&::placeholder {
color:${(p)=>p.theme.colors.defaultFont}; //placeholder 색상
}
`
(...)
<StyledInput theme={theme} type="text" onChange={handleOnChangeSearch} className="search" placeholder="검색어를 입력해주세요." />
자식 태그를 꾸밀때 처럼 해당 styled 컴포넌트 안에 &::placeholder를 추가해준다.
2. 디자인&placeholder 내용 적용하기
placeholder 값을 수정해야할 때, 동일한 input이 여러개라면 하나하나 모두 수정해야하지만
styled-components로 묶어줬다면 해당 styled만 수정해주면 돼서 유지보수 측면에서 좋다😎
적용하는 방법은 위의 방법과 동일하지만 placeholder라는 속성(attribute)을 추가해줄 것이다.
이때 기존 styled.input에 attrs를 추가해준다.
const StyledInput =styled.input.attrs({
placeholder:"검색어를 입력해주세요.",
type:"text",
className:"search"
})`
color:${(p)=>p.theme.colors.defaultFont};
border-bottom:1px solid ${(p)=>p.theme.colors.defaultLight}; //섞어서 사용도 가능하다.
&::placeholder {
color:${(p)=>p.theme.colors.defaultFont};
}
`
(...)
<StyledInput theme={theme} onChange={handleOnChangeSearch} />
💡 여기서 attrs는 속성 객체를 지정한다.
보통 태그의 type이나 className같은 속성값을 전부 styled-components로 묶어줄 수 있다.
만약 StyledInput 태그가 여러개가 쓰였다면 하나하나 수정해야하고 코드가 복잡하고 지저분해보일 수 있는데,
하나로 묶어주면 한번에 수정하면서 깔끔하게 정리할 수 있다.
styled-components으로 after, before 디자인 바꾸기
//css
button::after { background:#fff}
//styled-components
&:after{ background:#fff}
css에서 after의 디자인을 수정하려면 콜론을 두개(::after)사용하지만 styled-components에서는 하나만(:after) 사용한다.
이제 기존의 css로 지정해뒀던 다크모드 변경 버튼의 after부분만 styled를 추가한다.
//css
.App .theme_btn{ padding:5px; border-radius: 50px; width:140px; height:35px; font-size: 14px; position:relative; transition:0.5s; margin-top:15px; }
.App .theme_btn::after{content: ''; display: block; width:15px; height:15px; border-radius: 50%; position:absolute; top:calc(50% - 7.5px); left:8px; transition:0.5s;}
.App .theme_btn.dark::after{ left:calc(100% - 23px); }
//js
(...)
const StyledDarkBtn = styled.button`
background:${(p)=>p.theme.colors.listBox};
color:${(p)=>p.theme.colors.defaultFont};
&:after{
background:${(p)=>p.theme.colors.darkModeBtn};
}
`
(...)
<StyledDarkBtn onClick={onDarkMode} className={!darkMode ? 'theme_btn' : 'theme_btn dark'}>{!darkMode ? "Light Mode" : "Dark Mode"}</StyledDarkBtn>
💡styled-components는 기존의 css는 유지하면서 추가로 스타일을 지정한다.
또 기존의 button 태그를 styled 변수로 교체해주어도 태그에 속해있던 속성값이나 삼항연산자 등의 기능도 잘 작동한다.
styled-components 주의할 점
내가 사용하면서 유의해야했던 점을 정리했다.
- css에 적용된 스타일은 styled-components에 적용되지 않는다.
- styled-components를 통해 적용할 스타일은 적용이 안되는 오류가 있을 수 있으니 css에서 지우도록 한다. - 변화를 주고싶은 스타일 외에 고정 스타일은 css에 적는다.
- 고정스타일은 태그, 컴포넌트마다 디자인이 다르기 때문에 묶어줄 필요가 없었다.
(퍼블리싱으로 치면 html 태그안에 인라인으로 하나하나 style을 넣는것과 비슷했다.) - useContext를 사용하여 theme를 가져온다면, 적용할 태그의 속성값으로 theme={theme}을 잊지 말고 적용하기
- 이건 계속 쓰다보면 꼭 한번씩 잊어버리기 때문에 유의해야한다.
이런 방법으로 다크모드 구현을 마쳤고, 그 외 로컬스토리지에 현재 모드를 저장하여 새로고침하거나 다시 프로젝트를 불러와도 유지될 수 있도록 하여 노트 앱을 완성시켰다.