Practical positioning examples

김동현·2026년 3월 18일

mdn 학습 번역 - CSS

목록 보기
31/190

안녕하세요! 프론트엔드 개발자를 향해 성큼성큼 나아가고 계신 여러분, 진심으로 환영합니다. 저는 여러분의 CSS 실무 감각을 한층 끌어올려 드릴 강사입니다.

우리가 앞서 다양한 CSS 레이아웃과 포지셔닝(position) 개념들을 배웠죠? 하지만 이론만으로는 실무에서 어떻게 쓰이는지 확 와닿지 않을 수 있어요. 그래서 오늘은 포지셔닝 속성들을 활용해 실제 웹사이트에서 매일같이 쓰이는 실전 UI 컴포넌트들을 직접 만들어 볼 겁니다. 탭(Tab) 메뉴, 스크롤을 따라다니는 고정 박스, 그리고 스르륵 나타나는 슬라이드 패널까지!

공식 문서의 모든 내용을 아주 친절하게 번역해 드리면서, 제가 실무에서 구르며 얻은 꿀팁들도 아낌없이 방출해 드릴 테니 잘 따라와 주세요!


실전 포지셔닝 예제 (Practical positioning examples)

이 문서에서는 포지셔닝(positioning)을 이용해 어떤 것들을 할 수 있는지 보여드리기 위해, 몇 가지 실무(real-world) 예제들을 직접 만들어 보는 과정을 안내합니다.

선행 조건 (Prerequisites):HTML 기초 (HTML로 콘텐츠 구조화하기 공부하기), 그리고 CSS 작동 원리에 대한 이해 (CSS 스타일링 기초 공부하기).
학습 목표 (Objective):포지셔닝의 실용성과 활용 방법에 대한 감각 익히기.

탭 형태의 정보 박스 (A tabbed info-box)

우리가 첫 번째로 살펴볼 예제는 아주 고전적인 탭(tab) 형태의 정보 박스입니다. 이는 좁은 영역 안에 많은 양의 정보를 꽉꽉 채워 넣고 싶을 때 정말 흔하게 사용되는 기능이죠. 전략/전쟁 게임 같은 정보가 넘쳐나는 앱, 화면이 좁아서 공간이 부족한 모바일 버전 웹사이트, 그리고 전체 UI를 덮지 않으면서도 많은 정보를 컴팩트하게 제공하고 싶을 때 유용합니다. 우리가 만들 간단한 예제는 완성되고 나면 아래와 같은 모습일 겁니다:

Tab 1이 선택되어 있습니다. 'Tab 2'와 'Tab 3'가 나머지 두 개의 탭입니다. 선택된 탭의 내용만 보입니다. 탭이 선택되면 글자색이 검정에서 흰색으로 바뀌고, 배경색이 주황-빨강에서 새들-브라운(갈색)으로 바뀝니다.

참고:
완성된 예제가 실제로 동작하는 모습은 tabbed-info-box.html에서 확인하실 수 있습니다 (소스 코드 보기). 이 문서의 해당 섹션에서 어떤 것을 만들게 될지 미리 감을 잡아보세요.

여러분은 속으로 이렇게 생각할지도 모릅니다. "그냥 탭마다 서로 다른 별개의 웹페이지를 만들고, 탭을 클릭할 때마다 그 페이지들로 이동하게 해서 똑같은 효과를 내면 안 되나요?" 네, 그렇게 하면 코드는 더 단순해지겠죠. 하지만 그렇게 하면 별도의 "페이지" 뷰를 보여줄 때마다 매번 새로운 웹페이지를 불러와야(새로고침) 합니다. 이는 화면 간에 정보를 유지하거나, 이 기능을 더 큰 UI 디자인 속에 매끄럽게 통합하는 것을 훨씬 더 어렵게 만듭니다.

시작하기 전에, 시작 파일인 tabbed-info-box-start.htmltabs-manual.js의 로컬 복사본을 만들어 주세요. 컴퓨터의 적당한 곳에 저장한 뒤, 텍스트 에디터에서 tabbed-info-box-start.html 파일을 열어주세요. 본문(body) 안에 들어있는 HTML 구조부터 살펴보겠습니다:

