본문으로 건너뛰기

일반 흐름과 position

HTML·CSS 목차겹치고 고정하기: position레슨 76 / 93

목차

position은 상자를 일반 흐름에 남겨 둘지, 흐름에서 빼내 따로 놓을지를 정하는 CSS 속성입니다. 처음 값 static과 relative는 원래 자리를 남기고, absolute와 fixed는 흐름에서 빠져 뒤 상자가 그 자리로 올라옵니다.

일반 흐름에서 블록은 위에서 아래로 쌓일 뿐 서로 겹치지 않습니다(브라우저 규칙 7). 그런데 카드 그림 위의 배지, 굴려도 화면 위에 남는 머리글, 페이지 전체를 덮는 덮개는 다른 상자 위에 겹쳐 놓아야 합니다. 겹치려면 상자를 흐름 밖으로 꺼내야 하고, 꺼내면 그 상자가 있던 자리는 비게 됩니다. 이 레슨은 값 넷이 원래 자리와 뒤 상자를 어떻게 바꾸는지 봅니다.

이 단원을 마치면 레시피 카드 그림 위에 배지를 겹치고, 굴려도 위에 붙어 있는 머리글을 만들 수 있습니다. 이 단원(겹치고 고정하기)을 이미 안다면 단원 연습 문제부터 풀고 틀린 레슨만 보세요. 건너뛸지 볼 때는 힌트를 펴지 않고 풉니다.

그림 준비 중

1흐름에 남는 값 — static · relative

<div class="a">A</div>
<div class="b">B</div>
body {
  margin: 0;
}

.a,
.b {
  width: 120px;
  height: 100px;
}
결과 화면
잰 값개발자 도구에서 본 값
  • .a의 positionstatic
  • .b의 위 자리100px

잰 값 '위 자리'는 페이지 맨 위에서 그 상자의 테두리 위까지 잰 거리입니다. body { margin: 0; }은 페이지 둘레의 기본 여백 8px을 없애, 숫자가 0부터 세어지게 한 줄입니다. position을 적지 않은 상자는 처음 값 static이라, B는 A 아래 100에 쌓입니다.

.a {
  position: relative;
  top: 20px;
}
결과 화면
잰 값개발자 도구에서 본 값
  • .a의 위 자리20px
  • .b의 위 자리100px

relative는 원래 자리를 그대로 차지한 채 상자만 top만큼 비켜 놓습니다. A는 20px 내려가 B의 윗부분을 덮었지만, B는 A의 원래 자리를 보고 놓여 100 그대로입니다. top을 적지 않은 relative는 아무것도 옮기지 않습니다.

2흐름에서 빠지는 값 — absolute · fixed

브라우저 규칙 8. position: absolute · fixed 상자는 흐름에서 빠져 원래 자리를 남기지 않습니다(뒤 상자가 올라옵니다). top · left 등을 적지 않으면 원래 있던 자리에 떠 있습니다.

<div class="a">A</div>
<div class="b">B</div>
<div class="c">C</div>
body {
  margin: 0;
}

div {
  width: 120px;
  height: 100px;
}

.b {
  position: absolute;
}
결과 화면
잰 값개발자 도구에서 본 값
  • .b의 위 자리100px
  • .c의 위 자리100px
  • .c의 맨 위 요소div.b

B는 흐름에서 빠졌지만 top이 없어 원래 있던 자리 100에 그대로 떠 있습니다. 뒤의 C는 B가 남기지 않은 자리로 올라와 같은 100에 놓였습니다. 둘이 겹친 자리에서는 B가 위에 그려져 C를 가립니다. 잰 값 '맨 위 요소'는 그 상자 가운데 점에 맨 위로 그려진 요소입니다.

top 등을 적으면 상자는 원래 자리를 떠나 다른 상자에서 잰 자리로 갑니다. 그 상자를 기준 상자라고 합니다 — 위치를 재는 바탕 상자입니다. absolute가 어느 상자를 기준 상자로 삼는지는 다음 레슨 기준 상자와 absolute에서 봅니다. 네 값을 모으면 이렇습니다.

값원래 자리top 등을 재는 곳
static(처음 값)남김쓰지 않음
relative남김제 원래 자리
absolute남기지 않음기준 상자
fixed남기지 않음창

3fixed — 굴려도 창의 같은 자리

fixed는 absolute처럼 흐름에서 빠지고, 창을 기준으로 놓입니다. 페이지를 굴려도 창의 같은 자리에 남습니다. 아래는 페이지 전체를 반투명하게 덮는 덮개입니다. 잰 값은 페이지를 400px 내린 뒤에 잰 것입니다.

<div class="page">긴 본문</div>
<div class="overlay"></div>
/* 긴 본문 대신 높이만 줌 */
.page {
  height: 1600px;
}

