팀 프로젝트 도중
input
태그의type
을date
로 설정하여 날짜를 입력받는 기능을 만들어야했다.
이 때, 자동으로 브라우저마다 설정된 캘린더 아이콘이 나오게 되는데,
필자는 이를 커스텀하고 싶었다. 그 방법을 알아보자!
type
이 date
인 input
태그<input
type='date'
placeholder='날짜를 선택해주세요.'
required
value={props.date}
onChange={props.changeHandler}
id='dateSelect'
min={props.isFullRange ? undefined : getDate()}
/>
사실 간단하지는 않다.
설정 값에 대한 이유를 주석에 달아 놓았으므로, 읽어 내려가시면 좋을 것 같습니다.
input[type='date'] {
border: none; // 테두리 설정은 본인 맘대로
position: relative; // 캘린더 아이콘을 클릭해야만 달력이 보이기 때문에 이 영역 자체를 제어하기 위해 설정
width: 100%;
padding: 10px;
background: url(../../../assets/Calendar.svg) no-repeat right 10px center /
35px auto; // 배경에 커스텀 아이콘을 넣어주자! x축은 오른쪽에서부터 10px 떨어지게 하고, y축은 가운데 정렬하고, width 35px에 height auto라는 크기를 부여한다.
background-color: #bbbbbb;
box-shadow: 2px 2px 7px rgba(0, 0, 0, 0.2);
border-radius: 8px;
text-align: center;
font-size: 100%;
margin-bottom: 20px;
}
// 실제 캘린더 아이콘을 클릭하는 영역을 의미하는 선택자
// 이 영역을 확장해서 input의 어떤 곳을 클릭해도 캘린더를 클릭한 것과 같은 효과를 만들자!
input[type='date']::-webkit-calendar-picker-indicator {
position: absolute; // 이를 설정하기 위해 사전에 relative를 설정한 것이다.
left: 0;
top: 0;
width: 100%;
height: 100%;
background: transparent; // 배경은 투명하게,
color: transparent; // 글자도 투명하게! 이 두 설정을 통해 캘린더 아이콘을 사라지게 만든다.
cursor: pointer;
}
// type이 date인 input의 placeholder를 커스텀하기 위한 선택자
// 기본적으로 type date인 input은 placeholder가 먹히지 않기 때문이다!
input[type='date']::before {
content: attr(placeholder); // input 태그의 placeholder라는 속성값을 가져와서 content로 사용한다. 보통은 placeholder보다는 data-placeholder라는 커스텀 속성을 만들어서 사용하시는 것 같다.
width: 100%;
height: 100%;
}
// input에 어떠한 유효값이 입력된 상태인지 확인하는 선택자
// 날짜를 선택하면 유효값이 입력된다.
// 이 속성을 활용하고자 한다면 반드시 태그에 required 속성을 달아줘야한다.
input[type='date']:valid::before {
display: none; // 유효값이 입력된 경우 before에 있는 것을 사라지게 한다. 즉, placeholder를 사라지게 한다.
}
결과는 다음과 같다.
평소의 필자였다면 input
태그와 별도의 아이콘 태그를 사용하여 기존 캘린더를 덮었을 것 같은데,
이 방법은 위험하다.
왜?
캘린더 아이콘을 클릭해야 날짜를 선택할 수 있기 때문이다.
그러면 ref
걸어서 클릭되게 하면 해결 할 수 있지않느냐는 질문이 나올 수 있다.(React에서)
그 방법은 통하지 않는다.(매우 어렵다가 더 맞는 표현일 것 같다.)
input
을 클릭하는게 아니라 input
에 있는 캘린더 아이콘을 클릭해야하는 것이기 때문이다.
JS로 이를 구현하는 것은 매우 어렵게 돌아가는 방법이라고 생각된다.
필자는 CSS로 처리할 수 있는건 최대한 CSS로 처리하는 것을 선호하기 때문에,
굳이 JS를 사용하는 방법으로는 구현하지 않을 것 같다.
설명이 너무 깔끔합니다 🥹