<section class="info-box">
  <div role="tablist" class="manual">
    <button
      id="tab-1"
      type="button"
      role="tab"
      aria-selected="true"
      aria-controls="tabpanel-1">
      <span>Tab 1</span>
    </button>

    <button
      id="tab-2"
      type="button"
      role="tab"
      aria-selected="false"
      aria-controls="tabpanel-2">
      <span>Tab 2</span>
    </button>
    <button
      id="tab-3"
      type="button"
      role="tab"
      aria-selected="false"
      aria-controls="tabpanel-3">
      <span>Tab 3</span>
    </button>
  </div>

  <div class="panels">
    <article id="tabpanel-1" role="tabpanel" aria-labelledby="tab-1">
      <h2>The first tab</h2>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque
        turpis nibh, porttitor nec venenatis eu, pulvinar in augue. Vestibulum
        et orci scelerisque, vulputate tellus quis, lobortis dui. Vivamus varius
        libero at ipsum mattis efficitur ut nec nisl. Nullam eget tincidunt
        metus. Donec ultrices, urna maximus consequat aliquet, dui neque
        eleifend lorem, a auctor libero turpis at sem. Aliquam ut porttitor
        urna. Nulla facilisi.
      </p>
    </article>

    <article id="tabpanel-2" role="tabpanel" aria-labelledby="tab-2">
      <h2>The second tab</h2>
      <p>
        This tab hasn't got any Lorem Ipsum in it. But the content isn't very
        exciting all the same.
      </p>
    </article>

    <article id="tabpanel-3" role="tabpanel" aria-labelledby="tab-3">
      <h2>The third tab</h2>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque
        turpis nibh, porttitor nec venenatis eu, pulvinar in augue. And now an
        ordered list: how exciting!
      </p>
      <ol>
        <li>dui neque eleifend lorem, a auctor libero turpis at sem.</li>
        <li>Aliquam ut porttitor urna.</li>
        <li>Nulla facilisi</li>
      </ol>
    </article>
  </div>
</section>

여기에는 info-box라는 class를 가진 <section> 요소가 하나 있고, 그 안에는 두 개의 <div>가 들어있습니다. 첫 번째 div 안에는 세 개의 버튼이 있는데, 이것들이 바로 우리가 콘텐츠 패널을 표시하기 위해 클릭하게 될 실제 '탭' 메뉴가 될 것입니다. 두 번째 div 안에는 세 개의 <article> 요소가 들어있으며, 이것들이 각 탭에 대응하는 '콘텐츠 패널'을 구성합니다. 각 패널에는 약간의 샘플 텍스트가 들어있습니다.

우리의 아이디어는 이렇습니다. 탭들(버튼들)은 일반적인 수평 내비게이션 메뉴처럼 보이도록 스타일링하고, 콘텐츠 패널들은 절대 위치 지정(absolute positioning)을 사용해 한 군데에 차곡차곡 겹쳐지도록(sit on top of one another) 만들 것입니다. 또한, 탭을 눌렀을 때 그에 맞는 패널을 보여주기 위해 페이지에 포함시킬 약간의 자바스크립트(JavaScript)를 제공하고 탭 자체의 스타일도 지정할 것입니다. 당장 이 자바스크립트 코드를 완벽히 이해하실 필요는 없지만, 가능한 한 빨리 기본적인 자바스크립트를 배워두시는 것이 좋습니다. UI 기능이 복잡해질수록, 여러분이 원하는 동작을 구현하기 위해 자바스크립트가 필요할 확률이 기하급수적으로 높아지니까요.

기본적인 설정 (General setup)

가장 먼저, 여는 <style> 태그와 닫는 </style> 태그 사이에 다음 코드를 추가해 주세요:

html {
  font-family: sans-serif;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
}

