안녕하세요, 디자인 엔지니어 올리브예요. 멋진 사이트 분석 2편이에요.

EALARA의 호버·스크롤 인터랙션 4가지는 모두 CSS 몇 줄로 따라 만들 수 있어요. 메뉴와 버튼은 ::before 배경이 커지는 호버, 작업물 카드는 position: sticky, 저널 카드는 스크롤 값으로 가로 위치를 옮기는 짧은 스크립트예요. 아래 데모는 이 블로그 색으로 바꿔서 직접 만들어 본 거예요. 마우스를 올리거나 스크롤해 보세요.

1편에서는 EALARA의 색, 큰 제목, 섹션 틀을 봤어요. 다시 들여다보니 제 눈에 오래 남은 건 작은 움직임이었어요. 그중 네 가지를 골라 원본이 어떻게 움직이는지 보고, 똑같이 만들어 봤어요.

구분 원본에서 본 것 만드는 법
메뉴 호버 글자 아래 1px 점이 배경으로 차올라요 ::before 크기 전환
버튼 호버 화살표 원이 버튼 전체로 퍼지고 화살표가 꺾여요 ::before 너비 전환 + 회전
작업물 카드 다음 카드가 올라오며 앞 카드를 덮어요 position: sticky
저널 카드 스크롤하면 카드가 오른쪽에서 들어와요 스크롤 값 → translateX

1. 메뉴 호버는 어떻게 움직이나요?

원본은 어떻게 움직이나요?

메뉴 링크마다 옅은 알약이 깔려 있어요. 마우스를 올리면 글자 아래 가운데에 1px짜리 점이 생기고, 그 점이 0.4초 동안 일정한 속도로 커지면서 글자 뒤를 채워요. 글자 색도 같은 0.4초 동안 바뀌고, 마우스를 떼면 똑같은 속도로 다시 점으로 줄어들어요. 보통 메뉴 호버는 배경색이 한 번에 바뀌는데, 여기서는 옅은 알약 안을 아래에서부터 '채워요'.

따라 만들면?

메뉴 글자에 마우스를 올려 보세요. 속도와 곡선은 원본을 프레임 단위로 재서 그대로 맞췄어요.

