퀴즈로 풀어보는 CSS z-index 속성의 3가지 포인트

웹 페이지가 다이나믹해지고 요소들의 배치가 자유로워지면, 때때로 서로의 위치가 겹치는 요소들이 생기기 마련입니다. 이 때 어느 것을 위에 표시할 것인가를 제어하는 CSS 속성이 다름 아닌 z-index입니다. 그만큼 자주 접하게 되는 속성입니다만, 한편으로는 오해하기 쉬운 몇가지 특징을 가진 속성이기도 합니다.

이번 포스팅에서는 z-index에 대한 중요한 포인트를 3가지 퀴즈를 통해 알아봅니다. (이 질문은 제가 신입 개발자들을 교육할 때 실제로 사용하고 있는 질문이기도 합니다.) 이 3가지 질문에 대해 정확하게 답을 하고 원리를 설명하실 수 있다면, 실무에서 만나는 대부분의 상황에서는 z-index 속성을 사용하는 데에는 큰 문제가 없으실 것입니다.

z-index의 정확한 사양에 대해서는 CSS Specification의 9.9.1 Specifying the stack level: the ‘z-index’ property 항목에서 다루고 있습니다. 좀더 자세한 정보가 필요하실 때에 함께 읽어보시기 바랍니다.

 

Q1. CSS가 아래와 같이 작성되어 있을 때, HTML 코드에 있는 3개의 <div>를 상위에 표시되는 순서대로 나열하세요.

#first
{
	z-index		: 30;
	width		: 200px;
	height		: 200px;
	background	: #3366cc;
}
#second
{
	z-index		: 20;
	width		: 200px;
	height		: 200px;
	margin-top	: -100px;
	background	: #cc3333;
}
#third
{
	z-index		: 50;
	width		: 200px;
	height		: 200px;
	margin-top	: -100px;
	margin-left	: 100px;
	background	: #ffaa33;
}
<div id="first">
	1st Box
</div>
<div id="second">
	2nd Box 
	<div id="third">3rd Box</div>
</div>

3개의 <div> 태그가 있습니다. 크기는 모두 가로세로 200픽셀입니다. 2번째와 3번째 <div>는 margin-top 속성이 -100픽셀로 되어 있어, 원래 위치보다 위로 100픽셀 이동하여 보일 것입니다. <div>를 상위에 나오는 순서대로 나열하면 어떻게 될까요?

 

A1. 3rd – 2nd – 1st

z-index 함정퀴즈 #1 정답

많은 분들의 예상과 다르게 정답은 왼쪽과 같습니다. 2nd보다 1st가 z-index 속성에 입력된 값이 더 높기 때문에, 이 정답은 상당히 의외로 느껴질 수 있습니다. 여기에 우리가 기억해야 하는 z-index의 첫 번째 함정이 있습니다.

z-index 값을 지정하기 위해서는 해당 요소의 position 속성이 relative, absolute, fixed 중 하나여야만 한다.

CSS Specification를 살펴보면 z-index 속성의 적용대상은 positioned elements, 즉 position 속성이 설정된 요소로 제한되어 있습니다. 그러나 문제에 등장한 3개의 <div>는 어느 것 하나도 position 속성이 지정되어 있지 않았습니다. 이처럼 position 속성이 지정되지 않은 상태라면, 이 요소들은 z-index가 0인 것처럼 작동합니다. HTML 소스 상에서 나중에 등장하는 요소가 앞에 나온 요소를 덮어버리게 됩니다. 그림을 그릴 때 앞서 칠한 물감을 나중에 칠한 물감이 덮는 것과 같이 말이죠.

 

Q2. CSS가 아래와 같이 작성되어 있을 때, HTML 코드에 있는 3개의 <div>를 상위에 표시되는 순서대로 나열하세요.

#first
{
	position	: relative; 
	z-index		: 30;
	width		: 200px;
	height		: 200px;
	background	: #3366cc;
}
#second
{
	position	: relative; 
	z-index		: 20;
	width		: 200px;
	height		: 200px;
	margin-top	: -100px;
	background	: #cc3333;
}
#third
{
	position	: relative;
	z-index		: 50;
	width		: 200px;
	height		: 200px;
	margin-top	: -100px;
	margin-left	: 100px;
	background	: #ffaa33;
}
<div id="first">
	1st Box
</div>
<div id="second">
	2nd Box 
	<div id="third">3rd Box</div>
</div>

이번 문제에서 등장한 소스코드는 첫 번째 문제의 소스코드에서 각 <div>에 position 속성만 추가로 지정한 것입니다. position 속성은 모두 relative로 설정되었고, top과 left 속성은 지정되지 않았으므로 위치의 변동은 없을 것입니다. <div>를 상위에 나오는 순서대로 나열하면 어떻게 될까요?

 

