Nested
nested 옵션으로 중첩된 Flicking에서 자식이 경계에 도달하면 부모 Flicking으로 제어를 전환합니다. 같은 방향의 중첩 Flicking에서 자연스러운 UX를 제공합니다.
- JavaScript
- React
- Vue@3
import Flicking from "@egjs/flicking"; import "@egjs/flicking/dist/flicking.css"; import "./styles.css"; // nested: false new Flicking("#outer-false", { align: "center" }); document.querySelectorAll("#outer-false .inner-viewport").forEach(el => { new Flicking(el, { nested: false, align: "center", bound: true }); }); // nested: true new Flicking("#outer-true", { align: "center" }); document.querySelectorAll("#outer-true .inner-viewport").forEach(el => { new Flicking(el, { nested: true, align: "center", bound: true }); });
import Flicking from "@egjs/react-flicking"; import "@egjs/react-flicking/dist/flicking.css"; import "./styles.css"; export default function App() { return ( <div> {/* nested: false */} <div className="demo-container"> <div className="demo-label">nested: false (parent does not move at inner boundary)</div> <div className="demo-hint">The outer Flicking does not move when the inner one reaches its end</div> <Flicking align="center"> <div className="outer-panel outer-1"> <Flicking className="inner-viewport" nested={false} align="center" bound={true}> <div className="inner-panel">Inner 1</div> <div className="inner-panel">Inner 2</div> <div className="inner-panel">Inner 3</div> </Flicking> </div> <div className="outer-panel outer-2"> <Flicking className="inner-viewport" nested={false} align="center" bound={true}> <div className="inner-panel">Inner 1</div> <div className="inner-panel">Inner 2</div> <div className="inner-panel">Inner 3</div> </Flicking> </div> <div className="outer-panel outer-3"> <Flicking className="inner-viewport" nested={false} align="center" bound={true}> <div className="inner-panel">Inner 1</div> <div className="inner-panel">Inner 2</div> <div className="inner-panel">Inner 3</div> </Flicking> </div> </Flicking> </div> {/* nested: true */} <div className="demo-container"> <div className="demo-label">nested: true (propagates to parent at inner boundary)</div> <div className="demo-hint">The outer Flicking moves when the inner one reaches its end</div> <Flicking align="center"> <div className="outer-panel outer-1"> <Flicking className="inner-viewport" nested={true} align="center" bound={true}> <div className="inner-panel">Inner 1</div> <div className="inner-panel">Inner 2</div> <div className="inner-panel">Inner 3</div> </Flicking> </div> <div className="outer-panel outer-2"> <Flicking className="inner-viewport" nested={true} align="center" bound={true}> <div className="inner-panel">Inner 1</div> <div className="inner-panel">Inner 2</div> <div className="inner-panel">Inner 3</div> </Flicking> </div> <div className="outer-panel outer-3"> <Flicking className="inner-viewport" nested={true} align="center" bound={true}> <div className="inner-panel">Inner 1</div> <div className="inner-panel">Inner 2</div> <div className="inner-panel">Inner 3</div> </Flicking> </div> </Flicking> </div> </div> ); }
<template> <div> <!-- nested: false --> <div class="demo-container"> <div class="demo-label">nested: false (parent does not move at inner boundary)</div> <div class="demo-hint">The outer Flicking does not move when the inner one reaches its end</div> <Flicking :options="{ align: 'center' }"> <div :key="0" class="outer-panel outer-1"> <Flicking class="inner-viewport" :options="{ nested: false, align: 'center', bound: true }"> <div :key="0" class="inner-panel">Inner 1</div> <div :key="1" class="inner-panel">Inner 2</div> <div :key="2" class="inner-panel">Inner 3</div> </Flicking> </div> <div :key="1" class="outer-panel outer-2"> <Flicking class="inner-viewport" :options="{ nested: false, align: 'center', bound: true }"> <div :key="0" class="inner-panel">Inner 1</div> <div :key="1" class="inner-panel">Inner 2</div> <div :key="2" class="inner-panel">Inner 3</div> </Flicking> </div> <div :key="2" class="outer-panel outer-3"> <Flicking class="inner-viewport" :options="{ nested: false, align: 'center', bound: true }"> <div :key="0" class="inner-panel">Inner 1</div> <div :key="1" class="inner-panel">Inner 2</div> <div :key="2" class="inner-panel">Inner 3</div> </Flicking> </div> </Flicking> </div> <!-- nested: true --> <div class="demo-container"> <div class="demo-label">nested: true (propagates to parent at inner boundary)</div> <div class="demo-hint">The outer Flicking moves when the inner one reaches its end</div> <Flicking :options="{ align: 'center' }"> <div :key="0" class="outer-panel outer-1"> <Flicking class="inner-viewport" :options="{ nested: true, align: 'center', bound: true }"> <div :key="0" class="inner-panel">Inner 1</div> <div :key="1" class="inner-panel">Inner 2</div> <div :key="2" class="inner-panel">Inner 3</div> </Flicking> </div> <div :key="1" class="outer-panel outer-2"> <Flicking class="inner-viewport" :options="{ nested: true, align: 'center', bound: true }"> <div :key="0" class="inner-panel">Inner 1</div> <div :key="1" class="inner-panel">Inner 2</div> <div :key="2" class="inner-panel">Inner 3</div> </Flicking> </div> <div :key="2" class="outer-panel outer-3"> <Flicking class="inner-viewport" :options="{ nested: true, align: 'center', bound: true }"> <div :key="0" class="inner-panel">Inner 1</div> <div :key="1" class="inner-panel">Inner 2</div> <div :key="2" class="inner-panel">Inner 3</div> </Flicking> </div> </Flicking> </div> </div> </template> <script setup> import Flicking from "@egjs/vue3-flicking"; import "@egjs/vue3-flicking/dist/flicking.css"; </script> <style> .flicking-viewport.vertical { display: block; width: 100%; } .flicking-panel { width: 200px; height: 150px; margin-right: 10px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 24px; font-weight: bold; color: white; } .panel-1 { background: #3e8ed0; } .panel-2 { background: #00d1b2; } .panel-3 { background: #f14668; } .panel-4 { background: #ffe08a; color: #333; } .panel-5 { background: #48c78e; } .demo-container { margin-bottom: 24px; } .demo-label { font-weight: bold; margin-bottom: 8px; color: #666; } .button { padding: 8px 16px; margin: 4px; border: 2px solid #3498db; background: transparent; color: #3498db; border-radius: 4px; cursor: pointer; font-size: 14px; } .button:hover { background: #3498db; color: white; } .controls { display: flex; justify-content: center; margin-top: 16px; gap: 8px; } .outer-panel { width: 80%; height: 180px; padding: 10px; box-sizing: border-box; } .outer-1 { background: #3e8ed0; } .outer-2 { background: #00d1b2; } .outer-3 { background: #f14668; } .inner-viewport { height: 100%; background: rgba(255, 255, 255, 0.2); border-radius: 8px; } .inner-panel { width: 60%; height: 140px; background: rgba(255, 255, 255, 0.3); border: 2px solid rgba(255, 255, 255, 0.5); } .demo-hint { font-size: 12px; color: #888; margin-bottom: 8px; } </style>
요약
주요 옵션
| 옵션 | 타입 | 기본값 | 설명 |
|---|---|---|---|
nested | boolean | false | 경계 도달 시 부모로 제어 전환 |
값별 비교
| 값 | 동작 | 적합한 상황 |
|---|---|---|
false | 내부 경계에서 멈춤, 부모 이동 안 됨 (기본값) | 독립적인 내부 캐러셀 |
true | 내부 경계 도달 후 부모로 제어 전환 | 같은 방향의 중첩 캐러셀 |
상세 설명
nested 동작 원리
nested: true로 설정된 자식 Flicking이 첫 번째 또는 마지막 패널에 도달한 후 같은 방향으로 계속 드래그하면, 부모 Flicking이 대신 이동합니다.
// 부모 Flicking
<Flicking>
<div className="panel">
{/* 자식 Flicking - nested 설정 */}
<Flicking nested={true} bound={true}>
<div>내부 1</div>
<div>내부 2</div>
</Flicking>
</div>
</Flicking>
언제 필요한가?
- 필요한 경우: 부모와 자식이 같은 방향(둘 다 horizontal: true 또는 둘 다 false)
- 불필요한 경우: 부모와 자식이 다른 방향(하나는 수평, 하나는 수직) - 자동으로 구분됨
연관 옵션
- bound와의 관계:
bound: true와 함께 사용하면 내부 경계가 명확해져 nested 동작이 더 자연스럽습니다. - horizontal과의 관계: 부모/자식의 horizontal 값이 다르면 nested 옵션 없이도 자연스럽게 동작합니다.
사용 시나리오
언제 사용하나요?
- nested: true: 카테고리별 상품 캐러셀 (외부: 카테고리, 내부: 상품)
- nested: false: 독립적으로 동작해야 하는 내부 캐러셀
주의사항
자식 Flicking에 설정
nested 옵션은 자식(내부) Flicking에 설정합니다. 부모에는 설정할 필요가 없습니다.
다른 방향이면 불필요
부모가 수평이고 자식이 수직(또는 반대)이면 nested 옵션 없이도 자연스럽게 동작합니다.
관련 링크
관련 옵션
bound: 경계 제한 (nested와 함께 사용 권장)horizontal: 이동 방향