이건 단순히 우리 페이지에 산세리프(sans-serif) 폰트를 적용하고, border-box box-sizing 모델을 사용하며, <body> 요소가 기본적으로 가지는 여백(margin)을 없애기 위한 아주 기초적인 설정(setup)입니다.

다음으로, 이전 CSS 바로 아래에 다음을 추가해 주세요:

.info-box {
  width: 452px;
  height: 400px;
  margin: 1.25rem auto 0;
}

이 코드는 콘텐츠의 너비와 높이를 특정 값으로 고정하고, 예전 방식인 margin: 1.25rem auto 0을 사용해 화면 중앙에 오도록 배치합니다. 코스 초반부에서, 저희는 콘텐츠 컨테이너에 고정된 높이(fixed height)를 설정하는 것은 피하라고 권장해 드렸습니다. 하지만 이 예제의 경우에는 탭 안에 들어갈 콘텐츠가 고정되어 있기 때문에 예외적으로 고정 높이를 주어도 괜찮습니다.

탭 스타일링하기 (Styling our tabs)

이제 탭들이 진짜 탭처럼 보이도록 스타일링해 봅시다. 기본적으로 이것들은 수평 내비게이션 메뉴입니다. 코스 초반에 보았던 것처럼 클릭했을 때 완전히 다른 웹페이지를 로드하는 대신, 같은 페이지 안에서 다른 패널을 보여주게 되죠. 먼저 CSS 맨 아래에 다음 규칙을 추가해서 tablistflex 컨테이너로 만들고 가로 너비를 100%로 꽉 채우게 하세요:

.info-box [role="tablist"] {
  min-width: 100%;
  display: flex;
}

참고:
이 예제 전체에 걸쳐 선택자(selector) 체인의 맨 앞에 .info-box를 붙인 자손 선택자(descendant selectors)를 사용하고 있습니다. 이는 우리가 만든 이 탭 컴포넌트를 이미 다른 콘텐츠가 존재하는 페이지에 삽입했을 때, 페이지의 다른 부분에 적용된 스타일과 충돌(간섭)하는 것을 막기 위함입니다.

다음으로, 버튼들이 탭처럼 보이도록 스타일을 입히겠습니다. 다음 CSS를 추가해 주세요:

.info-box [role="tab"] {
  padding: 0 1rem;
  line-height: 3rem;
  background: white;
  color: #b60000;
  font-weight: bold;
  border: none;
  outline: none;
}

그다음으로, 탭에 포커스가 가거나(focused) 마우스가 올라갔을 때(hovered) 사용자가 시각적인 피드백을 받을 수 있도록 :focus:hover 상태를 다르게 보이게 설정하겠습니다.

.info-box [role="tab"]:focus span,
.info-box [role="tab"]:hover span {
  outline: 1px solid blue;
  outline-offset: 6px;
  border-radius: 4px;
}

이제 탭을 클릭했을 때 활성화된 탭을 강조해 주는 규칙을 추가합니다. 탭을 클릭하면 자바스크립트를 통해 해당 탭의 aria-selected 속성이 true로 설정될 것입니다. 아래 CSS를 나머지 스타일 아래에 추가해 주세요:

.info-box [role="tab"][aria-selected="true"] {
  background-color: #b60000;
  color: white;
}

패널 스타일링하기 (Styling the panels)

다음 작업은 우리의 패널(내용물)들을 스타일링하는 것입니다. 가볼까요!

먼저 .panels <div> 컨테이너를 스타일링하는 다음 규칙을 추가하세요. 여기서는 패널들이 정보 박스(info-box) 안에 아늑하게 들어맞도록 고정 height를 설정합니다. 그리고 가장 중요한 핵심인 positionrelative로 설정합니다. 이렇게 하면 이 <div>포지셔닝의 기준점(positioning context)이 되어, 나중에 자식 요소들을 브라우저 화면(viewport) 기준이 아닌 이 <div> 기준으로 배치할 수 있게 됩니다. 마지막으로 이전 CSS에서 설정된 플롯(float)이 나머지 레이아웃을 망가뜨리지 않도록 clear를 줍니다.

