position
요소가 문서 내에서 어떻게 배치되는지를 결정하는 속성입니다. top, right, bottom, left, z-index와 함께 사용합니다.
클래스 목록
| 클래스 | CSS | 설명 |
|---|---|---|
pst | position: static | 기본값. 문서 흐름에 따라 배치. top/left 등 무시 |
pr | position: relative | 원래 위치 기준 오프셋. 자식 absolute의 기준점 |
pa | position: absolute | 흐름에서 제거. 가장 가까운 positioned 부모 기준 배치 |
pf | position: fixed | 뷰포트 기준 고정. 스크롤해도 위치 유지 |
ps | position: sticky | relative + fixed 하이브리드. 스크롤 임계점에서 고정 |
pi | position: initial | 초기값(static)으로 리셋 |
시각적 비교
각 position 값이 요소에 어떤 영향을 주는지 비교합니다.
Static (기본값) — pst
문서 흐름에 따라 배치됩니다. top/left 등이 무시됩니다.
Relative — pr
원래 위치에서 top: 2rem, left: 2rem만큼 이동합니다. 원래 공간은 유지됩니다.
Absolute — pa
문서 흐름에서 제거, 부모 기준 배치
Fixed — pf
실제 pf는 뷰포트에 고정됩니다. 스크롤해도 위치가 변하지 않습니다.
Sticky — ps
위 박스를 스크롤하면 보라색 요소가 상단에 고정됩니다.
언제 뭘 쓸까?
| 상황 | 추천 | 이유 |
|---|---|---|
| 드롭다운 메뉴 | pa | 부모 기준으로 정확한 위치에 표시 |
| 고정 헤더/네비게이션 | pf / ps | 스크롤해도 항상 보이게 고정 |
| 툴팁/팝오버 | pa | 트리거 요소 기준으로 표시 |
| 모달 오버레이 | pf | 뷰포트 전체를 덮는 배경 |
| 위치 미세 조정 | pr | 원래 위치에서 약간의 오프셋 |
| 사이드바 고정 | ps | 스크롤하다가 특정 위치에서 고정 |
| 뱃지/아이콘 오버레이 | pa | 부모 위에 겹쳐서 표시 |
클래스별 상세
pstposition: static
기본값입니다. 요소가 문서의 일반적인 흐름에 따라 배치됩니다. top, right, bottom, left, z-index 속성이 적용되지 않습니다.
<!-- 기본 position (보통 명시할 필요 없음) -->
<div class="pst">
문서 흐름에 따라 배치됩니다.
top, left 등이 적용되지 않습니다.
</div>
<!-- 반응형에서 position 리셋 시 사용 -->
<div class="ps sm-pst t0">
데스크탑: sticky → 모바일: static
</div>prposition: relative
원래 위치를 기준으로 오프셋을 적용합니다. 원래 공간은 그대로 유지됩니다. 또한 자식 요소의 pa(absolute) 배치 기준점이 됩니다.
<!-- 원래 위치에서 오프셋 -->
<div class="pr t8px l16px">
원래 위치에서 top: 8px, left: 16px 이동
</div>
<!-- pa 자식의 기준점 역할 (가장 흔한 용도) -->
<div class="pr">
<img src="avatar.jpg" class="w4-8rem h4-8rem br50p" />
<span class="pa b0 r0 w12px h12px bg34D399 br50p"></span>
</div>자주 쓰는 조합
pr zi10 | 기준점 + 쌓임 순서 지정 |
pr t8px l8px | 원래 위치에서 미세 조정 |
pr oh | 기준점 + 자식 overflow 숨김 |
paposition: absolute
문서 흐름에서 완전히 제거됩니다. 가장 가까운 positioned 조상(pr, pa, pf)을 기준으로 배치됩니다. positioned 조상이 없으면 뷰포트 기준입니다.
<!-- 부모 기준 우상단 배치 -->
<div class="pr w100p h10rem bg18181B br8px">
<span class="pa t8px r8px bg6366F1 cFFFFFF py4px px8px br4px fs12px">
NEW
</span>
<div class="p2rem">카드 콘텐츠</div>
</div>
<!-- 드롭다운 메뉴 -->
<div class="pr dib">
<button class="py8px px16px bg6366F1 cFFFFFF br8px bn cp">메뉴</button>
<ul class="pa t100p l0 mt4px bg18181B b1pxsolid27272A br8px p16px lsn minw16rem zi10">
<li class="py4px cFAFAFA">항목 1</li>
<li class="py4px cFAFAFA">항목 2</li>
<li class="py4px cFAFAFA">항목 3</li>
</ul>
</div>
<!-- 가운데 정렬 (transform 조합) -->
<div class="pr h20rem bg18181B br8px">
<div class="pa t50p l50p neg-tty50p neg-ttx50p bg6366F1 cFFFFFF p2rem br8px">
정중앙 배치
</div>
</div>주의
pa를 사용할 때는 반드시 부모에 pr을 지정하세요. 그렇지 않으면 뷰포트 기준으로 배치되어 예상과 다른 위치에 표시됩니다.
자주 쓰는 조합
pa t0 l0 | 부모 좌상단에 배치 |
pa t0 r0 | 부모 우상단에 배치 |
pa b0 r0 | 부모 우하단에 배치 |
pa t0 l0 r0 b0 | 부모 전체를 덮는 오버레이 |
pa t100p l0 | 부모 바로 아래에 배치 (드롭다운) |
pa t50p l50p | 가운데 정렬 (transform 필요) |
pfposition: fixed
뷰포트를 기준으로 배치됩니다. 스크롤해도 위치가 변하지 않습니다. 고정 헤더, 플로팅 버튼, 모달 오버레이 등에 사용합니다.
<!-- 고정 헤더 -->
<header class="pf t0 l0 r0 bg0F0F17 py12px px2rem zi100 bb1pxsolid27272A">
<nav class="df jcsb aic">
<div class="cFAFAFA fw700">Logo</div>
<div class="df gap2rem">
<a href="#" class="cA1A1AA tdn">Home</a>
<a href="#" class="cA1A1AA tdn">About</a>
</div>
</nav>
</header>
<!-- 모달 오버레이 -->
<div class="pf t0 l0 w100p h100p bg0-0-0-50 df jcc aic zi999">
<div class="bg18181B br12px p3-2rem maxw48rem w100p">
<h2 class="cFAFAFA fs2rem fw700 mb16px">모달 제목</h2>
<p class="c71717A fs14px">모달 콘텐츠</p>
</div>
</div>
<!-- 플로팅 버튼 -->
<button class="pf b2rem r2rem w4-8rem h4-8rem br50p bg6366F1 cFFFFFF bn cp zi50 df jcc aic">
↑
</button>자주 쓰는 조합
pf t0 l0 r0 | 화면 상단 고정 (헤더) |
pf b0 l0 r0 | 화면 하단 고정 (푸터/네비) |
pf t0 l0 w100p h100p | 전체 화면 오버레이 (모달 배경) |
pf b2rem r2rem | 우하단 플로팅 버튼 |
pf t50p l50p | 뷰포트 중앙 (transform 필요) |
psposition: sticky
relative와 fixed의 하이브리드입니다. 스크롤 임계점을 지나면 고정됩니다. 반드시 top 등의 오프셋 값과 함께 사용해야 합니다.
<!-- 스크롤 시 고정되는 네비게이션 -->
<nav class="ps t0 bg0F0F17 py12px px2rem zi50 bb1pxsolid27272A">
<div class="df gap2rem">
<a href="#section1" class="cA1A1AA tdn">섹션 1</a>
<a href="#section2" class="cA1A1AA tdn">섹션 2</a>
<a href="#section3" class="cA1A1AA tdn">섹션 3</a>
</div>
</nav>
<!-- 테이블 헤더 고정 -->
<div class="maxh40rem oya">
<table class="w100p bcc">
<thead>
<tr>
<th class="ps t0 bg18181B py12px px16px zi10">이름</th>
<th class="ps t0 bg18181B py12px px16px zi10">이메일</th>
</tr>
</thead>
<tbody>
<!-- 데이터 행들 -->
</tbody>
</table>
</div>
<!-- 사이드바 sticky -->
<div class="dg gtc25rem-1fr gap2rem">
<aside class="ps t2rem ash">
사이드 네비게이션 (스크롤 시 고정)
</aside>
<main>메인 콘텐츠</main>
</div>주의
ps는 스크롤 컨테이너가 필요합니다. 부모에 oh(overflow: hidden)가 있으면 작동하지 않습니다. 또한 반드시 t0 같은 오프셋 값을 지정해야 합니다.
piposition: initial
position 속성을 초기값(static)으로 되돌립니다. 반응형에서 특정 화면 크기에서만 position을 리셋하고 싶을 때 활용합니다.
<!-- 반응형에서 position 리셋 -->
<div class="ps sm-pi t0">
데스크탑: sticky 고정
모바일(768px 이하): initial(static)로 리셋
</div>반응형 조합
미디어 쿼리 프리픽스와 조합하여 화면 크기에 따라 position을 변경할 수 있습니다.
<!-- 데스크탑 sticky → 모바일 static -->
<nav class="ps sm-pst t0">
데스크탑에서는 스크롤 시 고정, 모바일에서는 일반 흐름
</nav>
<!-- 데스크탑 fixed 헤더 → 모바일 static -->
<header class="pf sm-pst t0 l0 r0">
데스크탑에서는 고정 헤더, 모바일에서는 일반 배치
</header>| 클래스 조합 | 동작 |
|---|---|
ps sm-pst t0 | 기본 sticky → 768px 이하에서 static |
pf md-pst t0 l0 r0 | 기본 fixed → 1024px 이하에서 static |
pst sm-ps t0 | 기본 static → 768px 이하에서 sticky |
pa md-pr | 기본 absolute → 1024px 이하에서 relative |
ps lg-pst t0 | 기본 sticky → 1280px 이하에서 static |
팁 & 주의사항
pa는 반드시 pr 부모가 필요
pa는 가장 가까운 positioned 조상을 기준으로 배치됩니다. 부모에 pr이 없으면 뷰포트 기준이 되어 의도치 않은 위치에 표시됩니다.
pf는 부모가 아닌 뷰포트 기준
pf는 항상 뷰포트를 기준으로 배치됩니다. 부모 요소의 위치와 무관하게 동작하므로, 전체 화면에서의 위치를 지정하세요.
ps에는 스크롤 컨테이너가 필요
ps는 스크롤 가능한 부모 안에서만 작동합니다. 부모에 oh(overflow: hidden)가 설정되어 있으면 sticky가 동작하지 않습니다.
z-index는 positioned 요소에만 적용
zi10 등의 z-index 클래스는 pst(static) 이외의 position 값이 설정된 요소에서만 작동합니다.