← EonsFlow

hidden 속성을 걸었는데 요소가 계속 보입니다 — display 한 줄이 이기는 이유

2026년 8월 31일

el.hidden = true를 분명히 실행했고, 개발자 도구로 봐도 hidden 속성이 붙어 있습니다. 그런데 화면에는 그대로 보입니다. 범인은 CSS 파일에 있던 display: grid 한 줄이었습니다.

재현되는 최소 코드

<style>
  .cardgrid { display: grid; grid-template-columns: repeat(3, 1fr); }
</style>

<div class="cardgrid" hidden>
  <div>카드</div>
</div>

hidden이 붙어 있는데도 이 요소는 화면에 보입니다. 속성을 잘못 건 것도, 자바스크립트가 안 돈 것도 아닙니다.

원인은 우선순위가 아니라 출처입니다

hidden 속성이 요소를 숨기는 건 HTML 명세가 마법을 부려서가 아닙니다. 브라우저 기본 스타일시트(user-agent stylesheet)에 다음 규칙이 들어 있기 때문입니다.

/* 브라우저가 기본으로 들고 있는 규칙 */
[hidden] { display: none; }

여기서 오해가 생깁니다. [hidden]은 속성 선택자라 클래스 선택자와 명시도가 같고, 뒤에 온 쪽이 이길 것 같습니다. 하지만 이 비교는 애초에 성립하지 않습니다. CSS는 명시도를 따지기 전에 선언의 출처부터 정렬합니다.

순서출처
1 (가장 약함)브라우저 기본[hidden] { display: none }
2사용자 설정접근성 설정 등
3작성자 스타일.cardgrid { display: grid }
4 (가장 강함)작성자 !importantdisplay: none !important

내 CSS 파일에 쓴 display: grid는 3번, 브라우저의 display: none은 1번입니다. 명시도를 비교할 기회조차 없이 작성자 스타일이 이깁니다. 클래스에 display를 한 번이라도 지정하면 그 요소의 hidden은 그때부터 무력해집니다.

display 를 쓰는 모든 클래스가 잠재적 지뢰입니다

display: flex, display: grid, display: block 전부 해당합니다. 레이아웃을 잡으려고 무심코 쓴 한 줄이 나중에 hidden을 무력화합니다. 그리고 이 조합은 처음 만들 때는 멀쩡하고, 나중에 숨김 기능을 붙일 때 터집니다.

고치는 방법

display를 지정하는 클래스에는 [hidden] 짝을 같이 만들어 둡니다. 속성 선택자를 클래스와 함께 쓰면 명시도가 더 높아지므로 확실하게 이깁니다.

.cardgrid { display: grid; }
.cardgrid[hidden] { display: none; }   /* 짝을 만든다 */

프로젝트 전체에 한 번에 깔고 싶다면 전역 규칙을 하나 두는 방법도 있습니다.

[hidden] { display: none !important; }

다만 !important는 나중에 정당하게 display를 바꿔야 할 때 다시 걸림돌이 됩니다. 범위를 아는 프로젝트가 아니라면 클래스마다 짝을 만드는 쪽이 예측 가능합니다.

더 뼈아팠던 건 테스트였습니다

이 버그는 자동 검증을 통과한 채로 배포됐습니다. 검증 코드가 이렇게 생겼기 때문입니다.

// 통과했지만 아무것도 보장하지 못한 검사
expect(el.hidden).toBe(true);

el.hidden속성이 걸렸는지만 알려줍니다. 화면에서 사라졌는지는 모릅니다. 숨김을 검증하려면 실제로 계산된 스타일을 봐야 합니다.

// 화면에서 사라졌는지를 검사한다
expect(getComputedStyle(el).display).toBe("none");
속성이 맞다 ≠ 화면에 안 보인다

상태를 검사할 때는 "내가 건 값"이 아니라 "브라우저가 최종적으로 계산한 값"을 봐야 합니다. 이 구분을 놓치면 검증은 계속 초록불인데 사용자만 문제를 봅니다.

정리

이 글은 EonsFlow가 자동화 도구를 만들며 겪은 내용을 정리한 것입니다. "통과했는데 실제로는 안 되던" 다른 사례로 lstrip("www.")은 접두사를 지우지 않습니다도 함께 보시면 좋습니다.