.info-box .panels {
  height: 352px;
  clear: both;
  position: relative;
}

💡 강사님의 실무 팁! (매우 중요)
"부모는 relative, 자식은 absolute!"
실무에서 position: absolute를 쓸 때 무조건 외우셔야 하는 마법의 공식입니다. 자식 요소에 absolute를 주면 이 녀석은 화면 위로 붕 떠서 기준점을 찾으러 부모를 향해 거슬러 올라가는데, 이때 부모 중에 position: relative(혹은 fixed, absolute 등)를 가진 녀석을 만나면 그곳을 기준으로 좌표를 잡습니다. 만약 relative를 안 주면 브라우저 화면 전체를 기준으로 배치되어 버리니 레이아웃이 박살 나게 됩니다!

이 섹션의 마지막으로, 패널을 구성하는 각각의 <article> 요소들을 스타일링하겠습니다.
가장 먼저 추가할 규칙은 패널들에 positionabsolute로 주는 것입니다. 그리고 그것들이 부모 <div> 컨테이너의 topleft에 딱 맞게(flush) 달라붙도록 만듭니다. 이 부분이 이번 레이아웃 전체의 핵심(key)입니다. 이렇게 하면 모든 패널이 똑같은 위치에 겹쳐서 쌓이게(sit on top of one another) 되니까요. 이 규칙은 또한 패널에 컨테이너와 동일한 높이를 주고, 약간의 여백(padding), 글자색(color), 그리고 배경색(background-color)을 설정합니다.

.info-box [role="tabpanel"] {
  background-color: #b60000;
  color: white;
  position: absolute;
  padding: 0.8rem 1.2rem;
  height: 352px;
  top: 0;
  left: 0;
}

두 번째로 추가할 규칙은 is-hidden 클래스가 붙은 패널을 화면에서 숨기는 역할(display: none)을 합니다. 우리는 적절한 타이밍에 자바스크립트를 사용하여 이 클래스를 추가하거나 제거할 것입니다. 어떤 탭을 선택하면 그에 해당하는 패널은 is-hidden 클래스가 제거되어 보이고, 나머지 모든 패널에는 is-hidden 클래스가 추가되어 숨겨지겠죠. 결국 한 번에 오직 하나의 패널만 화면에 보이게 됩니다.

.info-box [role="tabpanel"].is-hidden {
  display: none;
}

자바스크립트 (JavaScript)

이 기능을 실제로 작동하게 만드는 마지막 퍼즐 조각은 바로 자바스크립트 코드입니다. tabs-manual.js 파일이 <script> 태그를 사용해 포함되어 있습니다:

<script src="tabs-manual.js"></script>

이 코드는 다음과 같은 일을 합니다:

  • window load 이벤트(window load event)가 발생하면, 페이지 내의 모든 tablist 요소들에 대해 TabsManual 클래스(class)를 초기화합니다.
  • TabsManual 객체가 생성될 때, 생성자(constructor) 안에서 모든 탭과 패널의 참조(reference)를 tabstabpanels 변수에 싹 모아둡니다. 나중에 쉽게 써먹기 위해서죠.
  • 또한 생성자는 모든 탭에 clickkeydown 이벤트 핸들러(event handlers)를 등록합니다. 이 이벤트 핸들러 안에는 탭을 클릭하거나 키보드를 눌러서 선택했을 때 무슨 일이 일어나야 하는지에 대한 로직이 들어있습니다.
  • setSelectedTab(currentTab) 함수 안에서는 다음 과정이 일어납니다:
    • for 루프(반복문)를 돌면서 모든 탭의 aria-selected 속성을 false로 바꾸고, 대응하는 패널들에 is-hidden 클래스를 추가하여 전부 숨깁니다(선택 해제).
    • 방금 선택된 탭(currentTab)의 aria-selectedtrue로 바꾸고, 거기에 대응하는 패널에서 is-hidden 클래스를 제거하여 화면에 나타나게 합니다.
  • 이 코드는 접근성(Accessibility)을 위해 왼쪽 화살표, 오른쪽 화살표, Home, End 키를 이용한 키보드 내비게이션 로직도 완벽하게 지원합니다.

