전체 글 보기

패스워드 입력 필드의 마스킹 커스텀하기

profile icon

브라우저와 운영체제마다 다르게 보이는 패스워드 마스킹 모양을 커스텀 폰트와 unicode-range로 통일하기

#CSS
마지막 수정일:

패스워드 입력 필드에서 black circle U+2022(•)U+25CF(●) 두 유니코드가 서로 다른 글리프로 표시되어, 브라우저와 운영체제 환경에 따라 마스킹 모양이 달라지는 문제를 겪었다. 이 글에서는 커스텀 폰트를 활용해 두 유니코드에 동일한 글리프를 적용하는 과정을 공유한다.

어느날 디자인 시스템에서 패스워드 마스킹 모양을 접속 기기와 상관없이 통일을 시켜달라는 요청사항이 들어왔다.

브라우저는 패스워드 입력 필드의 문자를 마스킹할 때 U+2022(•) 또는 U+25CF(●) 중 하나를 사용한다. 어떤 유니코드를 쓰는지는 브라우저와 운영체제마다 달라서, 같은 폰트라도 환경에 따라 마스킹 모양이 제각각으로 보일 수 있다는 점이 문제가 되었다.

처음에는 해당 글을 참고하여 font-nello라는 웹서비스를 사용해 각 유니코드에 아이콘을 지정한 커스텀 폰트를 만드는 방식을 시도했다.

그런데 font-nello에서는 하나의 아이콘을 여러 유니코드에 동시에 지정할 수 없었다. 어쩔 수 없이 U+2022 용 폰트와 U+25CF용 폰트를 각각 만든 뒤, unicode-range로 적용 범위를 나눠서 패스워드 필드에 불러왔다.

css
@font-face {
  font-family: "uni2022";
  src: url("/fonts/uni2022.woff2") format("woff2");
  font-style: normal;
  font-weight: normal;
  unicode-range: U+2022;
}

@font-face {
  font-family: "uni25cf";
  src: url("/fonts/uni25cf.woff2") format("woff2");
  font-style: normal;
  font-weight: normal;
  unicode-range: U+25cf;
}

input[type="password"]:not(:placeholder-shown) {
  font-family: uni2022, uni25cf, Pretendard, sans-serif;
  font-size: 13px;
  letter-spacing: 4px;
}

이 방식은 두 가지 문제를 남겼다.

문제 1. 폰트 로드 시점 차이로 인한 깜빡임

폰트를 2개 로드하다 보니 네트워크 상황에 따라 로드 완료 시점이 달라졌다. 패스워드를 입력하는 도중에 폰트가 교체되면서 글리프가 바뀌는 시각적 깜빡임이 생겼다.

문제 2. 폰트 크기 불일치

패스워드 필드에서 마스킹 글자 외 나머지 텍스트는 Pretendard로 표시된다. 그런데 커스텀 폰트의 글리프 크기가 Pretendard와 맞지 않아서, 모바일에서 특히 어색하게 보였다. 결국 font-sizeletter-spacing을 임의로 지정해서 억지로 맞추는 수밖에 없었다.

css
input[type="password"]:not(:placeholder-shown) {
  font-family: uni2022, uni25cf, Pretendard, sans-serif;
  font-size: 13px; 
  letter-spacing: 4px; 
}

첫 번째 시도에서 발생한 두 문제를 해결하기 위해 아래와 같은 시도를 했다.

이 문제들을 해결하기 위해서 기존 Pretendard 폰트에서 U+2022 글리프를 추출한 뒤, 그것을 U+25CF 위치에 복사해서 두 유니코드에 대한 글리프만 담은 bulletOnly 라는 폰트 파일 하나를 만들었다.

그리고 그 폰트를 아래와 같이 적용했다.

css
@font-face {
  font-family: "bulletOnly";
  src: url("/fonts/bulletOnly.woff2") format("woff2");
  font-style: normal;
  font-weight: normal;
  unicode-range: U+2022, U+25cf;
}

input[type="password"]:not(:placeholder-shown) {
  font-family: bulletOnly, Pretendard, sans-serif;
}

unicode-range에 두 유니코드를 함께 지정하면, 해당 유니코드에 대해서만 bulletOnly 폰트가 선택적으로 적용된다. 나머지 문자는 Pretendard가 그대로 처리하기 때문에, 별도의 font-sizeletter-spacing 조정이 필요 없어 졌다.

폰트 파일이 2개에서 1개로 줄면서 용량도 약 4KB에서 888bytes로 크게 감소했다. 로드 속도가 빨라진 덕분에 입력 도중 폰트가 바뀌는 깜빡임도 사라졌다. Pretendard를 기반으로 글리프를 복사했기 때문에 크기가 자연스럽게 맞아, 억지로 지정했던 font-sizeletter-spacing도 걷어낼 수 있었다.

전체 글 보기