정리/CSS

CSS visibility 상속과 재정의 규칙 정리

워로디스 2026. 4. 29. 22:58

1. 핵심 결론

visibility초기값(initial value)이 visible이고,** 상속되는 속성(inherited property)** 이다. CSS 2.1 명세의 visibility 정의도 Initial: visible, Inherited: yes로 명시한다. (W3C)

따라서 자식 요소에 visibility선언하지 않으면 부모의 visibility 값을 상속받는다. CSS Cascade 명세상, cascade 결과 값이 없을 때 상속 속성은 부모 요소를 통해 default 값을 얻고, 비상속 속성은 initial value를 사용한다. (W3C)

가장 중요한 규칙은 다음이다.

.parent {
  visibility: hidden;
}

.child {
  visibility: visible;
}
.parent: 안 보임
.child: 보임

부모가 visibility: hidden이어도, 자식이 visibility: visible을 직접 가지면 자식은 보일 수 있다. 명세와 MDN 모두 hidden 요소의 자손도 visibility: visible이면 보인다고 설명한다. (W3C)

2. 용어 정리

2.1 initial value

속성 정의표에 적힌 초기값이다.

visibility의 initial value는 다음이다.

visibility: visible;

즉, 아래 선언은:

.child {
  visibility: initial;
}

실질적으로 다음과 같다.

.child {
  visibility: visible;
}

2.2 inherited value

부모 요소의 computed value를 물려받은 값이다. CSS Cascade 명세는 어떤 요소의 inherited value가 부모 요소의 computed value라고 정의한다. 루트 요소처럼 부모가 없으면 inherited value는 initial value가 된다. (W3C)

예:

.parent {
  visibility: hidden;
}

.child {
  /* visibility 선언 없음 */
}
.child는 부모의 computed value인 hidden을 상속받음

2.3 “기본값”이라는 말

CSS 스펙에서 엄밀히 구분해야 한다.

표현 정확한 의미
초기값 initial value
선언하지 않았을 때 적용되는 값 defaulting 결과
상속값 parent의 computed value
inherit 부모 값을 명시적으로 사용하라는 CSS-wide keyword

따라서 visibility에 대해 정확한 표현은 이것이다.

visibility의 initial value는 visible이다.
하지만 visibility는 inherited property이므로,
자식에게 선언이 없으면 부모의 computed value를 상속받는다.

“값을 안 썼을 때의 기본 적용값”이라는 의미라면, 자식 요소에서는 inherit처럼 동작한다고 말할 수 있다.
하지만 스펙 용어로 “visibility의 초기값이 inherit이다”라고 하면 틀리다.

3. 선언별 동작 규칙

3.1 선언 없음

.parent {
  visibility: hidden;
}

.child {
  /* visibility 선언 없음 */
}

결과:

.parent: hidden
.child: hidden

이유:

visibility는 상속 속성이므로,
.child는 부모의 visibility 값을 상속받는다.

3.2 visibility: inherit

.parent {
  visibility: hidden;
}

.child {
  visibility: inherit;
}

결과:

.parent: hidden
.child: hidden

inherit은 부모의 computed value를 명시적으로 사용한다. CSS Cascade 명세도 inherit이 cascaded value이면 specified value와 computed value가 inherited value가 된다고 정의한다. (W3C)

선언 없음과 결과는 같을 수 있지만 의미는 다르다.

경우 의미
선언 없음 상속 속성이므로 defaulting 과정에서 부모 값 사용
visibility: inherit 부모 값을 명시적으로 사용

3.3 visibility: visible

.parent {
  visibility: hidden;
}

.child {
  visibility: visible;
}

결과:

.parent: 안 보임
.child: 보임

이 경우 자식은 부모의 hidden을 상속받지 않고, 자신에게 선언된 visible 값을 사용한다.

3.4 visibility: hidden

.box {
  visibility: hidden;
}

결과:

.box는 보이지 않음
.box의 레이아웃 공간은 유지됨

visibility: hidden은 박스를 그리지 않지만 레이아웃에는 영향을 준다. 박스 생성을 아예 막으려면 display: none을 사용해야 한다. (W3C)

3.5 visibility: initial

.parent {
  visibility: hidden;
}

.child {
  visibility: initial;
}

결과:

.child: visible

이유:

initial은 부모 값을 쓰는 것이 아니라
해당 속성의 initial value를 사용한다.

visibility의 initial value는 visible이다.

3.6 visibility: unset

.parent {
  visibility: hidden;
}

.child {
  visibility: unset;
}

결과:

.child: hidden

unset은 해당 속성이 상속 속성이면 inherit처럼, 비상속 속성이면 initial처럼 동작한다. visibility는 상속 속성이므로 이 경우 inherit처럼 처리된다. (W3C)

4. 대표 예시

4.1 부모 hidden, 자식 선언 없음

.parent {
  visibility: hidden;
}
<div class="parent">
  부모
  <div class="child">자식</div>
</div>

결과:

부모: 안 보임
자식: 안 보임

자식은 부모의 hidden을 상속받는다.

4.2 부모 hidden, 자식 visible

.parent {
  visibility: hidden;
}

.child {
  visibility: visible;
}
<div class="parent">
  부모
  <div class="child">자식</div>
</div>

결과:

부모: 안 보임
자식: 보임

자식은 visible을 직접 선언했으므로 부모의 hidden을 덮어쓴다.

4.3 부모 hidden, 자식 inherit

.parent {
  visibility: hidden;
}

.child {
  visibility: inherit;
}
<div class="parent">
  부모
  <div class="child">자식</div>
</div>

결과:

부모: 안 보임
자식: 안 보임

자식은 부모 값을 명시적으로 따른다.

4.4 부모 hidden, 자식 initial

.parent {
  visibility: hidden;
}

.child {
  visibility: initial;
}
<div class="parent">
  부모
  <div class="child">자식</div>
</div>

결과:

부모: 안 보임
자식: 보임

initialvisibility의 initial value인 visible을 사용한다.

5. display: none과의 차이

5.1 visibility: hidden

.parent {
  visibility: hidden;
}

.child {
  visibility: visible;
}
부모: 안 보임
자식: 보임
공간: 유지됨

visibility: hidden은 박스를 보이지 않게 할 뿐, 레이아웃 공간은 유지한다. 그리고 자손이 visibility: visible이면 보일 수 있다. (W3C)

5.2 display: none

.parent {
  display: none;
}

.child {
  visibility: visible;
}
부모: 안 보임
자식: 안 보임
공간: 없음

display: none은 박스 생성을 억제한다. 따라서 자식이 visibility: visible이어도 렌더링될 박스 자체가 없다. (W3C)

6. 최종 요약

visibility의 initial value는 visible이다.
visibility는 inherited property이다.
자식이 visibility를 선언하지 않으면
부모의 computed value를 상속받는다.
부모 hidden + 자식 선언 없음
→ 자식 hidden
부모 hidden + 자식 inherit
→ 자식 hidden
부모 hidden + 자식 visible
→ 자식 visible
부모 hidden + 자식 initial
→ 자식 visible
부모 hidden + 자식 unset
→ 자식 hidden