UI가 어색해 보일 때는 대개 거창한 이유가 아니라 사소한 습관 몇 가지가 겹친 탓입니다. 이번에는 자주 반복되는 실수를 before로 보여 주고, 고친 after를 나란히 두겠습니다. 아래 코드는 그대로 붙여 확인할 수 있습니다.

16.1 고정 높이로 글자 자르기

박스 높이를 픽셀로 못 박으면 글자가 길어질 때 잘리거나 넘칩니다. 흔한 실수부터 봅니다.


.card {
height: 120px;
overflow: hidden;
}


내용이 예상보다 길면 아래가 싹 잘립니다. 높이는 최소값만 정하고 내용이 늘어날 여지를 줍니다.


.card {
min-height: 120px;
padding: 16px;
}


min-height는 짧을 땐 자리를 지키고 길 땐 알아서 늘어납니다. 어떤 내용이 와도 잘리지 않습니다.

16.2 포커스 외곽선 지우기

outline: none은 보기엔 깔끔하지만 키보드 사용자의 길잡이를 없앱니다. 가장 흔하고 뼈아픈 실수입니다.


button:focus {
outline: none;
}


이러면 탭으로 이동할 때 지금 어디인지 알 수 없습니다. 지우는 대신 더 나은 외곽선으로 바꿔 줍니다.


button:focus-visible {
outline: 2px solid #2563eb;
outline-offset: 2px;
}


키보드로 왔을 때만 또렷한 테두리가 나타나고 마우스 클릭 땐 조용합니다. 접근성과 깔끔함을 둘 다 얻습니다.

16.3 대비 낮은 옅은 회색 글자

연한 회색 글자는 디자인 시안에선 세련돼 보여도 실제 화면에선 잘 안 읽힙니다.


.hint {
color: #cbd5e1;
background: #fff;
}


흰 배경 위 연회색은 눈이 아파 읽기를 포기하게 만듭니다. 최소한의 대비를 확보한 색으로 낮춥니다.


.hint {
color: #6b7280;
background: #fff;
}


같은 회색 계열이라도 이 정도는 되어야 부담 없이 읽힙니다. 옅음과 안 읽힘은 다릅니다.

16.4 클릭 영역이 글자만 한 링크

작은 아이콘이나 짧은 링크를 글자 크기만큼만 누르게 두면 손끝이 자주 빗나갑니다.


.tag {
font-size: 12px;
}


글자만 표적이라 모바일에서 누르기 어렵습니다. 여백을 넣어 눌리는 판을 키웁니다.


.tag {
font-size: 12px;
padding: 8px 12px;
display: inline-block;
}


안쪽 여백이 보이는 크기와 별개로 누를 면적을 넓혀 줍니다. 손가락이 조금 어긋나도 제대로 눌립니다.

16.5 간격을 margin으로 덕지덕지

자식마다 margin을 다르게 주면 나중에 순서만 바꿔도 간격이 어긋납니다. 부모에서 gap 하나로 다스립니다.


.list {
display: flex;
flex-direction: column;
gap: 12px;
}


자식은 여백을 신경 쓸 필요 없이 놓이기만 하면 됩니다. 항목을 더하거나 빼도 간격이 늘 일정합니다.

16.6 색 값을 곳곳에 흩뿌리기

같은 파랑을 파일 여기저기 직접 적으면 색을 바꿀 때 하나라도 놓칩니다. 변수로 모아 한 곳에서 다룹니다.


:root {
--brand: #2563eb;
--text: #111827;
}
.btn {
background: var(--brand);
}
.link {
color: var(--brand);
}


브랜드 색을 바꿀 일이 생기면 --brand 한 줄만 고치면 됩니다. 버튼과 링크가 동시에 따라옵니다.

16.7 가로 스크롤 흘리기

넓은 요소나 100vw 사용이 스크롤바 폭과 겹쳐 가로 스크롤을 만들곤 합니다. 가장 티 나는 실수입니다.


.row {
display: flex;
gap: 12px;
}
.row img {
max-width: 100%;
height: auto;
}
body {
overflow-x: hidden;
}


이미지에 max-width: 100%를 걸어 부모를 넘지 않게 하고, 혹시 모를 넘침은 overflow-x로 막습니다. 어느 화면에서도 옆으로 밀리지 않습니다.

16.8 버튼과 링크를 뒤섞기

이동은 링크로, 동작은 버튼으로 나눠야 하는데 div에 클릭만 걸어 두는 경우가 많습니다. 키보드로 닿지도, 새 탭으로 열리지도 않습니다.


<div class="link">더 보기</div>


겉보기엔 되지만 탭 이동과 엔터가 안 먹습니다. 이동이면 a, 동작이면 button으로 제 역할을 맡깁니다.


<a class="link" href="/more">더 보기</a>
<button type="button" class="btn">저장</button>


a는 키보드로 닿고 새 탭 열기도 되며, button은 엔터와 스페이스로 눌립니다. 올바른 태그를 쓰는 것만으로 접근성이 따라옵니다.

16.9 placeholder를 라벨 대신 쓰기

입력칸 안내를 placeholder로만 두면 타이핑을 시작하는 순간 사라져 무슨 칸인지 잊게 됩니다.


<input placeholder="이메일">


글자를 넣으면 안내가 지워져 나중에 헷갈립니다. 라벨을 따로 두고 placeholder는 예시로만 씁니다.


<label for="email">이메일</label>
<input id="email" placeholder="[email protected]">


라벨은 입력 중에도 남아 있어 무슨 칸인지 늘 보입니다. for와 id를 묶어 라벨을 눌러도 칸에 커서가 갑니다.

16.10 hover에만 정보 숨기기

중요한 동작을 마우스를 올려야만 보이게 하면 터치 기기에서는 아예 닿지 못합니다.


.card .actions {
opacity: 0;
}
.card:hover .actions {
opacity: 1;
}


손가락에는 hover가 없어 이 버튼들이 유령이 됩니다. 항상 보이게 두되 평소엔 옅게, 강조는 다른 방식으로 줍니다.


.card .actions {
opacity: .6;
transition: opacity .15s;
}
.card:hover .actions {
opacity: 1;
}


평소에도 60% 투명도로 보여 터치로 닿을 수 있고, 마우스를 올리면 또렷해집니다. 누구도 기능을 잃지 않습니다.

16.11 px로만 글자 크기 못 박기

모든 글자를 px로 고정하면 사용자가 브라우저에서 글자를 키워도 꿈쩍하지 않습니다. 본문 크기는 상대 단위로 여지를 둡니다.


body {
font-size: 16px;
}
.article {
font-size: 14px;
}


고정 px는 확대 설정을 무시해 접근성을 해칩니다. rem을 쓰면 기준 크기를 바꿀 때 전체가 함께 조절됩니다.


html {
font-size: 100%;
}
.article {
font-size: 1rem;
line-height: 1.6;
}


rem은 사용자가 정한 기본 글자 크기를 기준으로 삼아 확대에 반응합니다. 줄 간격까지 넉넉히 주면 긴 글도 편하게 읽힙니다.

16.12 정리

흔한 실수는 대개 고정 높이, 지워 버린 포커스, 낮은 대비, 좁은 클릭 영역, 흩어진 색처럼 작은 습관에서 옵니다. 각각을 min-height, focus-visible, 변수, gap으로 바꾸면 화면이 눈에 띄게 단단해집니다. 큰 재주보다 이 작은 것들을 안 틀리는 쪽이 더 오래 갑니다.