화면에 고정된 탭 정보 박스 (A fixed position tabbed info-box)

두 번째 예제에서는, 방금 만든 첫 번째 예제인 '정보 박스'를 가져와서 전체 웹페이지 문맥(context) 안에 넣어볼 겁니다. 단순히 넣기만 하는 게 아니라, 이 박스에 고정 위치(fixed position)를 주어서 브라우저 창의 항상 똑같은 자리에 머물도록 만들어 보겠습니다. 메인 콘텐츠가 스크롤되더라도, 이 정보 박스는 화면의 같은 자리에 딱 붙어있을 거예요. 완성된 예제는 다음과 같습니다:

정보 박스는 3개의 탭이 있는 컨테이너이며, 첫 번째 탭이 선택되어 그 내용만 표시되고 있습니다. 고정 위치(fixed position)가 적용되었습니다. 이 정보 박스는 너비가 452픽셀이며 창의 왼쪽 상단 모서리에 고정되어 있습니다. 가짜 콘텐츠가 들어있는 컨테이너가 창의 오른쪽 절반을 차지하고 있으며, 이 콘텐츠 컨테이너는 창보다 키가 커서 스크롤할 수 있습니다. 페이지를 스크롤할 때, 오른쪽 컨테이너는 움직이지만 정보 박스는 화면의 동일한 위치에 단단히 고정되어 있습니다.

참고:
완성된 예제가 실제로 동작하는 모습은 fixed-info-box.html에서 확인하실 수 있습니다 (소스 코드 보기). 이 섹션에서 무엇을 만들게 될지 미리 확인해 보세요.

시작하기 위해, 앞 섹션에서 여러분이 직접 완성한 예제를 사용하시거나 저희 GitHub 저장소에 있는 tabbed-info-box.html 파일의 로컬 복사본을 만드시면 됩니다.

HTML 추가하기 (HTML additions)

가장 먼저, 웹페이지의 메인 콘텐츠를 채워줄 추가적인 HTML이 필요합니다. 태그가 열리는 바로 밑부분, 즉 기존에 있던 <section class="info-box">가 시작하기 직전에 아래의 <section>을 추가해 주세요:

<section class="fake-content">
  <h1>Fake content</h1>
  <p>
    This is fake content. Your main web page contents would probably go here.
  </p>
  <p>
    This is fake content. Your main web page contents would probably go here.
  </p>
  <p>
    This is fake content. Your main web page contents would probably go here.
  </p>
  <p>
    This is fake content. Your main web page contents would probably go here.
  </p>
  <p>
    This is fake content. Your main web page contents would probably go here.
  </p>
  <p>
    This is fake content. Your main web page contents would probably go here.
  </p>
  <p>
    This is fake content. Your main web page contents would probably go here.
  </p>
  <p>
    This is fake content. Your main web page contents would probably go here.
  </p>
</section>

참고:
물론 원하신다면 이 가짜 텍스트 대신 뭔가 그럴싸한 진짜 콘텐츠를 넣어보셔도 좋습니다.

기존 CSS 변경하기 (Changes to the existing CSS)

다음으로, 이 정보 박스를 올바른 자리에 고정하기 위해 기존 CSS를 약간만 수정해야 합니다.
여러분의 .info-box 규칙을 찾아가서 중앙 정렬을 하던 margin: 0 auto;를 지워주세요 (이제 더 이상 가운데 정렬을 원하지 않으니까요). 그리고 position: fixed; 속성을 추가한 뒤, 브라우저 화면의 꼭대기(top)에 딱 붙도록 만들어줍니다.

수정된 코드는 이렇게 생겼을 겁니다:

.info-box {
  width: 452px;
  height: 400px;
  margin: 0 auto;
  position: fixed;
  top: 0;
}