A2. 1st – 3rd – 2nd

z-index 함정퀴즈 #2 정답이번에야말로 z-index가 큰 순서대로 표시될 것이라고 예상하셨다면, 다시 한 번 예상이 빗나간 결과를 발견하게 됩니다. 우리가 기억해야 하는 z-index의 두 번째 함정이 여기에 있기 때문입니다.

z-index의 값은 같은 depth의 요소끼리 비교하는 것이 원칙이다.

z-index 값은 같은 depth에 있는 형제 요소(Siblings) 간에 비교하여 상하를 결정하는 것이 원칙이며, 자식 요소는 부모 요소의 비교결과를 따라가게 됩니다. 위 코드의 경우에는 형제간인 1st와 2nd를 비교하여 이미 1st가 상위에 있는 것으로 결론내렸기 때문에, 2nd의 자식 요소인 3rd는 아무리 높은 z-index 값을 주어도 1st보다 상위에 표시되지 않습니다.

 

Q3. CSS가 아래와 같이 작성되어 있을 때, HTML 코드에 있는 3개의 <div>를 상위에 표시되는 순서대로 나열하세요.

#first
{
	position	: relative; 
	z-index		: 30;
	width		: 200px;
	height		: 200px;
	background	: #3366cc;
}
#second
{
	position	: relative; 
	/*z-index	: 20;*/
	width		: 200px;
	height		: 200px;
	margin-top	: -100px;
	background	: #cc3333;
}
#third
{
	position	: relative;
	z-index		: 50;
	width		: 200px;
	height		: 200px;
	margin-top	: -100px;
	margin-left	: 100px;
	background	: #ffaa33;
}
<div id="first">
	1st Box
</div>
<div id="second">
	2nd Box 
	<div id="third">3rd Box</div>
</div>

두 번째 문제의 소스코드에서 #second 요소의 z-index 값을 주석처리 하였습니다. 그 외에는 어떠한 변경된 내용도 없습니다. <div>를 상위에 나오는 순서대로 나열하면 어떻게 될까요?

 

A3. 3rd – 1st – 2nd

z-index 함정퀴즈 #3 정답

이 문제의 경우, 1st – 3rd – 2nd라는 오답이 나오기 쉽습니다. 오답의 원인은 바로 z-index의 기본값이 정수 0일 것이라고 잘못 추측하는 데에 있습니다. 우리가 기억해야 하는 z-index의 세 번째 함정은 z-index의 기본값에 관한 것입니다.

z-index의 기본값은 auto이며, 이 경우 브라우저는 그 요소를 제쳐두고 자식 요소의 z-index 값을 비교대상으로 삼는다.

z-index에 아무런 값이 지정되지 않은 경우, 기본값은 auto가 됩니다. z-index가 auto로 지정된 요소는 z-index가 0으로 입력된 것처럼 작동하는 동시에, z-index 값의 비교대상을 자식 요소에게 넘겨줍니다. 위 코드에서는 2nd의 z-index가 auto이므로, 1st와 z-index를 비교할 대상은 3rd가 됩니다. 비교 결과 3rd의 z-index가 1st의 z-index보다 더 높으므로, 결과적으로 3rd가 가장 위에 표시되는 결과를 보게 됩니다.

그렇다면 우리는 왜 z-index의 기본값을 0으로 잘못 알고 있을까요. 이유는 바로 Internet Explorer 7의 버그 때문입니다. 당시 웹 브라우저 시장을 장악하고 있던 IE7에는 한 가지 버그가 있었는데, 그것이 다름 아닌 z-index의 기본값을 auto가 아닌 0으로 지정하는 것이었습니다. 이로 인하여 많은 웹 개발자들에게 잘못된 경험이 축적되었고 지금에 이르게 된 것입니다.

 

정리

금번 포스팅의 내용을 토대로 z-index의 주요 포인트를 정리하면, 아래와 같습니다.

  1. z-index 속성은 대게 정수값을 가지며, 높은 숫자를 가진 요소가 상위에 표시됩니다. 같은 z-index 간에는 HTML 코드상 나중에 등장하는 요소가 상위에 표시됩니다.
  2. z-index 값을 지정하기 위해서는 해당 요소의 position 속성이 relative, absolute, fixed 중 하나여야만 합니다.
  3. z-index의 값은 같은 depth의 요소끼리 비교하는 것이 원칙입니다.
  4. z-index의 기본값은 auto이며, 이 경우 브라우저는 그 요소를 제쳐두고 자식 요소의 z-index 값을 비교대상으로 삼습니다. (단, Internet Explorer 7에서는 z-index의 기본값이 0인 버그가 있습니다.)