.overlay {
  position: fixed;
  inset: 0;
  background-color:
    rgb(0 0 0 / 0.5);
}
결과 화면
잰 값개발자 도구에서 본 값
  • .overlay의 창 위 자리0px
  • .overlay의 위 자리400px
  • .overlay의 top0px
  • .overlay의 right0px
  • .overlay의 bottom0px
  • .overlay의 left0px
  • .page의 창 위 자리-392px

'창 위 자리'는 지금 창 맨 위에서 잰 거리입니다. 페이지를 400px 내렸는데 덮개는 창 맨 위 0에 그대로이고, 페이지에서 재면 400 아래로 따라 내려왔습니다. 결과 화면은 안에서 굴러가지 않습니다 — 굴리는 일은 위 실험대가 보이고, 내 파일에서 해 봅니다.

inset: 0은 top · right · bottom · left 넷에 한꺼번에 0을 주는 짧게 적기입니다(브라우저 규칙 4). 잰 값 아래 네 줄처럼 네 변이 모두 0이 되어, 창의 네 변에 닿은 덮개가 창 전체를 덮습니다.

예제

덮개 위의 안내

저장하는 동안 페이지를 덮고 안내를 띄우는 화면입니다. 결과 화면을 펴기 전에, 덮개를 띄운 채 '저장' 단추를 누를 수 있을지 먼저 적어 보세요.

<h1>김치볶음밥</h1>
<button>저장</button>
<div class="overlay">
  <p class="notice">
    저장하는 중입니다.
  </p>
</div>
.overlay {
  position: fixed;
  inset: 0;
  background-color:
    rgb(0 0 0 / 0.5);
}

.notice {
  margin: 16px;
  padding: 16px;
  background-color: #ffffff;
}
결과 화면 보기
결과 화면
잰 값개발자 도구에서 본 값
  • button의 맨 위 요소div.overlay
  • .notice의 위 자리16px
  • 덮개는 흐름에서 빠져 창 전체를 덮고, position을 준 상자라 앞의 제목 · 단추보다 위에 그려집니다. 단추 가운데의 맨 위 요소가 덮개라, 누르면 단추가 아니라 덮개가 눌립니다.
  • 안내 p는 덮개 안의 흐름에 놓입니다. 덮개 맨 위에서 바깥 여백 16px 아래, 창 맨 위에서도 16입니다.

예상과 다르면 그곳이 배울 곳입니다.

자주 틀리는 곳

틀린 생각: relative만 주면 상자가 움직인다.

<div class="a">A</div>
body {
  margin: 0;
}

.a {
  position: relative;
  height: 100px;
}
결과 화면
잰 값개발자 도구에서 본 값
  • .a의 위 자리0px

relative는 '옮길 수 있게' 할 뿐 거리를 정하지 않습니다. top · left 등이 없으면 상자는 원래 자리 그대로입니다.

맞는 규칙: relative로 옮기려면 top 등을 함께 적습니다. 옮길 생각이 없는 relative는 다음 레슨에서 볼 기준 상자를 정하는 쓰임입니다.

틀린 생각: absolute만 주면 상자가 기준 상자의 모서리로 간다.

<div class="recipe-card">
  <span class="badge">한식</span>
  <h2>떡볶이</h2>
</div>
.recipe-card {
  position: relative;
  padding: 16px;
  border: 2px solid #d2d2d7;
}

.badge {
  position: absolute;
  top: 8px;
}
결과 화면
잰 값개발자 도구에서 본 값
  • .badge의 배치 위 자리8px
  • .badge의 배치 왼쪽 자리16px

카드를 배지의 기준 상자로 삼으려고 relative를 주었습니다. '배치 위 자리' · '배치 왼쪽 자리'는 기준 상자 테두리 안쪽에서 잰 거리입니다. 적은 top은 세로를 기준 상자 위에서 8로 옮겼지만, 적지 않은 가로는 원래 자리(안쪽 여백 16 안)에 남았습니다. 배지가 흐름에서 빠져, 그 아래 제목 '떡볶이'는 배지가 있던 줄로 올라옵니다.

맞는 규칙: 방향마다 적은 값만 기준 상자에서 잽니다. 모서리에 놓으려면 두 방향(top과 right 등)을 다 적습니다.

틀린 생각: absolute를 주어도 상자 너비는 그대로다.

<div class="card">
  <div class="photo">
    <img
      src="images/kimchi.svg"
      alt="김치볶음밥"
      width="120"
      height="90"
    />
  </div>
</div>
.card {
  width: 300px;
}

.photo {
  position: absolute;
  background-color: #f5f5f7;
}
결과 화면
잰 값개발자 도구에서 본 값
  • .photo의 너비120px

흐름 안의 블록이라면 .photo는 부모 .card의 내용 칸 300을 채웁니다. 흐름에서 빠진 상자는 너비를 적지 않으면 안의 내용만큼 줄어, 그림 너비 120이 되었습니다.

맞는 규칙: 흐름에서 빠진 상자는 내용만큼의 너비가 됩니다. 넓게 두려면 width를 적거나, left와 right를 둘 다 적어 두 변 사이를 채웁니다.