<style>
  .stage { display: grid; place-items: center; height: 100vh; background: #F4F6F4; }
  .nav { display: flex; gap: 8px; }
  /* 링크마다 옅은 알약 (원본: 검정 10% + 배경 흐림) */
  .nav a {
    position: relative; isolation: isolate; overflow: hidden;
    padding: 8px 24px; border-radius: 38px;
    background: rgba(10, 31, 14, .06); backdrop-filter: blur(40px);
    color: #0A1F0E; font-size: 15px; font-weight: 500; text-decoration: none;
    transition: color .4s linear;
  }
  /* 글자 아래 가운데 1px 점 → 링크 전체로 차오른다 (원본: 0.4초, linear) */
  .nav a::before {
    content: ""; position: absolute; z-index: -1;
    left: 50%; bottom: -1px; width: 1px; height: 1px; /* 쉴 때는 알약 바로 아래라 잘려서 안 보인다 */
    border-radius: 16px; background: #00A30F;
    transform: translateX(-50%);
    transition: width .4s linear, height .4s linear;
  }
  .nav a:hover { color: #fff; }
  .nav a:hover::before { width: calc(100% + 2px); height: calc(100% + 2px); }
  @media (max-width: 420px) { .nav { gap: 4px; } .nav a { padding: 8px 12px; font-size: 13px; } }
</style>
<div class="stage">
  <nav class="nav">
    <a href="#">About</a><a href="#">Services</a><a href="#">Works</a><a href="#">Blog</a>
  </nav>
</div>
  • 배경은 ::before 하나: 처음엔 1×1px 점, 호버하면 링크 크기(100%×100%)까지 커져요.
  • bottom: -1px + left: 50%: 점을 알약 바로 아래 가운데에 숨겨 두면, 호버할 때 위와 양옆으로 차올라요.
  • 링크마다 옅은 알약 + overflow: hidden: 차오르는 배경은 둥글기 16px이지만, 링크(둥글기 38px)가 잘라 줘서 끝 모양은 완전한 알약이 돼요.
  • linear 0.4초: 원본은 가속 없이 일정한 속도예요. 그래서 커지는 동안 작은 알약 모양이 눈에 보여요.

2. 버튼 호버는 어떻게 움직이나요?

원본은 어떻게 움직이나요?

히어로의 버튼 두 개는 오른쪽에 화살표가 든 동그라미가 있어요. 마우스를 올리면 이 동그라미가 왼쪽으로 늘어나 버튼 전체를 채우고, 색이 뒤집히고, 화살표가 → 에서 ↗ 로 꺾여요. 흰 버튼은 검게, 투명한 버튼은 하얗게 바뀌어서 두 버튼이 서로 반대로 움직여요.

따라 만들면?

두 버튼에 차례로 마우스를 올려 보세요.

<style>
  .stage { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; align-items: center; height: 100vh; padding: 16px; background: #F4F6F4; }
  .btn {
    --fill: #00A30F; --ink: #fff;
    position: relative; isolation: isolate; overflow: hidden;
    display: inline-flex; align-items: center; gap: 12px;
    padding: 5px 5px 5px 22px; border-radius: 999px;
    border: 1px solid #E6E9E6; background: #fff; color: #0A1F0E;
    font-size: 15px; font-weight: 600; text-decoration: none;
    transition: color .45s;
  }
  .btn.alt { --fill: #fff; --ink: #00A30F; border-color: #00A30F; background: #00A30F; color: #fff; }
  /* 오른쪽 동그라미가 버튼 전체로 퍼진다 */
  .btn::before {
    content: ""; position: absolute; z-index: -1;
    top: 5px; right: 5px; bottom: 5px; width: 40px;
    border-radius: 999px; background: var(--fill);
    transition: width .45s cubic-bezier(.2,.8,.2,1);
  }
  .btn:hover { color: var(--ink); }
  .btn:hover::before { width: calc(100% - 10px); }
  .icon { display: grid; place-items: center; width: 40px; height: 40px; color: var(--ink); transition: transform .45s cubic-bezier(.2,.8,.2,1); }
  .btn:hover .icon { transform: rotate(-45deg); }
</style>
<div class="stage">
  <a class="btn" href="#">View Selected Work
    <span class="icon"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg></span>
  </a>
  <a class="btn alt" href="#">Start a project
    <span class="icon"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg></span>
  </a>
</div>
  • 동그라미 = ::before: 오른쪽에 붙인 채 width만 40px → 100%로 늘려요. 그래서 오른쪽에서 왼쪽으로 퍼져요.
  • 색 뒤집기는 변수 두 개: --fill(퍼지는 색)과 --ink(바뀐 글자 색)만 바꾸면 반대 버튼이 돼요.
  • 화살표는 rotate(-45deg): → 가 ↗ 로 꺾이면서 "누르면 이동해요"라는 느낌을 줘요.

3. 작업물 카드는 어떻게 바뀌나요?

원본은 어떻게 움직이나요?

Selected Works에서 스크롤을 내리면 다음 사진 카드가 아래에서 올라와 앞 카드를 덮어요. 앞 카드는 위쪽 끝만 살짝 남아서 카드가 겹겹이 쌓이는 것처럼 보여요. 카드가 바뀔 때마다 Fashion → Portrait → Editorial → Campaign 라벨도 같이 바뀌어서, 넘겨 보는 재미가 있어요.

따라 만들면?

상자 안에서 스크롤해 보세요.

<style>
  body { background: #F4F6F4; }
  .hint { position: sticky; top: 0; z-index: 10; margin: 0; padding: 12px; text-align: center; font-size: 13px; color: #6B7F6E; background: #F4F6F4; }
  .stack { max-width: 460px; margin: 0 auto; padding: 0 20px 160px; }
  .card {
    position: sticky; top: calc(56px + var(--i) * 12px);
    height: 280px; margin-bottom: 48px; padding: 18px;
    display: flex; flex-direction: column; justify-content: space-between;
    border-radius: 16px; box-shadow: 0 -10px 24px rgba(10, 31, 14, .10);
  }
  .card b { font-size: 40px; line-height: 1; }
  .label { align-self: center; padding: 6px 14px; border-radius: 999px; background: #fff; color: #0A1F0E; font-size: 13px; font-weight: 600; }
</style>
<p class="hint">↓ 스크롤해 보세요</p>
<div class="stack">
  <div class="card" style="--i: 0; background: #00A30F; color: #fff;"><b>01</b><span class="label">Fashion</span></div>
  <div class="card" style="--i: 1; background: #E5F2E7; color: #007A0B;"><b>02</b><span class="label">Portrait</span></div>
  <div class="card" style="--i: 2; background: #007A0B; color: #fff;"><b>03</b><span class="label">Editorial</span></div>
  <div class="card" style="--i: 3; background: #0A1F0E; color: #fff;"><b>04</b><span class="label">Campaign</span></div>
</div>
  • 핵심은 position: sticky 한 줄: 카드마다 화면 위쪽에 붙어 있고, 뒤에 오는 카드가 그 위를 덮어요.
  • top을 카드마다 12px씩 더 내리기: 앞 카드의 위쪽 끝이 남아서 '쌓인' 느낌이 나요.
  • 위로 드리운 그림자: box-shadow를 위쪽(-10px)으로 줘서 올라오는 카드가 앞 카드 위에 떠 보여요.

4. 저널 카드는 어떻게 들어오나요?

원본은 어떻게 움직이나요?

From The Journal 섹션에서는 세로로 긴 카드들이 한 줄로 놓여 있어요. 스크롤을 내리면 카드 줄이 왼쪽으로 밀려 가고, 오른쪽에서 새 카드가 들어와요. 스크롤을 멈추면 카드도 멈춰요. 세로 스크롤로 가로 움직임을 만드니, 글 목록인데도 갤러리를 넘기는 기분이 들어요.

따라 만들면?

상자 안에서 스크롤해 보세요. 오른쪽에서 들어오는 카드는 아래에서 살짝 올라오게 해서, 제가 원본에서 느낀 '올라오는' 느낌을 조금 더 살렸어요.

<style>
  body { background: #F4F6F4; }
  .scroller { height: 400vh; }
  .sticky { position: sticky; top: 0; height: 100vh; overflow: hidden; display: flex; flex-direction: column; justify-content: center; gap: 18px; }
  .title { margin: 0; text-align: center; font-size: 18px; font-weight: 700; }
  .title small { display: block; margin-top: 4px; font-size: 12px; font-weight: 400; color: #6B7F6E; }
  .track { display: flex; gap: 14px; width: max-content; padding-left: 20px; will-change: transform; }
  .card { flex: none; width: 160px; overflow: hidden; background: #fff; border: 1px solid #E6E9E6; border-radius: 12px; will-change: transform, opacity; }
  .thumb { height: 170px; }
  .meta { padding: 10px 12px 12px; font-size: 13px; }
  .meta b { display: block; margin-bottom: 2px; }
  .meta span { color: #6B7F6E; font-size: 11px; }
</style>
<div class="scroller">
  <div class="sticky">
    <p class="title">Notes from the blog<small>↓ 스크롤해 보세요</small></p>
    <div class="track">
      <div class="card"><div class="thumb" style="background: #00A30F"></div><div class="meta"><b>Chasing Light</b><span>SEP 18</span></div></div>
      <div class="card"><div class="thumb" style="background: #E5F2E7"></div><div class="meta"><b>The Art of Seeing</b><span>SEP 12</span></div></div>
      <div class="card"><div class="thumb" style="background: #007A0B"></div><div class="meta"><b>Frames in Motion</b><span>SEP 05</span></div></div>
      <div class="card"><div class="thumb" style="background: #0A1F0E"></div><div class="meta"><b>Quiet Moments</b><span>AUG 29</span></div></div>
    </div>
  </div>
</div>
<script>
  const track = document.querySelector('.track');
  // 카드 묶음을 한 번 더 붙여서 끝없이 이어지게 한다
  const count = track.children.length;
  [...track.children].forEach(card => track.appendChild(card.cloneNode(true)));
  const cards = [...track.children];

  function update() {
    const loop = cards[count].offsetLeft - cards[0].offsetLeft; // 카드 묶음 하나의 폭
    const x = (scrollY * 0.8) % loop;
    track.style.transform = `translateX(${-x}px)`;
    // 화면 오른쪽에 있을수록 아래에 있다가, 왼쪽으로 오면서 올라온다
    cards.forEach(card => {
      const left = card.getBoundingClientRect().left;
      const t = Math.min(1, Math.max(0, (left - innerWidth * 0.5) / (innerWidth * 0.5)));
      card.style.transform = `translateY(${t * 48}px)`;
      card.style.opacity = 1 - t * 0.5;
    });
  }
  addEventListener('scroll', update, { passive: true });
  addEventListener('resize', update);
  update();
</script>
  • 세로 스크롤 → 가로 이동: 섹션을 sticky로 붙여 두고, scrollY만큼 카드 줄을 왼쪽으로 옮겨요.
  • 끝없이 이어지기: 카드 묶음을 한 번 더 복사해 두고, 묶음 하나의 폭으로 나눈 나머지(%)만큼만 옮겨요.
  • 올라오는 느낌: 카드가 화면 오른쪽에 있을수록 아래로 내리고 흐리게 해서, 왼쪽으로 오며 제자리로 올라와요.

올리브의 한마디

1편을 쓸 때는 색과 큰 제목만 보였는데, 다시 보니 이 사이트를 기억에 남게 만든 건 이런 작은 움직임이었어요. 그런데 직접 만들어 보니 대부분 CSS 속성 한두 개를 전환하는 것이 전부였어요. 메뉴와 버튼은 ::before 크기를 바꾸고, 카드는 sticky로 붙여 두는 정도예요.

어려운 기술보다 어디서 시작해서 어디로 커지는지를 정하는 게 디테일의 차이였어요. 점이 배경으로 차오르고, 동그라미가 버튼으로 퍼지는 것처럼요. 저도 이 블로그 버튼에 하나쯤 가져와 볼까 해요.

오늘도 읽어 주셔서 고마워요. 다음 글에서 만나요! 🌿