💡 강사님의 실무 팁!
position: fixed는 무조건 브라우저 창(Viewport)을 기준으로 좌표를 잡습니다. 부모 요소에 relative가 있든 없든 다 무시하고 화면의 특정 위치(보통 top, bottom 등)에 영원히 박제됩니다. 실무에서는 헤더(GNB)를 스크롤을 내려도 항상 상단에 따라다니게 만들거나, 오른쪽 아래에 둥둥 떠 있는 '맨 위로 가기(Top)' 버튼을 만들 때 아주 요긴하게 쓰입니다.

메인 콘텐츠 스타일링하기 (Styling the main content)

이 예제의 마지막 작업은 메인 콘텐츠에 약간의 스타일을 입히는 것입니다. CSS의 맨 밑바닥에 다음 규칙을 추가해 주세요:

.fake-content {
  background-color: #a60000;
  color: white;
  padding: 10px;
  height: 2000px;
  margin-left: 470px;
}

.fake-content p {
  margin-bottom: 200px;
}

우선, 이 가짜 콘텐츠 영역에 정보 박스 패널들과 동일한 background-color, color, 그리고 padding을 주었습니다. 그런 다음 콘텐츠 영역 전체에 아주 커다란 margin-left를 주어서 화면의 오른쪽으로 확 밀어냈습니다. 이렇게 하는 이유는? 방금 우리가 화면 왼쪽에 고정시켜둔 정보 박스(info-box)가 위치할 수 있는 넉넉한 공간을 비워두기 위해서입니다. 이 여백을 안 주면 정보 박스가 메인 글자들을 가려버리게(overlap) 되거든요.

이것으로 두 번째 예제가 끝났습니다. 세 번째 예제도 아주 재미있으니 기대해 주세요!


스르륵 나타나는 숨김 패널 (A sliding hidden panel)

우리가 여기서 선보일 마지막 예제는 아이콘을 꾹 누를 때마다 화면 밖에서 스르륵 밀려 들어왔다가 다시 밀려 나가는 패널입니다. 앞서 말씀드렸듯, 이 방식은 특히 스마트폰 같은 좁은 화면의 모바일 레이아웃에서 엄청난 인기를 끄는 방식입니다. 귀중한 화면 공간을 메뉴나 정보 패널로 가득 채우는 대신, 진짜 필요한 콘텐츠를 먼저 보여주고 싶을 때 최고거든요.

우리가 완성할 예제는 이런 모습입니다:

화면의 왼쪽 60%는 빈 공간이고, 오른쪽 40% 영역에는 정보를 보여주는 패널이 자리 잡고 있습니다. 오른쪽 상단 모서리에는 '물음표' 아이콘이 있습니다. 이 물음표 아이콘을 누르면 패널이 화면 안으로 스르륵 밀려 들어왔다가, 다시 누르면 화면 밖으로 스르륵 사라집니다.

참고:
완성된 예제가 실제로 동작하는 모습은 hidden-info-panel.html에서 확인하실 수 있습니다 (소스 코드 보기). 이 섹션에서 무엇을 만들게 될지 미리 확인해 보세요.

이번 예제는 이전 예제에서 코드가 이어지지 않으므로, 완전히 새롭게 시작해야 합니다. 저희 GitHub 저장소에서 hidden-info-panel-start.html 파일의 로컬 복사본을 만드세요. HTML 파일의 안쪽을 들여다보겠습니다:

<button
  type="button"
  id="menu-button"
  aria-haspopup="true"
  aria-controls="info-panel"
  aria-expanded="false"></button>

<aside id="info-panel" aria-labelledby="menu-button"></aside>

우선, 텍스트 대신 특별한 물음표 기호(❔) 문자를 품고 있는 <button> 요소가 하나 있습니다. 이 버튼을 누르면 그 아래에 있는 <aside> 정보 패널이 보였다 안 보였다(show/hide) 하게 될 겁니다. 아래 섹션들에서 이것이 어떻게 작동하는지 전부 파헤쳐 드릴게요.

버튼 스타일링하기 (Styling the button)