틀린 생각: 페이지를 덮는 덮개를 띄우면 뒤 페이지는 굴러가지 않는다.

3절 덮개 예제의 잰 값을 다시 봅니다. 덮개를 띄운 채 400px 굴렸더니 뒤 .page의 창 위 자리가 처음 8에서 −392px로 올라갔습니다. 덮개는 위에 그려질 뿐 굴림을 막지 않습니다.

맞는 규칙: fixed 덮개는 모양만 덮습니다. 덮개를 띄운 동안 뒤 페이지를 멈추는 일은 JavaScript가 따로 합니다.

확인 문제

1. 예제에서 .overlay 규칙의 position: fixed; 줄을 지웠습니다. 덮개는 결과 화면 어디에 그려질까요?

<h1>김치볶음밥</h1>
<button>저장</button>
<div class="overlay">
  <p class="notice">
    저장하는 중입니다.
  </p>
</div>
.overlay {
  inset: 0;
  background-color:
    rgb(0 0 0 / 0.5);
}

.notice {
  margin: 16px;
  padding: 16px;
  background-color: #ffffff;
}
  • ① 지금처럼 페이지 전체를 덮는다
  • ② '저장' 단추 아래에 띠로 놓인다
  • ③ 아무 데도 그려지지 않는다
힌트

position을 지운 덮개의 값이 무엇이 되는지, 그 값에서 inset이 쓰이는지 봅니다.

정답

②입니다.

결과 화면
잰 값개발자 도구에서 본 값
  • .overlay의 positionstatic
  • button의 맨 위 요소button
  • position을 지우면 처음 값 static이라 덮개는 흐름에 남아 단추 아래 블록으로 쌓입니다. static은 top 등을 쓰지 않아 inset: 0도 아무 일을 하지 않습니다.
  • 단추 가운데의 맨 위 요소가 단추 자신이라 이제 단추를 누를 수 있습니다.
  • 흔한 오답은 ①입니다. inset: 0만으로 창을 덮는다고 본 것입니다. 네 변에서 재는 일은 흐름에서 빠진 상자에만 일어납니다.

2. inset: 0; 한 줄을 풀어 적은 네 줄입니다. 빠진 한 줄을 쓰세요.

.overlay {
  position: fixed;
  top: 0;
  right: 0;
  ____
  left: 0;
}
힌트

inset이 정하는 네 변을 위부터 시계 방향으로 짚어 봅니다.

정답

bottom: 0;입니다.

.overlay {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

inset은 top · right · bottom · left의 짧게 적기입니다. 아래 변을 빼면 덮개가 창 아래까지 닿지 않고, 높이를 적지 않은 빈 상자라 아무것도 덮지 않습니다.

3. 플로우 카페 메뉴판의 '오늘의 추천' 띠를 창 맨 위에 늘 보이게 하려고 아래처럼 썼습니다. 그런데 메뉴판을 내리면 띠가 함께 올라가 사라집니다. 몇 번 줄을 어떻게 고칠까요?

<p class="pick">
  오늘의 추천: 라테
</p>
<div class="menu">메뉴</div>
.pick {
  position: absolute;
  top: 0;
  margin: 0;
  background-color: #ffffff;
}

.menu {
  height: 1600px;
}
힌트

css 2번 줄의 값이 top: 0을 어디에서 재는지 봅니다.

힌트 둘

창에서 재는 값은 2절 표의 넷 가운데 하나입니다.

정답

css 2번 줄의 absolute를 fixed로 바꿉니다. 고치기 전 띠를 400px 내린 뒤 재면 이렇습니다.

결과 화면
잰 값개발자 도구에서 본 값
  • .pick의 위 자리0px
  • .pick의 창 위 자리-400px

고친 뒤입니다.

<p class="pick">
  오늘의 추천: 라테
</p>
<div class="menu">메뉴</div>
.pick {
  position: fixed;
  top: 0;
  margin: 0;
  background-color: #ffffff;
}

.menu {
  height: 1600px;
}
결과 화면
잰 값개발자 도구에서 본 값
  • .pick의 창 위 자리0px
  • 고치기 전 띠는 페이지 맨 위 0에 놓여, 400px 내리면 창 위로 400px 벗어납니다. fixed는 창에서 재어 굴려도 창 맨 위 0에 남습니다.
  • 흔한 오답은 top: 0을 지우는 답입니다. 그래도 띠는 원래 자리(페이지 맨 위)에 떠 있을 뿐 창을 따라오지 않습니다.

컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요. 2절 예제를 index.html과 style.css로 저장하고 link로 이어 엽니다(문서 뼈대의 body 안에 예제 HTML을 넣습니다). .b의 absolute를 relative로 바꾸면 C가 어디로 갈지 먼저 적고, 저장하고 새로고침해 맞춰 봅니다. C를 검사해 Computed 창에서 position도 봅니다.

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

HTML·CSS 목차로