Study/React

[React] styled-components로 다크모드 만들기 (placeholder, after, before...)

hyjang 2024. 7. 12. 18:24
728x90

들어가며


현재 리액트로 만든 노트 앱에 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 주의할 점

내가 사용하면서 유의해야했던 점을 정리했다.

 

  1. css에 적용된 스타일은 styled-components에 적용되지 않는다.
    - styled-components를 통해 적용할 스타일은 적용이 안되는 오류가 있을 수 있으니 css에서 지우도록 한다.

  2. 변화를 주고싶은 스타일 외에 고정 스타일은 css에 적는다.
    - 고정스타일은 태그, 컴포넌트마다 디자인이 다르기 때문에 묶어줄 필요가 없었다. 
      (퍼블리싱으로 치면 html 태그안에 인라인으로 하나하나 style을 넣는것과 비슷했다.)

  3. useContext를 사용하여 theme를 가져온다면, 적용할 태그의 속성값으로 theme={theme}을 잊지 말고 적용하기
    - 이건 계속 쓰다보면 꼭 한번씩 잊어버리기 때문에 유의해야한다.

 

 


이런 방법으로 다크모드 구현을 마쳤고, 그 외 로컬스토리지에 현재 모드를 저장하여 새로고침하거나 다시 프로젝트를 불러와도 유지될 수 있도록 하여 노트 앱을 완성시켰다.