마크업
position 속성의 값으로 요소의 배치 방법을 선언하고, 이후 오프셋 속성으로 위치를 정의한다.
div {
position: relative;
top: 0px;
left: 0px;
}
position 속성의 값
static | position 속성을 정의하지 않은 상태와 동일한 기본값으로, 오프셋 값과 z-index 값이 아무런 영향도 주지 않는다. |
---|---|
relative | 요소 자신을 기준으로 오프셋을 적용하는 상대 위치로 배치한다. |
absolute | position 속성값으로 relative가 정의 된 가장 가까운 부모 혹은 조상 요소를 기준으로 오프셋을 적용하는 절대 위치로 배치한다. |
fixed | 요소가 문서의 흐름에서 완전히 벗어나 초기 컨테이닝 블록(아래에서 후술) 요소를 기준으로 오프셋을 적용하는 절대 위치로 배치한다. |
sticky | 요소가 가장 가까운 스크롤 되는 부모 혹은 조상 요소를 기준으로 한다. |
오프셋 속성의 값
positon 속성이 static 값으로 정의되지 않은 요소에 사용할 수 있다. top, right, bottom, left 속성이 있으며 값으로는 px, em, % 같은 length를 쓴다.
속성 이름 뒤에 “~으로부터” 어느 위치에 있는지 생각하면 된다. left: 0은 요소의 왼쪽으로부터 0의 위치.
음수를 사용하면 속성 이름과 같은 방향 즉, “~으로”가 된다. left: -100px은 요소가 왼쪽으로 100px 이동한다.
position 값 상세설명
relative
position: relative가 선언된 요소는 문서의 흐름에 의해 정해진 공간은 유지한 채로 오프셋 값만큼 배치 되기에, 다른 요소에 영향을 주지 않는다. 다음 그림을 보자.
두 요소는 정해진 문서 흐름대로 각 50% 크기로 나란히 위치하고 있다. 이제 2번처럼 dv1 요소에 position: relative와 top: 100px이 선언되었다면 상단으로부터 100px 떨어져 배치된다.
이때 dv2는 dv1의 이동에 의해 생긴 공간을 메꾸거나 차지하지 않는다. 만일 dv1에 left: 100px을 정의 했더라도 div2는 밀려나지 않는다.
앞서 말한바와 같이 relative 요소의 오프셋은 다른 요소에 영향을 주지 않는다.
- 참고 할 것
아이콘과 텍스트를 인라인으로 나란히 표현할 때 줄이 잘 맞지 않는 경우를 많이 경험하는데, margin, padding, line-height 속성보다 부작용이 없는 position과 오프셋 속성이 좋은 대안이다.
absolute
position: absolute가 선언된 요소는 문서의 흐름에서 빠져나와 어떤 요소에도 영향을 받지도 주지도 않는 부유 요소가 된다.
그리고 position: statics가 아닌 값(fixed, absolute, relative, sticky)을 가진 가장 가까운 부모 혹은 조상 요소를 기준으로 배치된다.
부모나 조상 요소에 기준으로 삼을 값이 아무것도 정의되어 있지 않으면 초기 컨테이닝 블록이 기준이 된다. 초기 컨테이닝 블록은 루트 요소(html 요소)를 감싸고 있는 뷰포트 크기의 가장 최상위 블록이다.
See the Pen CSS Position - 컨테이닝 블록 요소 by Hyunhwa Jeong (@dev4design) on CodePen.
위 코드에서 dv2는 absolute 값을 가지는데, 부모나 조상 요소에서 참조할 위치 속성이 없어 초기 컨테이닝 블록에 붙는 상황이다.
초기 컨테이너 블록을 body나 html 요소로 잘못 이해할 수 있는데, 위에서 노랑 선은 body, 주황 선은 html 요소이며, 이들은 초기 컨테이닝 블록이 아님을 알 수 있다.
위 그림처럼 기준이 되는 요소(relative 요소)의 박스 모델 경계를 벗어나는 포지션을 가져야 할 경우, 기준 요소의 overflow 속성값이 hidden을 갖지 않도록 주의한다.
fixed
문서의 흐름에서 빠져나와 앞서 설명한 초기 컨테이닝 블록에 배치된다. 따라서 부모나 조상요소에 position: relative 같은 위치 속성이 정의되어 있더라고 참조하지 않는다.
fixed 요소는 뷰포트 크기를 갖는 초기 컨테이닝 블록이 기준이기에 오프셋을 정의하지 않는 이상 언제나 화면에 나타난다. 그래서 고정된 상단 네비게이션 바에 자주 사용한다.
어떤 경우에는 fixed 요소를 뷰포트가 아닌 다른 요소에 붙이고 싶을 수 있다. fixed 요소는 가까운 부모나 조상 요소의 속성으로 transform, perspective, filter 속성이 선언되어 있다면 그 요소를 기준으로 한다.
그리고 그 속성들의 값은 none이 아니어야 한다.
.d1 {
width: 250px;
transform: translate(0, 0);
}
.d2 {
position: fixed;
top: 0;
}
sticky
W3C 2021년도 Working Draft의 Positioned Layout Module Level 3CSS 명세에 추가된 가장 최신 속성이다. 이 명세 덕분에 더이상 자바스크립트 의존없이 CSS 선언으로 구현할 수 있다.
요소를 일반적인 문서 흐름에 따라 배치하고, 가장 가까운 스크롤 되는 부모나 조상 요소를 기준으로 한다.
See the Pen CSS Position - 컨테이닝 블록 요소 by Hyunhwa Jeong (@dev4design) on CodePen.
위 코드로 보자면, 평소에는 .sticky 요소가 position: statics 처럼 동작하다가, 기준 요소(.container)와 닿으면 position: fixed처럼 동작한다.
스크롤이 진행되다가 .sticky 요소가 부모 요소(.wrapper)의 마지막 블록 경계와 만나면 다시 position: statics처럼 동작한다.
여기서 유심히 볼 부분은 오프셋 속성이다. sticky 요소에 top: 10px이 정의되었지만 실제로 화면에 보이는 갭은 부모 요소의 padding-top: 30px 속성값이다.
sticky 요소의 오프셋 값은 기준 요소와 닿아, 고정 된 상태일 때의 값이 된다. 그래서 스크롤을 내려보면 요소가 상단으로부터 10px 떨어진 위치에 고정된다.
z-index
요소를 가상의 3차원 공간에서 z축으로 정렬했을 경우의 쌓임 순서. 값으로는 양수와 음수(index)를 받으며, 인덱스가 클수록 쌓임 맥락의 상위에 놓인다. 기본값은 auto.
z-index가 정의되지 않은 일반적인 문서의 흐름에서는 후행 정의한 HTML 태그가 높은 인덱스를 가진다. 따라서 아래 코드에서는 .d2 요소가 .d1 요소 위에 올라탄다.
d1
d2
.d1을 상위에 배치하고 싶다고하여 z-index: 100 속성값을 정의해도 무효하다. z-index 속성은 position: statics가 아닌 값(fixed, absolute, relative, sticky)을 가진 요소에서 유효하다.
- 참고 할 것
그밖에 z-index 속성을 사용할 수 있는 요소는 다양하니 MDN: 쌓임맥락에서 확인한다.
요소에 position: statics가 아닌 값을 정의하면 새로운 쌓임 맥락이 생겨 일반적인 문서 흐름 내이 쌓임 맥락보다 높은 인덱스를 가진다.
.d1 {
background-color: #ff6600;
position: relative;
}
.d2 {
background-color: #ffcc00;
margin-top: -20px;
}
이제 .d1 요소는 position: relative 선언에 의해 새로운 쌓임 맥락을 구성하였기 때문에 후행 태그보다 높은 인덱스를 가진다. 따라서 .d2 요소는 더이상 .d1 요소에 올라탈 수 없다.
.d1 {
background-color: #ff6600;
position: relative;
}
.d2 {
background-color: #ffcc00;
position: relative;
margin-top: -20px;
}
이제 .d1 요소는 position: relative 선언에 의해 새로운 쌓임 맥락을 구성하였기 때문에 후행 태그보다 높은 인덱스를 가진다. 따라서 .d2 요소는 더이상 .d1 요소에 올라탈 수 없다.
.d1 {
background-color: #ff6600;
position: relative;
z-index: 1;
}
.d2 {
background-color: #ffcc00;
position: relative;
margin-top: -20px;
}
.d1 요소에 z-index: 1을 정의하면 .d2 요소의 기본값 z-index: auto 보다 높은 인덱스를 가지므로 .d2 요소는 다시 .d1 요소에 올라탈 수 없게 된다.
아래에 10초짜리 영상을 만들어 이해를 돕도록 하였다.