jQuery / Method / .fadeIn() - 선택한 요소를 서서히 나타나게 하는 메서드

jQuery의 .fadeIn()은 숨겨진 요소를 표시하면서 불투명도를 점차 높여 나타나게 합니다. .fadeIn(800)의 800은 기다리는 시간이 아니라 효과가 진행되는 800밀리초입니다. 효과가 끝난 뒤 작업하려면 호출 바로 다음 줄이 아니라 완료 콜백에서 처리해야 합니다.

실행 시간·easing·완료 콜백 이해하기

.fadeIn() 공식 문서의 주요 형식은 .fadeIn(duration, easing, complete)이며 필요한 선택 인수는 생략할 수 있습니다. duration은 밀리초 단위라 숫자가 클수록 천천히 나타납니다. complete는 요소의 효과가 끝난 뒤 실행할 함수입니다.

시간 지정 실행 시간 표현
생략 기본 400밀리초 .fadeIn()
숫자 지정한 밀리초 .fadeIn(800)
"fast" 200밀리초 .fadeIn("fast")
"slow" 600밀리초 .fadeIn("slow")
0 점진적 전환 없이 최종 상태 .fadeIn(0)

easing은 진행 중 속도가 변하는 방식을 정하며 기본값은 swing이고 일정한 진행에는 linear를 씁니다. linear는 duration 자리에 단독으로 넣는 것이 아니라 .fadeIn(800, "linear")처럼 시간 뒤에 지정합니다. 이 글의 전체 예제는 기본 easing을 사용합니다.

두 알림 패널을 나타내는 전체 예제

전체 코드를 UTF-8의 fadein-demo.html로 저장하고 브라우저에서 엽니다. 공식 jQuery의 전체 배포 파일을 CDN(Content Delivery Network, 콘텐츠 전송 네트워크)에서 읽을 인터넷 연결이 필요하며 별도 설치는 없습니다. effects 모듈이 제외된 slim 배포본에는 .fadeIn()이 없으므로 전체 파일을 사용합니다.