먼저 이 버튼부터 처리해 볼까요 — 여는 <style> 태그와 닫는 </style> 태그 사이에 다음 CSS를 추가해 주세요:

#menu-button {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  z-index: 1;

  font-size: 3rem;
  cursor: pointer;
  border: none;
  background-color: transparent;
}

첫 번째 규칙은 <button>을 꾸미는 역할입니다. 여기서 우리가 한 일은:

  • 아이콘이 크고 예쁘게 보이도록 font-size를 큼직하게 설정했습니다.
  • 버튼 특유의 못생긴 테두리(border)를 없애고 배경을 투명(transparent)하게 만들어서, 칙칙한 회색 버튼 대신 예쁜 ? 아이콘만 화면에 보이도록 만들었습니다.
  • position: absolute;를 설정하고, topright 속성을 사용해 아이콘이 화면의 오른쪽 위 구석에 찰싹 달라붙도록 위치를 예쁘게 잡았습니다.
  • z-index를 1로 주었습니다. 왜냐고요? 나중에 정보 패널이 등장했을 때, 이 아이콘이 패널 밑으로 숨어버리면 안 되니까요! 아이콘이 항상 패널 위(top)에 떠 있어야만, 유저가 다시 눌러서 패널을 숨길 수 있겠죠.
  • 마우스 포인터가 아이콘 위에 올라갔을 때 마우스 커서를 링크를 클릭할 때처럼 손가락 모양(hand pointer)으로 바꾸기 위해 cursor: pointer;를 사용했습니다. 유저에게 "이건 클릭할 수 있는 재밌는 버튼이야!"라는 걸 시각적으로 넌지시 알려주는 센스 있는 기능입니다.

패널 스타일링하기 (Styling the panel)

이제 진짜 스르륵 미끄러져 들어올 슬라이딩 패널 자체를 스타일링할 차례입니다. CSS 맨 아래에 다음 규칙을 추가하세요:

#info-panel {
  background-color: #a60000;
  color: white;

  width: 340px;
  height: 100%;
  padding: 0 20px;

  position: fixed;
  top: 0;
  right: -370px;

  transition: 0.6s right ease-out;
}

여기서 꽤 많은 일들이 일어나고 있네요 — 차근차근 분해해 봅시다:

  • 먼저, 정보 박스에 심플한 background-color와 텍스트 color를 설정했습니다.
  • 다음으로, 패널의 width를 특정 픽셀로 고정하고, height는 브라우저 창의 전체 높이(100%)를 꽉 채우도록 설정했습니다.
  • 내용을 보기 좋게 띄우기 위해 약간의 가로 padding도 추가했고요.
  • 이제 포지셔닝 타임입니다! position: fixed;를 주어서 페이지가 스크롤되더라도 이 패널은 항상 화면의 똑같은 위치에 머물게 했습니다. 화면 맨 위(top: 0)에 딱 붙여놓았고, 기본 상태로는 패널 전체 너비(340px + 양옆 패딩)보다 넉넉하게 화면 오른쪽 밖으로 밀어내어 숨기기 위해 right: -370px;로 설정했습니다.
  • 대망의 마지막 줄! 요소에 transition을 주었습니다. 트랜지션은 요소의 상태가 휙휙(abruptly) 변하는 대신, 아주 부드럽고 우아하게 변하도록 만들어주는 마법 같은 기능입니다. 여기서는 자바스크립트에 의해 체크박스가 체크될 때(버튼이 클릭될 때) 패널이 스르륵 화면 안으로 부드럽게 미끄러져 들어오도록 만들려는 의도입니다.

