예제 하나로 보는 position: absolute
absolute로 배치한 요소는 일반 흐름에서 빠져나와 top, right, bottom, left로 배치돼요. 이 오프셋은 position이 static이 아닌 가장 가까운 조상을 기준으로 계산되고, 그래서 부모에 position: relative를 줘요.
.card에서 position: relative를 지우면 배지가 페이지 전체의 오른쪽 위로 튀어 가요. 위치가 지정된 조상이 더 이상 없기 때문이에요. "position absolute가 안 돼요" 질문 대부분이 이 한 줄로 설명돼요.
absolute 요소에 대해 알아 둘 것들이에요.
- 공간을 차지하지 않아요. 제목과 문단은 배지가 없는 것처럼 배치돼요.
- 너비가 콘텐츠에 맞게 줄어들어요.
width를 주거나left와right를 모두 지정하면 달라져요. - 오프셋은 포함 블록의 padding 가장자리, 즉 테두리 안쪽까지 계산돼요.
다섯 가지 position 값
| 값 | 흐름에 남나요? | 오프셋 기준 | 주로 쓰는 곳 |
|---|---|---|---|
static (기본값) | 네 | 오프셋이 무시돼요 | 일반 요소 |
relative | 네, 공간이 유지돼요 | 자기 원래 위치 | absolute 자식의 기준점, 살짝 옮기기 |
absolute | 아니요 | 가장 가까운 위치 지정 조상(또는 페이지) | 배지, 툴팁, 오버레이, 닫기 버튼 |
fixed | 아니요 | 뷰포트 | 헤더, 채팅 버튼, 쿠키 배너 |
sticky | 네 | 오프셋에 닿은 뒤의 스크롤 컨테이너 | 표 머리글, 섹션 제목, 사이드바 |
position: relative
relative로 배치한 요소는 흐름에서 원래 있던 자리에 머물러요. 오프셋은 그려지는 위치를 옮기지만 원래 공간은 계속 예약되어 있어서 주변은 움직이지 않아요.
상자 2는 아래로 20px, 오른쪽으로 20px 옮겨 그려져서 상자 3과 겹치지만, 상자 3은 움직이지 않았어요. 여전히 원래 자리에 상자 2를 위한 공간을 남겨 둬요. relative 자체로 뭔가를 옮기는 경우는 드물고, 주된 역할은 absolute 자식의 기준 상자가 되는 거예요.
오프셋과 inset
top, right, bottom, left는 길이, 퍼센트(포함 블록 기준), auto를 받아요. inset 단축 속성은 margin과 같은 순서로 네 개를 모두 지정해요.
.overlay {
position: absolute;
inset: 0; /* top: 0; right: 0; bottom: 0; left: 0; */
}
.corner {
position: absolute;
inset: auto 16px 16px auto; /* bottom right corner, 16px in */
}
반대쪽 변을 모두 지정하면 요소가 늘어나요. left: 0; right: 0은 요소를 포함 블록만큼 넓게 만들어요. absolute 자식에 inset: 0을 주는 게 카드를 오버레이로 덮는 표준 방법이에요.
absolute와 transform으로 가운데 정렬
top: 50%; left: 50%는 요소의 왼쪽 위 모서리를 가운데에 놓아요. 그다음 translate(-50%, -50%)가 자기 크기의 절반만큼 다시 옮겨요.
요소가 흐름에 남아도 된다면 flexbox와 grid가 더 간단하게 가운데 정렬해요. div 가운데 정렬 페이지에서 모든 방법을 비교해요.
position: fixed
fixed 요소는 뷰포트를 기준으로 배치되고 페이지를 스크롤해도 그 자리에 있어요.
.chat-button {
position: fixed;
bottom: 16px;
right: 16px;
}
함정이 두 가지 있어요. fixed 요소는 공간을 차지하지 않아서, body에 padding-top을 주지 않으면 고정 헤더가 페이지 위쪽을 가려요. 그리고 조상에 transform, filter, perspective가 있으면 뷰포트 대신 그 조상이 기준 상자가 되어 요소가 함께 스크롤돼요.
position: sticky
sticky 요소는 오프셋에 닿을 때까지 평소처럼 스크롤되다가, 부모의 끝이 스크롤되어 지나갈 때까지 거기 붙어 있어요. 아래 상자를 스크롤해 보세요.
각 글자는 자기 섹션이 보이는 동안 스크롤 상자 위쪽에 붙어 있다가 다음 글자에 밀려나요. sticky 요소는 부모를 절대 벗어나지 않기 때문이에요.
sticky가 붙지 않으면 다음을 확인하세요.
- 오프셋 없음.
position: sticky는top,bottom,left,right없이는 아무것도 하지 않아요. overflow: hidden,auto,scroll인 조상. 그 조상이 스크롤 컨테이너가 되고, 실제로 스크롤되지 않으면 아무것도 붙지 않아요. 넘치는 부분을 숨기기만 하면 된다면overflow: clip을 쓰세요.- sticky 요소보다 높지 않은 부모. 그 안에 붙어 있을 공간이 없어요.
- 요소를 늘리는 flex나 grid 부모. flex 행에서는 sticky 사이드바에
align-self: flex-start를 추가하세요.
자주 하는 실수
- absolute 요소의 부모에
position: relative빠뜨리기. - 페이지 레이아웃에 absolute 쓰기. absolute 요소는 서로와 콘텐츠를 무시해서 작은 화면에서 텍스트가 겹쳐요. 레이아웃에는 flexbox나 grid를, 작은 장식에는 absolute를 쓰세요.
- static 요소에 오프셋.
position없이는top: 10px가 아무것도 하지 않아요. - 어느 요소가 위에 올지 다투기. 겹친 위치 지정 요소의 순서는 z-index가 정해요.
- 고정 헤더가 콘텐츠를 가리기. 페이지에 padding을 주거나
scroll-padding-top을 줘서 앵커 링크가 헤더 아래에 도착하게 하세요.
자주 묻는 질문
position: absolute는 무엇을 하나요?
요소를 일반 흐름에서 빼내고(다른 요소들은 그 요소가 없는 것처럼 동작해요) top, right, bottom, left로 배치해요. 기준은 포함 블록, 즉 position이 static이 아닌 가장 가까운 조상이에요.
부모를 기준으로 요소를 absolute 배치하려면 어떻게 하나요?
부모에 position: relative;를, 자식에 position: absolute;와 top: 0; right: 0; 같은 오프셋을 주세요. 위치가 지정된 부모가 없으면 자식은 페이지를 기준으로 배치돼요.
relative와 absolute position은 무엇이 다른가요?
relative는 요소를 흐름에 남겨 두고 그려지는 위치만 옮겨서 원래 공간이 그대로 남아요. absolute는 요소를 흐름에서 빼내고 위치가 지정된 조상을 기준으로 배치해요.
position: sticky가 동작하지 않는 이유는 무엇인가요?
보통 셋 중 하나예요. top(또는 다른 오프셋)을 지정하지 않았거나, 조상에 overflow: hidden이나 auto가 있어서 그 조상이 스크롤 컨테이너가 되었거나, sticky 요소의 부모가 요소보다 높지 않아서 붙어 있을 공간이 없는 경우예요.
fixed와 sticky는 무엇이 다른가요?
fixed는 흐름에서 빠져서 뷰포트에 고정돼요(조상에 transform이나 filter가 없다면요). sticky는 흐름에 남아서 오프셋에 닿을 때까지 평소처럼 스크롤되다가, 부모가 화면에 있는 동안 붙어 있어요.