웹 개발을 하다 보면 특정 요소를 화면에서 숨겨야 하는 경우가 자주 발생합니다. 이때 많은 개발자가 display 속성과 visibility 속성 사이에서 고민하게 되는데요. 겉보기에는 두 속성 모두 요소를 '숨기는' 것처럼 보이지만, 실제 동작 방식에는 중요한 차이가 있습니다.
display:none과 visibility:hidden의 핵심 차이
- CSS display: none − 해당 요소를 문서에서 아예 렌더링하지 않습니다. 요소가 차지하던 공간까지 완전히 사라지므로, 마치 요소가 처음부터 존재하지 않았던 것처럼 동작합니다.
- CSS visibility: hidden − 요소는 문서에 그대로 렌더링되고 공간도 그대로 유지되지만, 사용자 눈에는 보이지 않습니다. 즉, 투명해진 것처럼 제자리에 공간을 차지한 채 남아 있습니다.
두 속성의 차이를 표로 정리하면 다음과 같습니다.
| 구분 | display: none | visibility: hidden |
|---|---|---|
| 렌더링 여부 | 요소를 렌더링하지 않음 | 요소를 렌더링함 |
| 공간 점유 | 공간을 차지하지 않음 | 공간을 그대로 차지함 |
| 레이아웃 영향 | 주변 요소가 재배치됨 | 레이아웃 변화 없음 |
| 주요 활용 | 요소를 완전히 제거할 때 | 요소를 잠시 가릴 때 |
예제 1: CSS display:none
다음 예제에서는 버튼을 클릭하면 primary 클래스를 가진 색상 블록들이 display: none 처리되어 화면에서 완전히 사라집니다.
<!DOCTYPE html>
<html>
<head>
<title>CSS Display None</title>
<style>
form {
width:70%;
margin: 0 auto;
text-align: center;
}
* {
padding: 2px;
margin:5px;
box-sizing: border-box;
}
input[type="button"] {
border-radius: 10px;
}
.child{
display: inline-block;
height: 40px;
width: 40px;
color: white;
border: 4px solid black;
}
.child:nth-of-type(1){
background-color: #FF8A00;
}
.child:nth-of-type(2){
background-color: #F44336;
}
.child:nth-of-type(3){
background-color: #C303C3;
}
.child:nth-of-type(4){
background-color: #4CAF50;
}
.child:nth-of-type(5){
background-color: #03A9F4;
}
.child:nth-of-type(6){
background-color: #FEDC11;
}
</style>
</head>
<body>
<form>
<fieldset>
<legend>CSS-Display-None</legend>
<div id="container">
<div class="child"></div><div class="child primary"></div><div class="child"></div><div class="child"></div><div class="child primary"></div><div class="child primary"></div>
</div><br>
<input type="button" value="Hide Primary Colors" onclick="displayNone()">
</fieldset>
</form>
<script>
var primaryColor = document.getElementsByClassName('primary');
function displayNone(){
for(var i=0; i<3; i++)
primaryColor[i].style.display = 'none';
}
</script>
</body>
</html>
실행 결과
'Hide Primary Colors' 버튼을 클릭하기 전의 화면입니다.

버튼을 클릭한 후에는 primary 클래스를 가진 블록들이 문서에서 완전히 제거되고, 남은 블록들이 빈 자리를 메우며 다시 배치되는 것을 확인할 수 있습니다.

예제 2: CSS visibility:hidden
이번에는 동일한 구조에서 visibility: hidden을 적용해 보겠습니다.
<!DOCTYPE html>
<html>
<head>
<title>CSS Visibility hidden</title>
<style>
form {
width:70%;
margin: 0 auto;
text-align: center;
}
* {
padding: 2px;
margin:5px;
box-sizing: border-box;
}
input[type="button"] {
border-radius: 10px;
}
.child{
display: inline-block;
height: 40px;
width: 40px;
color: white;
border: 4px solid black;
}
.child:nth-of-type(1){
background-color: #FF8A00;
}
.child:nth-of-type(2){
background-color: #F44336;
}
.child:nth-of-type(3){
background-color: #C303C3;
}
.child:nth-of-type(4){
background-color: #4CAF50;
}
.child:nth-of-type(5){
background-color: #03A9F4;
}
.child:nth-of-type(6){
background-color: #FEDC11;
}
</style>
</head>
<body>
<form>
<fieldset>
<legend>CSS-Visibility-hidden</legend>
<div id="container">
<div class="child"></div><div class="child primary"></div><div class="child"></div><div class="child"></div><div class="child primary"></div><div class="child primary"></div>
</div><br>
<input type="button" value="Hide Primary Colors" onclick="visibilityHidden()">
</fieldset>
</form>
<script>
var primaryColor = document.getElementsByClassName('primary');
function visibilityHidden(){
for(var i=0; i<3; i++)
primaryColor[i].style.visibility = 'hidden';
}
</script>
</body>
</html>
실행 결과
'Hide Primary Colors' 버튼을 클릭하기 전의 화면입니다.

버튼을 클릭한 후에도 블록들의 위치는 그대로 유지됩니다. 다만 primary 클래스를 가진 블록들은 보이지 않게 되어, 마치 빈 공간처럼 자리를 차지한 채 남아 있는 것을 확인할 수 있습니다.

정리: 어떤 속성을 선택해야 할까?
두 속성의 결과를 비교해 보면 명확한 차이를 알 수 있습니다. display: none은 요소를 완전히 문서 흐름에서 제거하기 때문에 주변 요소의 레이아웃이 재배치되지만, visibility: hidden은 요소의 자리를 그대로 유지하면서 화면에서만 가려줍니다.
따라서 요소를 일시적으로 감추되 레이아웃이 흔들리는 것을 원하지 않는다면 visibility: hidden이 적합하고, 요소를 완전히 제거하는 것과 같은 효과가 필요하다면 display: none을 사용하는 것이 좋습니다. 또한 애니메이션이나 전환 효과를 적용할 계획이라면 opacity나 transform과 함께 활용하는 방법도 고려해 볼 수 있습니다.