💡 강사님의 실무 팁! (매우 중요)
MDN 문서에서는 이 애니메이션을 만들기 위해 right 속성을 transition 하고 있습니다. 초보자분들이 이해하기엔 직관적이죠. 하지만 실제 모던 프론트엔드 실무(React, Vue 등)에서는 rightleft 같은 레이아웃 속성으로 애니메이션을 주는 것을 극도로 기피합니다!
왜냐하면 right를 이동시키면 브라우저가 화면 전체의 레이아웃을 다시 계산(Reflow/Repaint)해야 해서 폰에서 버벅거릴(Frame Drop) 확률이 높거든요. 실무에서는 화면 밖으로 밀어낼 때 transform: translateX(100%);를 쓰고, 들어올 땐 transform: translateX(0);으로 바꾼 뒤, transition: transform 0.6s ease-out;을 쓰는 것이 프론트엔드 성능 최적화의 절대적인 국룰입니다. 꼭 기억해 두세요!

체크 상태 변경하기 (Setting the checked state)

아직 추가할 CSS가 한 조각 더 남았습니다. CSS 맨 끝에 다음을 추가해 주세요:

#info-panel.open {
  right: 0px;
}

이 규칙은 아주 명확합니다. 정보 패널(<aside>)에 .open이라는 클래스가 부여되면, 패널의 right 속성을 0px로 바꿔라! 그러면 화면 오른쪽 밖으로 숨어있던 녀석이 화면 오른쪽 끝에 딱 붙도록 위치가 바뀌면서 (트랜지션 덕분에 부드럽게) 나타나겠죠. 반대로 .open 클래스를 제거하면 다시 원래의 -370px로 돌아가 숨어버리게 됩니다.

이제 이 버튼을 클릭할 때 정보 패널에 .open 클래스를 붙였다 뗐다(add/remove) 해줄 약간의 자바스크립트가 필요합니다. HTML 문서의 <script> 태그 사이에 다음 코드를 추가하세요:

const button = document.querySelector("#menu-button");
const panel = document.querySelector("#info-panel");

button.addEventListener("click", () => {
  panel.classList.toggle("open");
  button.setAttribute("aria-expanded", panel.classList.contains("open"));
});

이 자바스크립트 코드는 버튼에 클릭 이벤트 핸들러(click event handler)를 달아줍니다.
유저가 클릭할 때마다 이 핸들러는 정보 패널 요소에 open이라는 클래스를 토글(toggle, 있으면 빼고 없으면 붙임) 시키고, 그 결과로 패널이 뷰포트 안팎으로 스르륵 미끄러지듯 이동하게 됩니다.
또한 시각 장애인용 스크린 리더 등을 위해(접근성, accessibility), 메뉴가 현재 펼쳐져 있는지 아닌지를 알려주도록 버튼의 aria-expanded 속성값도 함께 업데이트해 줍니다.

어때요? 이게 바로 토글되는 정보 패널 효과를 만드는 가장 쉬우면서도 강력한 방법입니다!


요약 (Summary)

이것으로 우리의 기나긴 포지셔닝(positioning) 탐험을 모두 마칩니다. 이제 여러분은 포지셔닝의 기본적인 동작 원리가 어떻게 굴러가는지 감을 잡으셨을 테고, 이를 응용해서 꽤 흥미롭고 유용한 UI 컴포넌트들을 직접 만들어 볼 수 있게 되셨습니다.

혹시 이 내용이 단번에 다 이해되지 않았더라도 너무 좌절하지 마세요! 포지셔닝은 꽤나 고급 주제(advanced topic)에 속합니다. 이해가 안 갈 땐 언제든지 이 문서를 다시 처음부터 읽어보고 예제를 뜯어보면서 지식을 다지시면 됩니다.


MDN 개선에 도움을 주세요 (Help improve MDN)

기여하는 방법 알아보기 (Learn how to contribute)

이 페이지의 마지막 수정일은 Aug 20, 2025 이며, MDN 기여자들(MDN contributors)에 의해 작성되었습니다.

오늘도 정말 고생 많으셨습니다! 실무에서 밥 먹듯이 쓰이는 모달 창, 툴팁, 햄버거 메뉴가 다 오늘 배운 포지셔닝 원리에서 출발합니다. 이해가 안 되는 부분이 있다면 언제든 팍팍 물어봐 주세요!

profile
프론트에_가까운_풀스택_개발자

0개의 댓글