코드는 4.0.0을 사용합니다. 패널의 중간 불투명도, 800·200밀리초 실행, 요소별 완료, 중도 초기화와 즉시 표시를 3.7.1과 4.0.0에서 실행해 확인했습니다. 운영체제에서 동작 줄이기를 사용하면 효과를 생략하도록 구성했습니다.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Fade in two notice panels</title>
  <style>
    body { font: 16px/1.6 sans-serif; margin: 24px; }
    .panel { display: none; padding: 16px; margin: 12px 0; background: #e4f3f1; }
    button, select { padding: 8px; margin: 4px; }
  </style>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
</head>
<body>
  <h1>Fade in two notice panels</h1>
  <label for="duration">Duration:</label>
  <select id="duration">
    <option value="800">800 ms</option>
    <option value="200">200 ms</option>
  </select>
  <label><input type="checkbox" id="instant"> Show instantly</label>
  <button type="button" id="show">Show notices</button>
  <button type="button" id="reset">Reset</button>
  <div id="notices">
    <div class="panel" id="one">Notice one</div>
    <div class="panel" id="two">Notice two</div>
  </div>
  <p id="result" aria-live="polite"></p>
  <script>
    $(function () {
      const $panels = $("#notices > .panel");
      let completed = 0;
      function report(state) {
        $("#result").text(`state=${state} | completed=${completed}`);
      }
      function clearPanels() {
        $panels.stop(true, false).hide().css("opacity", "");
        completed = 0;
      }
      $("#show").on("click", function () {
        clearPanels();
        const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
        const duration = $("#instant").prop("checked") || reduce
          ? 0 : Number($("#duration").val());
        $("#show").prop("disabled", true);
        report("showing");
        $panels.fadeIn(duration, function () {
          completed++;
          if (completed === $panels.length) {
            report("visible");
            $("#show").prop("disabled", false);
          } else {
            report("showing");
          }
        });
      });
      $("#reset").on("click", function () {
        clearPanels();
        $("#show").prop("disabled", false);
        report("hidden");
      });
      report("hidden");
    });
  </script>
</body>
</html>

초기에는 두 패널이 모두 display: none 상태이며 결과는 다음과 같습니다.

state=hidden | completed=0
  1. Show instantly를 끄고 Duration을 800 ms로 둔 뒤 Show notices를 누릅니다. 패널 둘이 함께 나타나며 진행 중에는 Show notices가 비활성화됩니다.
  2. 완료되면 두 패널이 보이고 state=visible | completed=2가 됩니다. 숫자 2는 버튼 클릭 수가 아니라 완료한 요소 수입니다.
  3. Reset을 눌러 숨긴 뒤 200 ms를 선택하고 다시 실행하면 같은 결과에 더 빠르게 도달합니다. 시간을 바꾸는 것만으로 이미 진행 중인 효과가 바뀌지는 않습니다.
  4. 800 ms로 실행 도중 Reset을 누르면 즉시 숨겨지고 state=hidden | completed=0으로 돌아갑니다. 원래 실행 시간이 지난 뒤에도 완료 표시가 다시 나타나지 않습니다.
  5. Show instantly를 켜면 duration이 0이 되어 점진적 효과 없이 두 패널을 표시합니다. 운영체제의 동작 줄이기 설정이 감지된 경우도 같습니다.

효과가 보이지 않을 때는 먼저 즉시 표시 체크와 prefers-reduced-motion 설정을 확인합니다. 이 예제는 사용자의 동작 줄이기 요청을 우선해 0을 선택하므로 Duration이 800이어도 바로 표시될 수 있습니다.

완료 콜백은 요소마다 실행하기

.fadeIn() 호출은 효과가 끝날 때까지 다음 JavaScript 실행을 막지 않습니다. 호출 다음 줄에서 완료 상태를 표시하면 화면의 효과가 진행 중인데도 끝났다고 표시할 수 있습니다. 예제는 콜백에서 completed를 늘려 실제 완료를 집계합니다.

선택한 두 패널은 각각 콜백을 한 번 실행합니다. 따라서 콜백을 ‘선택한 집합 전체가 끝나고 한 번만 호출되는 함수’로 생각하면 안 됩니다. completed가 $panels.length에 도달했을 때만 visible을 표시하고 버튼을 다시 켭니다. 이 패널 집합은 실습 중 바꾸지 않으며, 일반 함수 콜백의 this는 방금 완료한 DOM 요소입니다.

중도 초기화와 동작하지 않을 때 확인하기

.stop(true, false)의 첫 true는 남은 효과 대기열을 지우고, 두 번째 false는 현재 효과를 끝까지 완료시키지 않고 중단합니다. 완료 콜백도 실행하지 않으므로 Reset 후에 이전 완료가 끼어들지 않습니다. 이어서 .hide()로 숨기고 중간에 남을 수 있는 인라인 opacity를 지운 뒤 카운터를 0으로 되돌립니다.

Show notices를 다시 실행할 때도 먼저 같은 정리를 하여 숨긴 상태에서 재시작합니다. 실행 중 버튼을 비활성화하므로 클릭이 누적되어 효과가 줄줄이 재생되는 일을 피합니다. 초기화는 예제의 패널과 카운터에만 적용하며 전역 효과 설정을 바꾸지 않습니다.

동작하지 않으면 Network에서 전체 jQuery 파일이 로드되었는지, Console에 .fadeIn is not a function 같은 오류가 있는지 확인합니다. 선택자가 비어 있으면 요소별 콜백도 실행되지 않습니다. visibility: hidden이나 숨겨진 부모, 강한 CSS display 규칙은 별도로 확인해야 하며, 단순히 불투명도만 바뀐다고 모든 숨김 조건이 해제되는 것은 아닙니다.