Static positioning 은 모든 엘리먼트에 기본으로 적용되어 있으며 그것의 의미는 "해당 엘리먼트를 문서 흐름의 normal position에 두어라" 이다.
.positioned {
position: static;
background: yellow;
}
Relative positioning은 Static positioning과 비슷하지만 한 가지 다른 점이 있다.
noraml position을 기준으로 최종위치를 수정할 수 있다.
이는 페이지 내의 다른 엘리먼트들을 겹치게 하는것도 포함한다.
최종위치를 수정하기 위해서는 top
, bottom
, left
, right
프로퍼티들을 설정해야 한다.
이러한 프로퍼티의 값으로는 pixels, mm, rems, % 와 같은 units를 사용한다.
top: 30px;
left: 30px;
position: absolute;
포지션된 엘리먼트는 더이상 normal flow에 속하지 않는다.
이는 첫 번째 단락과 세 번째 단락이 붙어있다는 것을 보면 알 수 있다.
이 성질을 이용하면 페이지의 다른 엘리먼트 레이아웃을 방해하지 않는 독립된 UI 기능을 만들 수 있다.
예를 들어, 팝업 정보 상자, 제어 메뉴, 롤오버 패널, 페이지의 아무 곳이나 드래그 앤 드롭할 수 있는 UI 기능 등이 있다.
또한, top
, bottom
, left
, right
프로퍼티들이 Relative positioning 과는 다르게 적용된다.
Relative positioned 엘리먼트는 normal document flow 내에서의 기준 위치를 나타내지만 Absolute positioned 엘리먼트는 containing 엘리먼트의 각 면들과의 거리를 의미한다.
이게 무슨 소리냐면 Relative 일 경우 left:30px
, right:30px;
을 설정하면 더 늦게 온 속성값 기준으로 위치가 옮겨지지만, Absolute 일 경우 containing 엘리먼트의 왼쪽면 기준으로 30px 떨어진 부분부터 containing 엘리먼트의 오른쪽면 기준으로 30px 떨어진 부분까지 Absolute positioned 엘리먼트의 사이즈가 재조정된다는 말이다.
물론 left
, right
중 하나만을 선택하면 기존의 너비를 유지한 채 그 위치로 이동된다.
top
, bottom
에도 똑같이 적용된다.
Absolute positioned 엘리먼트는 margin
도 적용된다.
normal flow에서 벗어났으므로 normal flow 내의 엘리먼트와는 상호작용 하지 않지만, containing 엘리먼트와는 상호작용 한다.
위에서 containing 엘리먼트 라는 용어가 사용되었다.
containing block에 대하여 알아보자.
대부분의 경우, containing block 은 가장 가까운 조상 block-level 엘리먼트의 content 영역을 뜻하지만 반드시 그런건 아니다.
엘리먼트의 containing block 을 아는 것이 왜 중요할까.
엘리먼트의 크기와 포지션이 해당 엘리먼트의 containing block에 영향을 받기 때문이다.
엘리먼트의 width
, height
, padding
, margin
의 퍼센트 값과 absolute position의 offset 프로퍼티들의 값들이 containing block으로부터 계산된다.
containing block을 정의하는 프로세스는 전적으로 해당 엘리먼트의 position
프로퍼티의 값에 달려있다.
position 의 값이 static
, relative
, sticky
일 경우 :
가장 가까운 block-level 조상 엘리먼트의 content 영역
formatting context가 생성되는 경우 해당 영역(table container, flex container, grid container, 자기자신의 block container 처럼)
position 의 값이 absolute
일 경우 :
static
을 제외한 다른 값들을 가지고 있는 가장 가까운 조상 엘리먼트의 패딩박스 영역position 의 값이 fixed
일 경우 :
뷰포트 영역 (continuous media의 케이스)
페이지 영역 (paged media의 케이스)
position 의 값이 absolute
, fixed
이고 가장 가까운 조상이 다음중 하나 이상을 만족 할 경우 그 조상의 패딩영역이 containing block이 된다.
transform
또는 perspective
의 값으로 none
이 아닌 다른 값을 가진 경우
will-change
값으로 transform
또는 perspective
를 가진 경우
filter
값으로 none
이 아닌 다른 값을 갖거나 will-change
값으로 filter
를 가진 경우
contain
값으로 paint
을 가진 경우
backdrop-filter
값으로 none
이 아닌 다른 값을 가진 경우
filter
와backdrop-filter
의 차이점은filter
는 SVG 이미지를 필터링하고backdrop-filter
는 배경 이미지를 필터링한다.
루트 엘리먼트 (
<html>
) 를 포함한 containing block은 initial containing block 이라 불린다.
위에서 언급한 바와 같이 특정 프로퍼티에 백분율 값이 지정되면 엘리먼트의 containing block에 따라 값이 계산된다.
이러한 방식으로 동작하는 프로퍼티는 box model 프로퍼티들과 offset 프로퍼티들이다.
height
, top
, bottom
프로퍼티들은 퍼센트 값이 containing block 의 height
값을 기준으로 계산된다.
width
, left
, right
, padding
, margin
프로퍼티들은 퍼센트 값이 containing block 의 width
값을 기준으로 계산된다.
다음의 예시는 absolute positioned 엘리먼트와 그 부모 엘리먼트가 transform
프로퍼티를 갖는 경우이다.
부모 엘리먼트가 transform
프로퍼티를 갖고 있기 때문에 부모 엘리먼트의 패딩 영역이 absolute positioned 엘리먼트의 containing block이 된다.
<body>
<section>
<p>
Lorem ipsum dolor
</p>
</section>
</body>
body {
background: beige;
}
section {
transform: rotate(0deg);
left: 30px;
top: 30px;
width: 400px;
height: 160px;
padding: 30px 20px;
background: lightgray;
}
p {
position: absolute;
width: 50%; /* == (400px + 20px + 20px) * .5 = 220px */
height: 25%; /* == (160px + 30px + 30px) * .25 = 55px */
margin: 5%; /* == (400px + 20px + 20px) * .05 = 22px */
padding: 5%; /* == (400px + 20px + 20px) * .05 = 22px */
background: cyan;
color: black;
}
조상 엘리먼트 들 중에 containing block 이 될 조건을 만족하는 엘리먼트가 없다면 absolute positioned 엘리먼트의 containing block 은 initial containing block이 된다.
initial containing block 은 뷰포트의 dimension을 가지며 <html>
루트 엘리먼트를 포함하는 블록이다.
즉, 이 경우에 absolute positioned 엘리먼트는 <html>
의 외부에 표시되고 초기 뷰포트에 상대적으로 위치한다.
한 가지 예시를 보자.
아래의 이미지는 absolute positioned 엘리먼트가 <body>
내부에 있지만 <body>
가 containing block이 아니므로 initial containing block 기준으로 위치하는 것을 보여준다.
만약 <body>
에 position: relative
와 같은 containing block 이 될 조건을 설정한다면 아래처첨 동작한다.
Absolute positioning 에서는 엘리먼트끼리 겹쳐지는 것을 고려해야 한다.
화면에는 x축 y축 이 있는 것처럼 z축 또한 존재한다.
왼쪽 위를 영점(0, 0)으로 잡고 x축은 왼쪽에서 오른쪽, y축은 위쪽에서 아래쪽으로 가로지른다.
또한 writing-mode에 따라 영점이 달라진다.
z축은 화면에서 얼굴을 향해 달리는 가상의 선이며 영점은 화면의 표면이다.
z-index
프로퍼티를 이용해 z축 좌표를 설정할 수 있다.
기본적으로 z-index
의 값으로 auto
를 가지며 이는 사실상 0이다.
z-index
는 단위가 없는 인덱스 값만 사용할 수 있다.
즉, px와 같은 단위를 사용할 수 없다.
진짜 z축 좌표를 나타내는게 아니라 겹치는 부분에 대한 우선순위를 나타내는 것이기 때문이다.
따라서 2 와 5 를 사용하면 200 과 500을 사용하는 것과 동일한 효과를 얻을 수 있다.
absolute positioning 과 같은 방식으로 동작하되 containing block이 다르다.
fixed positioning은 일반적으로 containing block이 뷰포트 또는 페이지 영역이다.
예외 상황은 위에 언급한 containing block부분을 살펴보자.
fiexed positioned 엘리먼트는 normal flow에서 벗어나므로 normal flow에 속하는 다른 엘리먼트들과 겹쳐질 수 있다.
따라서 원치 않는다면 normal flow에 속하는 엘리먼트들에 margin 값을 적절하게 설정해서 여백을 만들어 줘야 한다.
Sticky positioning은 최신 문법이다.
Relative 와 Fixed 사이의 믹스 버전이다.
기본적으로 Relative 엘리먼트처럼 동작하되, 특정 임계값까지 스크롤한 후부터는 Fixed 엘리먼트가 된다.
.positioned {
position: sticky;
top: 30px;
left: 30px;
}
<h1>Sticky positioning</h1>
<dl>
<dt>A</dt>
<dd>Apple</dd>
<dd>Ant</dd>
<dd>Altimeter</dd>
<dd>Airplane</dd>
<dt>B</dt>
<dd>Bird</dd>
<dd>Buzzard</dd>
<dd>Bee</dd>
<dd>Banana</dd>
<dd>Beanstalk</dd>
<dt>C</dt>
<dd>Calculator</dd>
<dd>Cane</dd>
<dd>Camera</dd>
<dd>Camel</dd>
<dt>D</dt>
<dd>Duck</dd>
<dd>Dime</dd>
<dd>Dipstick</dd>
<dd>Drone</dd>
<dt>E</dt>
<dd>Egg</dd>
<dd>Elephant</dd>
<dd>Egret</dd>
</dl>
<h1>Sticky positioning</h1>
<dl>
<dt>A</dt>
<dd>Apple</dd>
<dd>Ant</dd>
<dd>Altimeter</dd>
<dd>Airplane</dd>
<dt>B</dt>
<dd>Bird</dd>
<dd>Buzzard</dd>
<dd>Bee</dd>
<dd>Banana</dd>
<dd>Beanstalk</dd>
<dt>C</dt>
<dd>Calculator</dd>
<dd>Cane</dd>
<dd>Camera</dd>
<dd>Camel</dd>
<dt>D</dt>
<dd>Duck</dd>
<dd>Dime</dd>
<dd>Dipstick</dd>
<dd>Drone</dd>
<dt>E</dt>
<dd>Egg</dd>
<dd>Elephant</dd>
<dd>Egret</dd>
</dl>
dt {
background-color: black;
color: white;
padding: 10px;
position: sticky;
top: 0;
left: 0;
margin: 1em 0;
}
[참고] : MDN