μ λμ μ΄κ³ μ±κ³Ό κ°μ μΉ κ²½νμ ꡬννμΈμ. μ΄ μ’ ν© κ°μ΄λλ λμ νμ΄μ§ μ ν μ€νμΌλ§μ μν κ°λ ₯ν CSS λ·° νΈλμ§μ μμ¬ μμλ₯Ό μ€μ μμ μ λͺ¨λ² μ¬λ‘μ ν¨κ» νμν©λλ€.
CSS λ·° νΈλμ§μ λ§μ€ν°νκΈ°: μμ¬ μμ μ€νμΌλ§ μ¬μΈ΅ λΆμ
λμμμ΄ μ§ννλ μΉ κ°λ° νκ²½μμ λ§€λλ½κ³ μ λμ μ΄λ©° λ§€λ ₯μ μΈ μ¬μ©μ κ²½νμ μΆκ΅¬νλ κ²μ λ³μΉ μλ κ³Όμ μ λλ€. μλ κ° κ°λ°μλ€μ μΉκ³Ό λ€μ΄ν°λΈ μ ν리μΌμ΄μ κ°μ 격차λ₯Ό μ€μ΄κΈ° μν΄ λ Έλ ₯ν΄μμΌλ©°, νΉν νμ΄μ§ μ νμ λΆλλ¬μμ μ€μ μ λμμ΅λλ€. μ ν΅μ μΈ μΉ νμμ μ’ μ’ μ¬μ©μμ λͺ°μ μ μκ°μ μΌλ‘ κΉ¨λ¨λ¦¬λ κ±°μΉ μ 체 νμ΄μ§ μλ‘κ³ μΉ¨βμ¦, ν λΉ ν° νλ©΄βμ μ λ°ν©λλ€. μ±κΈ νμ΄μ§ μ ν리μΌμ΄μ (SPA)μ΄ μ΄λ₯Ό μννμ§λ§, μλ―Έ μλ λ§μΆ€ν μ νμ λ§λλ κ²μ μ¬μ ν 볡μ‘νκ³ μ’ μ’ λΆμμ ν μμ μ΄μμΌλ©°, μλ°μ€ν¬λ¦½νΈ λΌμ΄λΈλ¬λ¦¬μ 볡μ‘ν μν κ΄λ¦¬μ ν¬κ² μμ‘΄νμ΅λλ€.
μΉμμ UI λ³κ²½μ μ²λ¦¬νλ λ°©μμ νμ ν μ€λΉκ° λ νκΈ°μ μΈ κΈ°μ μΈ CSS λ·° νΈλμ§μ APIκ° λ±μ₯νμ΅λλ€. μ΄ κ°λ ₯ν APIλ μλ‘ λ€λ₯Έ DOM μν κ°μ μ λλ©μ΄μ μ μν κ°λ¨νλ©΄μλ λ§€μ° μ μ°ν λ©μ»€λμ¦μ μ 곡νμ¬, μ¬μ©μλ€μ΄ κΈ°λνκ² λ μΈλ ¨λκ³ μ±κ³Ό κ°μ κ²½νμ κ·Έ μ΄λ λλ³΄λ€ μ½κ² λ§λ€ μ μλλ‘ ν©λλ€. μ΄ APIμ ν΅μ¬μ μΈ νμ μλ‘μ΄ CSS μμ¬ μμ μΈνΈμ μμ΅λλ€. μ΄κ²λ€μ μΌλ°μ μΈ μ νμκ° μλλλ€. λΈλΌμ°μ κ° μ νμ λͺ¨λ λ¨κ³λ₯Ό μΈλ°νκ² μ μ΄ν μ μλλ‘ λμ μΌλ‘ μμ±νλ μμ μμμ λλ€. μ΄ κ°μ΄λλ μ΄ μμ¬ μμ νΈλ¦¬λ₯Ό μ¬μΈ΅μ μΌλ‘ νꡬνλ©°, κ° κ΅¬μ± μμλ₯Ό μ€νμΌλ§νμ¬ μ μΈκ³ μ¬μ©μλ₯Ό μν λ©μ§κ³ μ±λ₯μ΄ λ°μ΄λλ©° μ κ·Όμ± λμ μ λλ©μ΄μ μ λ§λλ λ°©λ²μ μ΄ν΄λ΄ λλ€.
λ·° νΈλμ§μ μ ꡬ쑰
μ νμ μ€νμΌλ§νκΈ° μ μ, μ νμ΄ νΈλ¦¬κ±°λ λ λ΄λΆμ μΌλ‘ μ΄λ€ μΌμ΄ μΌμ΄λλμ§ μ΄ν΄ν΄μΌ ν©λλ€. λ·° νΈλμ§μ μ μμνλ©΄(μ: document.startViewTransition() νΈμΆ), λΈλΌμ°μ λ μΌλ ¨μ λ¨κ³λ₯Ό μνν©λλ€:
- μ΄μ μν μΊ‘μ²: λΈλΌμ°μ λ νμ¬ νμ΄μ§ μνμ "μ€λ μ·"μ μ°μ΅λλ€.
- DOM μ λ°μ΄νΈ: μ½λκ° DOMμ λ³κ²½ν©λλ€(μ: μλ‘μ΄ λ·°λ‘ μ΄λ, μμ μΆκ° λλ μ κ±°).
- μλ‘μ΄ μν μΊ‘μ²: DOM μ λ°μ΄νΈκ° μλ£λλ©΄ λΈλΌμ°μ λ μλ‘μ΄ μνμ μ€λ μ·μ μ°μ΅λλ€.
- μμ¬ μμ νΈλ¦¬ ꡬμΆ: λΈλΌμ°μ λ νμ΄μ§μ μ€λ²λ μ΄μ μμ μμ¬ μμ νΈλ¦¬λ₯Ό ꡬμ±ν©λλ€. μ΄ νΈλ¦¬μλ μΊ‘μ²λ μ΄μ μνμ μλ‘μ΄ μνμ μ΄λ―Έμ§κ° ν¬ν¨λ©λλ€.
- μ λλ©μ΄μ : μ΄ μμ¬ μμμ CSS μ λλ©μ΄μ μ΄ μ μ©λμ΄ μ΄μ μνμμ μλ‘μ΄ μνλ‘ λΆλλ¬μ΄ μ νμ λ§λλλ€. κΈ°λ³Έκ°μ κ°λ¨ν κ΅μ°¨ νμ΄λμ λλ€.
- μ 리: μ λλ©μ΄μ μ΄ μλ£λλ©΄ μμ¬ μμ νΈλ¦¬κ° μ κ±°λκ³ μ¬μ©μλ μλ‘μ΄ λΌμ΄λΈ DOMκ³Ό μνΈ μμ©ν μ μμ΅λλ€.
컀μ€ν°λ§μ΄μ§μ ν΅μ¬μ μ΄ μμ μμ¬ μμ νΈλ¦¬μ λλ€. λμμΈ λꡬμ λ μ΄μ΄ μΈνΈμ²λΌ νμ΄μ§ μμ μΌμμ μΌλ‘ λ°°μΉλλ€κ³ μκ°νλ©΄ λ©λλ€. μ΄ λ μ΄μ΄λ€μ CSSλ‘ μλ²½νκ² μ μ΄ν μ μμ΅λλ€. μ¬λ¬λΆμ΄ λ€λ£¨κ² λ ꡬ쑰λ λ€μκ³Ό κ°μ΅λλ€:
- ::view-transition
- ::view-transition-group(*)
- ::view-transition-image-pair(*)
- ::view-transition-old(*)
- ::view-transition-new(*)
- ::view-transition-image-pair(*)
- ::view-transition-group(*)
κ° μμ¬ μμκ° λ¬΄μμ λνλ΄λμ§ μμΈν μ΄ν΄λ³΄κ² μ΅λλ€.
μμ¬ μμμ μν
::view-transition: μ 체 ꡬ쑰μ 루νΈμ λλ€. λ·°ν¬νΈλ₯Ό μ±μ°κ³ λ€λ₯Έ λͺ¨λ νμ΄μ§ μ½ν μΈ μμ μμΉνλ λ¨μΌ μμμ λλ€. λͺ¨λ μ ν κ·Έλ£Ήμ 컨ν μ΄λ μν μ νλ©°, μ§μ μκ°μ΄λ νμ΄λ° ν¨μμ κ°μ μ λ°μ μΈ μ ν μμ±μ μ€μ νκΈ°μ μ’μ μμΉμ λλ€.
::view-transition-group(*): κ° κ³ μ ν μ ν μμ(view-transition-name CSS μμ±μΌλ‘ μλ³)μ λν΄ κ·Έλ£Ήμ΄ μμ±λ©λλ€. μ΄ μμ¬ μμλ μ½ν μΈ μ μμΉμ ν¬κΈ°λ₯Ό μ λλ©μ΄μ νλ μν μ ν©λλ€. λ§μ½ μΉ΄λκ° νλ©΄μ νμͺ½μμ λ€λ₯Έ μͺ½μΌλ‘ μ΄λνλ€λ©΄, μ€μ λ‘ μμ§μ΄λ κ²μ ::view-transition-groupμ λλ€.
::view-transition-image-pair(*): κ·Έλ£Ή λ΄λΆμ μ€μ²©λ μ΄ μμλ μ΄μ λ·°μ μλ‘μ΄ λ·°μ 컨ν μ΄λ λ° ν΄λ¦¬ν λ§μ€ν¬ μν μ ν©λλ€. μ£Όμ μν μ μ λλ©μ΄μ λμ border-radiusλ transformκ³Ό κ°μ ν¨κ³Όλ₯Ό μ μ§νκ³ κΈ°λ³Έ κ΅μ°¨ νμ΄λ μ λλ©μ΄μ μ μ²λ¦¬νλ κ²μ λλ€.
::view-transition-old(*): μ΄κ²μ μ΄μ μν(DOM λ³κ²½ μ )μ μλ μμμ "μ€λ μ·" λλ λ λλ§λ λ·°λ₯Ό λνλ λλ€. κΈ°λ³Έμ μΌλ‘ opacity: 1μμ opacity: 0μΌλ‘ μ λλ©μ΄μ λ©λλ€.
::view-transition-new(*): μ΄κ²μ μλ‘μ΄ μν(DOM λ³κ²½ ν)μ μλ μμμ "μ€λ μ·" λλ λ λλ§λ λ·°λ₯Ό λνλ λλ€. κΈ°λ³Έμ μΌλ‘ opacity: 0μμ opacity: 1λ‘ μ λλ©μ΄μ λ©λλ€.
루νΈ: ::view-transition μμ¬ μμ μ€νμΌλ§
::view-transition μμ¬ μμλ μ 체 μ λλ©μ΄μ μ΄ κ·Έλ €μ§λ μΊλ²μ€μ λλ€. μ΅μμ 컨ν μ΄λλ‘μ μ νμ μ μμ μΌλ‘ μ μ©λμ΄μΌ ν μμ±μ μ μνκΈ°μ μ΄μμ μΈ μ₯μμ λλ€. κΈ°λ³Έμ μΌλ‘ λΈλΌμ°μ λ μ λλ©μ΄μ μΈνΈλ₯Ό μ 곡νμ§λ§, μ΄λ₯Ό μ½κ² μ¬μ μν μ μμ΅λλ€.
μλ₯Ό λ€μ΄, κΈ°λ³Έ μ νμ 250λ°λ¦¬μ΄ λμ μ§μλλ κ΅μ°¨ νμ΄λμ λλ€. μ¬μ΄νΈμ λͺ¨λ μ νμ λν΄ μ΄λ₯Ό λ³κ²½νκ³ μΆλ€λ©΄ λ£¨νΈ μμ¬ μμλ₯Ό νκ²ν ν μ μμ΅λλ€:
::view-transition {
animation-duration: 500ms;
animation-timing-function: ease-in-out;
}
μ΄ κ°λ¨ν κ·μΉμΌλ‘ μ΄μ λͺ¨λ κΈ°λ³Έ νμ΄μ§ νμ΄λκ° λ λ°° λ μ€λ κ±Έλ¦¬κ³ 'ease-in-out' 곑μ μ μ¬μ©νμ¬ μ½κ° λ€λ₯Έ λλμ μ€λλ€. μ¬κΈ°μ 볡μ‘ν μ λλ©μ΄μ μ μ μ©ν μλ μμ§λ§, μΌλ°μ μΌλ‘λ 보νΈμ μΈ νμ΄λ°κ³Ό μ΄μ§μ μ μνλ λ° μ¬μ©νλ κ²μ΄ κ°μ₯ μ’μΌλ©°, μΈλΆμ μΈ μ°μΆμ λ ꡬ체μ μΈ μμ¬ μμκ° μ²λ¦¬νλλ‘ ν©λλ€.
κ·Έλ£Ήν λ° μ΄λ¦ μ§μ : `view-transition-name`μ ν
μΆκ° μμ μμ΄λ λ·° νΈλμ§μ APIλ κΈ°λ³Έμ μΌλ‘ μ 체 νμ΄μ§μ λν κ΅μ°¨ νμ΄λλ₯Ό μ 곡ν©λλ€. μ΄λ 루νΈμ λν λ¨μΌ μμ¬ μμ κ·Έλ£Ήμ μν΄ μ²λ¦¬λ©λλ€. μ΄ APIμ μ§μ ν νμ νΉμ κ°λ³ μμλ₯Ό μν κ°μ μ ννκ³ μΆμ λ λ°νλ©λλ€. μλ₯Ό λ€μ΄, λͺ©λ‘ νμ΄μ§μ μ ν μΈλ€μΌμ΄ μμΈ νμ΄μ§μ κΈ°λ³Έ μ ν μ΄λ―Έμ§ μμΉλ‘ λ§€λλ½κ² 컀μ§λ©΄μ μ΄λνκ² λ§λλ κ²μ λλ€.
μλ‘ λ€λ₯Έ DOM μνμ μλ λ μμκ° κ°λ μ μΌλ‘ λμΌνλ€λ κ²μ λΈλΌμ°μ μ μλ¦¬λ €λ©΄ view-transition-name CSS μμ±μ μ¬μ©ν©λλ€. μ΄ μμ±μ μμ μμμ λ μμ λͺ¨λμ μ μ©λμ΄μΌ ν©λλ€.
/* λͺ©λ‘ νμ΄μ§ CSSμμ */
.product-thumbnail {
view-transition-name: product-image;
}
/* μμΈ νμ΄μ§ CSSμμ */
.main-product-image {
view-transition-name: product-image;
}
λ μμμ λμΌν κ³ μ μ΄λ¦('product-image'μ κ²½μ°)μ λΆμ¬ν¨μΌλ‘μ¨, λΈλΌμ°μ μ "μ΄μ νμ΄μ§λ₯Ό νμ΄λ μμνκ³ μ νμ΄μ§λ₯Ό νμ΄λ μΈνλ λμ , μ΄ νΉμ μμμ λν νΉλ³ν μ νμ λ§λ€μ΄λΌ"κ³ μ§μν©λλ€. λΈλΌμ°μ λ μ΄μ λ£¨νΈ νμ΄λμλ λ³λλ‘ μ λλ©μ΄μ μ μ²λ¦¬νκΈ° μν΄ μ μ© ::view-transition-group(product-image)μ μμ±ν©λλ€. μ΄κ²μ΄ λ°λ‘ μΈκΈ° μλ "λͺ¨ν" λλ "곡μ μμ" μ ν ν¨κ³Όλ₯Ό κ°λ₯νκ² νλ κΈ°λ³Έ κ°λ μ λλ€.
μ€μ μ°Έκ³ : μ ν μ€ νΉμ μκ°μ view-transition-nameμ κ³ μ ν΄μΌ ν©λλ€. λμμ λμΌν μ΄λ¦μ κ°μ§ λ κ°μ 보μ΄λ μμκ° μμ μ μμ΅λλ€.
μ¬μΈ΅ μ€νμΌλ§: ν΅μ¬ μμ¬ μμ
μμμ μ΄λ¦μ μ§μ νμΌλ―λ‘, μ΄μ λΈλΌμ°μ κ° μμ±νλ νΉμ μμ¬ μμλ₯Ό μ€νμΌλ§νλ λ¨κ³λ‘ λμ΄κ° μ μμ΅λλ€. μ¬κΈ°μ μ§μ μΌλ‘ λ μ°½μ μ΄κ³ ννλ ₯ μλ μ λλ©μ΄μ μ λ§λ€ μ μμ΅λλ€.
`::view-transition-group(name)`: μ΄λ λ΄λΉ
κ·Έλ£Ήμ μ μΌν μ± μμ μ΄μ μμμ ν¬κΈ°μ μμΉμμ μ μμμ ν¬κΈ°μ μμΉλ‘ μ ννλ κ²μ λλ€. μ€μ μ½ν μΈ μ λͺ¨μμ ν¬ν¨νμ§ μμΌλ©°, μ€μ§ κ·Έ κ²½κ³ μμ(bounding box)λ§ λ€λ£Ήλλ€. μμ§μ΄λ νλ μμ΄λΌκ³ μκ°νλ©΄ λ©λλ€.
κΈ°λ³Έμ μΌλ‘ λΈλΌμ°μ λ transformκ³Ό width/height μμ±μ μ λλ©μ΄μ ν©λλ€. μ΄λ₯Ό μ¬μ μνμ¬ λ€λ₯Έ ν¨κ³Όλ₯Ό λ§λ€ μ μμ΅λλ€. μλ₯Ό λ€μ΄, 곑μ κ²½λ‘λ₯Ό λ°λΌ μ λλ©μ΄μ νμ¬ μμ§μμ νΈλ₯Ό μΆκ°νκ±°λ, μ΄λ μ€μ ν¬κΈ°λ₯Ό ν€μ λ€ μ€μλ€ ν μ μμ΅λλ€.
::view-transition-group(product-image) {
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
μ΄ μμμλ μ ν μ΄λ―Έμ§μ μμ§μμλ§ νΉμ μ΄μ§ ν¨μλ₯Ό μ μ©νμ¬, λλ¨Έμ§ νμ΄μ§μ κΈ°λ³Έ νμ΄λμ μν₯μ μ£Όμ§ μμΌλ©΄μ λ μλμ μ΄κ³ 물리μ μΈ λλμ μ€λλ€.
`::view-transition-image-pair(name)`: ν΄λ¦¬ν λ° νμ΄λ λ΄λΉ
μμ§μ΄λ κ·Έλ£Ή λ΄μ μ€μ²©λ image-pairλ μ΄μ λ·°μ μλ‘μ΄ λ·°λ₯Ό λ΄κ³ μμ΅λλ€. ν΄λ¦¬ν λ§μ€ν¬ μν μ νλ―λ‘ μμμ border-radiusκ° μλ κ²½μ°, image-pairλ ν¬κΈ°μ μμΉ μ λλ©μ΄μ μ 체μ κ±Έμ³ μ½ν μΈ κ° ν΄λΉ λ°κ²½μΌλ‘ ν΄λ¦¬νλλλ‘ λ³΄μ₯ν©λλ€. λ€λ₯Έ μ£Όμ μν μ μ΄μ μ½ν μΈ μ μ μ½ν μΈ κ°μ κΈ°λ³Έ κ΅μ°¨ νμ΄λλ₯Ό μ‘°μ¨νλ κ²μ λλ€.
μκ°μ μΌκ΄μ±μ 보μ₯νκ±°λ λ κ³ κΈ ν¨κ³Όλ₯Ό λ§λ€κΈ° μν΄ μ΄ μμλ₯Ό μ€νμΌλ§ν μ μμ΅λλ€. κ³ λ €ν΄μΌ ν ν΅μ¬ μμ±μ isolation: isolateμ λλ€. μμ μμ(μ΄μ λ° μλ‘μ΄ λ·°)μ κ³ κΈ mix-blend-mode ν¨κ³Όλ₯Ό μ¬μ©ν κ³νμ΄λΌλ©΄ μ΄λ λ§€μ° μ€μν©λλ€. μλ‘μ΄ μμ λ§₯λ½(stacking context)μ μμ±νμ¬ λΈλ λ©μ΄ μ ν κ·Έλ£Ή μΈλΆμ μμμ μν₯μ λ―ΈμΉλ κ²μ λ°©μ§νκΈ° λλ¬Έμ λλ€.
::view-transition-image-pair(product-image) {
isolation: isolate;
}
`::view-transition-old(name)` λ° `::view-transition-new(name)`: μΌμ μ£ΌμΈκ³΅
μ΄λ€μ DOM λ³κ²½ μ νμ μμμ μκ°μ λͺ¨μμ λνλ΄λ μμ¬ μμμ λλ€. λλΆλΆμ λ§μΆ€ μ λλ©μ΄μ μμ μ΄ μ¬κΈ°μ μ΄λ£¨μ΄μ§λλ€. κΈ°λ³Έμ μΌλ‘ λΈλΌμ°μ λ opacityμ mix-blend-modeλ₯Ό μ¬μ©νμ¬ κ°λ¨ν κ΅μ°¨ νμ΄λ μ λλ©μ΄μ μ μ€νν©λλ€. λ§μΆ€ μ λλ©μ΄μ μ λ§λ€λ €λ©΄ λ¨Όμ κΈ°λ³Έ μ λλ©μ΄μ μ κΊΌμΌ ν©λλ€.
::view-transition-old(name),
::view-transition-new(name) {
animation: none;
}
κΈ°λ³Έ μ λλ©μ΄μ μ΄ λΉνμ±νλλ©΄ μμ λ‘κ² μμ λ§μ μ λλ©μ΄μ μ μ μ©ν μ μμ΅λλ€. λͺ κ°μ§ μΌλ°μ μΈ ν¨ν΄μ μ΄ν΄λ³΄κ² μ΅λλ€.
λ§μΆ€ μ λλ©μ΄μ : μ¬λΌμ΄λ
κ΅μ°¨ νμ΄λ λμ 컨ν μ΄λμ μ½ν μΈ κ° μ¬λΌμ΄λ μΈνλλ‘ λ§λ€μ΄ λ΄ μλ€. μλ₯Ό λ€μ΄, κΈ°μ¬ κ°μ μ΄λν λ μ κΈ°μ¬μ ν μ€νΈλ μ€λ₯Έμͺ½μμ μ¬λΌμ΄λ μΈνκ³ μ΄μ ν μ€νΈλ μΌμͺ½μΌλ‘ μ¬λΌμ΄λ μμλλλ‘ νκ³ μΆμ΅λλ€.
λ¨Όμ , ν€νλ μμ μ μν©λλ€:
@keyframes slide-from-right {
from { transform: translateX(100%); }
to { transform: translateX(0); }
}
@keyframes slide-to-left {
from { transform: translateX(0); }
to { transform: translateX(-100%); }
}
μ΄μ μ΄ μ λλ©μ΄μ λ€μ 'article-content'λΌλ μ΄λ¦μ μμμ λν μ΄μ λ° μλ‘μ΄ μμ¬ μμμ μ μ©ν©λλ€.
::view-transition-old(article-content) {
animation: 300ms ease-out forwards slide-to-left;
}
::view-transition-new(article-content) {
animation: 300ms ease-out forwards slide-from-right;
}
λ§μΆ€ μ λλ©μ΄μ : 3D ν립
λ κ·Ήμ μΈ ν¨κ³Όλ₯Ό μν΄ 3D μΉ΄λ ν립μ λ§λ€ μ μμ΅λλ€. μ΄λ₯Ό μν΄μλ transform μμ±μ rotateYλ‘ μ λλ©μ΄μ νκ³ backface-visibilityλ κ΄λ¦¬ν΄μΌ ν©λλ€.
/* κ·Έλ£Ήμλ 3D 컨ν μ€νΈκ° νμν©λλ€ */
::view-transition-group(card-flipper) {
transform-style: preserve-3d;
}
/* image-pairλ 3D 컨ν μ€νΈλ₯Ό μ μ§ν΄μΌ ν©λλ€ */
::view-transition-image-pair(card-flipper) {
transform-style: preserve-3d;
}
/* μ΄μ λ·°λ 0λμμ -180λλ‘ λ€μ§νλλ€ */
::view-transition-old(card-flipper) {
animation: 600ms ease-in forwards flip-out;
backface-visibility: hidden;
}
/* μλ‘μ΄ λ·°λ 180λμμ 0λλ‘ λ€μ§νλλ€ */
::view-transition-new(card-flipper) {
animation: 600ms ease-out forwards flip-in;
backface-visibility: hidden;
}
@keyframes flip-out {
from { transform: rotateY(0deg); }
to { transform: rotateY(-180deg); }
}
@keyframes flip-in {
from { transform: rotateY(180deg); }
to { transform: rotateY(0deg); }
}
μ€μ© μμ λ° κ³ κΈ κΈ°μ
μ΄λ‘ μ μ μ©νμ§λ§, μ€μ μ μ©μ ν΅ν΄ μ§μ μΌλ‘ λ°°μΈ μ μμ΅λλ€. λͺ κ°μ§ μΌλ°μ μΈ μλ리μ€μ μ΄λ₯Ό λ·° νΈλμ§μ μμ¬ μμλ‘ ν΄κ²°νλ λ°©λ²μ μ΄ν΄λ³΄κ² μ΅λλ€.
μμ : "λͺ¨ν" μΉ΄λ μΈλ€μΌ
μ΄κ²μ μ νμ μΈ κ³΅μ μμ μ νμ λλ€. μ¬μ©μ νλ‘ν κ°€λ¬λ¦¬λ₯Ό μμν΄ λ³΄μΈμ. κ° νλ‘νμ μλ°νκ° μλ μΉ΄λμ λλ€. μΉ΄λλ₯Ό ν΄λ¦νλ©΄ ν΄λΉ μλ°νκ° μλ¨μ λμ λκ² νμλλ μμΈ νμ΄μ§λ‘ μ΄λν©λλ€.
1λ¨κ³: μ΄λ¦ ν λΉ
κ°€λ¬λ¦¬ νμ΄μ§μμ μλ°ν μ΄λ―Έμ§μ μ΄λ¦μ μ§μ ν©λλ€. μ΄λ¦μ κ° μΉ΄λλ§λ€ κ³ μ ν΄μΌ νλ©°, μλ₯Ό λ€μ΄ μ¬μ©μ IDλ₯Ό κΈ°λ°μΌλ‘ ν μ μμ΅λλ€.
/* gallery-item.cssμμ */
.card-avatar { view-transition-name: avatar-user-123; }
νλ‘ν μμΈ νμ΄μ§μμ ν° ν€λ μλ°νλ μ νν λμΌν μ΄λ¦μ κ°μ΅λλ€.
/* profile-page.cssμμ */
.profile-header-avatar { view-transition-name: avatar-user-123; }
2λ¨κ³: μ λλ©μ΄μ λ§μΆ€ μ€μ
κΈ°λ³Έμ μΌλ‘ λΈλΌμ°μ λ μλ°νλ₯Ό μ΄λνκ³ ν¬κΈ°λ₯Ό μ‘°μ νμ§λ§ μ½ν μΈ λ κ΅μ°¨ νμ΄λν©λλ€. μ΄λ―Έμ§κ° λμΌνλ€λ©΄ μ΄ νμ΄λλ λΆνμνλ©° μ½κ°μ κΉλ°μμ μ λ°ν μ μμ΅λλ€. μ΄λ₯Ό λΉνμ±νν μ μμ΅λλ€.
/* μ¬κΈ°μ λ³ν(*)λ μ΄λ¦μ΄ μ§μ λ λͺ¨λ κ·Έλ£Ήμ λν μμΌλμΉ΄λμ λλ€ */
::view-transition-image-pair(*) {
/* κΈ°λ³Έ νμ΄λ λΉνμ±ν */
animation-duration: 0s;
}
μ κΉ, νμ΄λλ₯Ό λΉνμ±ννλ©΄ μ½ν μΈ λ μ΄λ»κ² μ νλ κΉμ? μ΄μ λ·°μ μλ‘μ΄ λ·°κ° λμΌν 곡μ μμμ κ²½μ°, λΈλΌμ°μ λ μ 체 μ νμ νλμ λ·°λ§ μ¬μ©ν λ§νΌ λλν©λλ€. `image-pair`λ λ³Έμ§μ μΌλ‘ νλμ μ΄λ―Έμ§λ§ λ΄κ³ μμΌλ―λ‘ νμ΄λλ₯Ό λΉνμ±ννλ©΄ μ΄ μ΅μ νκ° λλ¬λ©λλ€. μ½ν μΈ κ° μ€μ λ‘ λ³κ²½λλ μμμ κ²½μ°, κΈ°λ³Έ νμ΄λ λμ λ§μΆ€ μ λλ©μ΄μ μ΄ νμν©λλ€.
κ°λ‘μΈλ‘ λΉμ¨ λ³κ²½ μ²λ¦¬
μ ννλ μμμ κ°λ‘μΈλ‘ λΉμ¨μ΄ λ³κ²½λ λ νν λ°μνλ λ¬Έμ κ° μμ΅λλ€. μλ₯Ό λ€μ΄, λͺ©λ‘ νμ΄μ§μ 16:9 κ°λ‘ μΈλ€μΌμ΄ μμΈ νμ΄μ§μ 1:1 μ μ¬κ°ν μλ°νλ‘ μ νλ μ μμ΅λλ€. λΈλΌμ°μ μ κΈ°λ³Έ λμμ λλΉμ λμ΄λ₯Ό λ 립μ μΌλ‘ μ λλ©μ΄μ νλ―λ‘ μ ν μ€μ μ΄λ―Έμ§κ° μ°κ·Έλ¬μ§κ±°λ λμ΄λ 보μ λλ€.
ν΄κ²°μ± μ μ°μν©λλ€. ::view-transition-groupμ΄ ν¬κΈ°μ μμΉ λ³κ²½μ μ²λ¦¬νλλ‘ νκ³ , κ·Έ μμ μ΄μ λ° μλ‘μ΄ μ΄λ―Έμ§ μ€νμΌλ§μ μ¬μ μν©λλ€.
λͺ©νλ μ΄μ λ° μλ‘μ΄ "μ€λ μ·"μ΄ μ곑 μμ΄ μ»¨ν μ΄λλ₯Ό μ±μ°λλ‘ νλ κ²μ λλ€. λλΉμ λμ΄λ₯Ό 100%λ‘ μ€μ νκ³ λΈλΌμ°μ μ κΈ°λ³Έ object-fit μμ±(μλ³Έ μμμμ μμλ¨)μ΄ ν¬κΈ° μ‘°μ μ μ¬λ°λ₯΄κ² μ²λ¦¬νλλ‘ νμ¬ μ΄λ₯Ό μνν μ μμ΅λλ€.
::view-transition-old(hero-image),
::view-transition-new(hero-image) {
/* 컨ν μ΄λλ₯Ό μ±μ μ곑 λ°©μ§ */
width: 100%;
height: 100%;
/* ν¨κ³Όλ₯Ό λͺ ννκ² λ³΄κΈ° μν΄ κΈ°λ³Έ κ΅μ°¨ νμ΄λ μ¬μ μ */
animation: none;
}
μ΄ CSSλ₯Ό μ¬μ©νλ©΄ `image-pair`λ κ°λ‘μΈλ‘ λΉμ¨μ λΆλλ½κ² μ λλ©μ΄μ νκ³ , λ΄λΆμ μ΄λ―Έμ§λ μΌλ° 컨ν μ΄λμμμ κ°μ΄ `object-fit` κ°μ λ°λΌ μ¬λ°λ₯΄κ² μ리거λ λ ν°λ°μ€ μ²λ¦¬λ©λλ€. κ·Έλ° λ€μ μ΄ μμ λ κΈ°νν μμ κ΅μ°¨ νμ΄λμ κ°μ μμ λ§μ λ§μΆ€ μ λλ©μ΄μ μ μΆκ°ν μ μμ΅λλ€.
λλ²κΉ λ° λΈλΌμ°μ μ§μ
μμ£Ό μ§§μ μκ° λμλ§ μ‘΄μ¬νλ μμλ₯Ό μ€νμΌλ§νλ κ²μ κΉλ€λ‘μΈ μ μμ΅λλ€. λ€νν μ΅μ λΈλΌμ°μ λ μ΄λ₯Ό μν νλ₯ν κ°λ°μ λꡬλ₯Ό μ 곡ν©λλ€. Chrome λλ Edge κ°λ°μ λꡬμ "Animations" ν¨λμμ λ·° νΈλμ§μ μ νΈλ¦¬κ±°ν λ μΌμ μ€μ§ν μ μμ΅λλ€. μ λλ©μ΄μ μ΄ μΌμ μ€μ§λ μνμμ "Elements" ν¨λμ μ¬μ©νμ¬ λ€λ₯Έ DOM λΆλΆμ²λΌ μ 체 `::view-transition` μμ¬ μμ νΈλ¦¬λ₯Ό κ²μ¬ν μ μμ΅λλ€. μ μ©λ μ€νμΌμ λ³΄κ³ μ€μκ°μΌλ‘ μμ νμ¬ μ λλ©μ΄μ μ μμ±ν μ μμ΅λλ€.
2023λ λ§ κΈ°μ€μΌλ‘ λ·° νΈλμ§μ APIλ Chromium κΈ°λ° λΈλΌμ°μ (Chrome, Edge, Opera)μμ μ§μλ©λλ€. Firefoxμ Safariμ λν ꡬνμ΄ μ§ν μ€μ λλ€. μ΄λ μ μ§μ ν₯μμ μλ²½ν νλ³΄κ° λ©λλ€. μ§μλλ λΈλΌμ°μ μ μ¬μ©μλ μ¦κ²κ³ ν₯μλ κ²½νμ μ»κ³ , λ€λ₯Έ λΈλΌμ°μ μ μ¬μ©μλ νμ€μ μΈ μ¦κ°μ μΈ νμμ κ²½νν©λλ€. CSSμμ μ§μ μ¬λΆλ₯Ό νμΈν μ μμ΅λλ€:
@supports (view-transition: none) {
/* λͺ¨λ λ·° νΈλμ§μ μ€νμΌμ μ¬κΈ°μ μμ±ν©λλ€ */
::view-transition-old(my-element) { ... }
}
μ μΈκ³ μ¬μ©μλ₯Ό μν λͺ¨λ² μ¬λ‘
μ λλ©μ΄μ μ ꡬνν λ μ μΈκ³μ λ€μν μ¬μ©μμ μ₯μΉλ₯Ό κ³ λ €νλ κ²μ΄ μ€μν©λλ€.
μ±λ₯: μ λλ©μ΄μ μ λΉ λ₯΄κ³ μ λμ μ΄μ΄μΌ ν©λλ€. λΈλΌμ°μ κ° μ²λ¦¬νκΈ°μ λΉμ©μ΄ μ λ ΄ν CSS μμ±, μ£Όλ‘ transformκ³Ό opacityλ₯Ό μ λλ©μ΄μ νλ λ° μ§μ€νμΈμ. width, height, marginκ³Ό κ°μ μμ±μ μ λλ©μ΄μ νλ©΄ λͺ¨λ νλ μμμ λ μ΄μμ μ¬κ³μ°μ μ λ°νμ¬ νΉν μ μ¬μ μ₯μΉμμ λ²λ² κ±°λ¦Όκ³Ό λμ κ²½νμ μ΄λν μ μμ΅λλ€.
μ κ·Όμ±: μΌλΆ μ¬μ©μλ μ λλ©μ΄μ μΌλ‘ μΈν΄ λ©λ―Έλ λΆνΈν¨μ κ²½νν©λλ€. λͺ¨λ μ£Όμ μ΄μ 체μ λ μμ§μμ μ€μ΄λ μ¬μ©μ μ€μ μ μ 곡ν©λλ€. μ°λ¦¬λ μ΄λ₯Ό μ‘΄μ€ν΄μΌ ν©λλ€. prefers-reduced-motion λ―Έλμ΄ μΏΌλ¦¬λ₯Ό μ¬μ©νλ©΄ μ΄λ¬ν μ¬μ©μλ₯Ό μν΄ μ λλ©μ΄μ μ λΉνμ±ννκ±°λ λ¨μνν μ μμ΅λλ€.
@media (prefers-reduced-motion: reduce) {
::view-transition-group(*),
::view-transition-old(*),
::view-transition-new(*) {
/* λͺ¨λ λ§μΆ€ μ λλ©μ΄μ μ 건λλ°κ³ λΉ λ₯΄κ³ κ°λ¨ν νμ΄λλ₯Ό μ¬μ© */
animation: none !important;
}
}
μ¬μ©μ κ²½ν(UX): μ’μ μ νμ λͺ©μ μ΄ μμ΅λλ€. μ¬μ©μμ μ£Όμλ₯Ό μ λνκ³ UIμμ μΌμ΄λλ λ³νμ λν λ§₯λ½μ μ 곡ν΄μΌ ν©λλ€. λ무 λλ¦° μ λλ©μ΄μ μ μ ν리μΌμ΄μ μ λλ¦¬κ² λλΌκ² ν μ μκ³ , λ무 νλ €ν μ λλ©μ΄μ μ μ£Όμλ₯Ό μ°λ§νκ² ν μ μμ΅λλ€. μ ν μ§μ μκ°μ 200msμμ 500ms μ¬μ΄λ₯Ό λͺ©νλ‘ νμΈμ. λͺ©νλ μ λλ©μ΄μ μ΄ λμ 보μ΄λ κ²λ³΄λ€ λκ»΄μ§λλ‘ νλ κ²μ λλ€.
κ²°λ‘ : λ―Έλλ μ λμ μ΄λ€
CSS λ·° νΈλμ§μ API, νΉν κ·Έ κ°λ ₯ν μμ¬ μμ νΈλ¦¬λ μΉ μ¬μ©μ μΈν°νμ΄μ€μ κΈ°λ λΉμ μΈ λμ½μ μλ―Έν©λλ€. μ΄λ κ°λ°μμκ² νλ λ€μ΄ν°λΈ μ ν리μΌμ΄μ μ μ μ λ¬Όμ΄μλ μ λμ μ΄κ³ μν μ μ₯ μ νμ λ§λ€ μ μλ λ€μ΄ν°λΈνκ³ μ±λ₯μ΄ λ°μ΄λλ©° κ³ λλ‘ μ¬μ©μ μ μ κ°λ₯ν λꡬ μΈνΈλ₯Ό μ 곡ν©λλ€. ::view-transition, ::view-transition-group, κ·Έλ¦¬κ³ old/new μ΄λ―Έμ§ μμ μν μ μ΄ν΄ν¨μΌλ‘μ¨ λ¨μν νμ΄λλ₯Ό λμ΄ μ¬μ©μ±μ ν₯μμν€κ³ μ¬μ©μλ₯Ό μ¦κ²κ² νλ 볡μ‘νκ³ μλ―Έ μλ μ λλ©μ΄μ μ μ°μΆν μ μμ΅λλ€.
λΈλΌμ°μ μ§μμ΄ νλλ¨μ λ°λΌ μ΄ APIλ νλ νλ‘ νΈμλ κ°λ°μμ ν΄ν·μμ νμμ μΈ λΆλΆμ΄ λ κ²μ λλ€. κ·Έ κΈ°λ₯μ μμ©νκ³ μ±λ₯ λ° μ κ·Όμ±μ λν λͺ¨λ² μ¬λ‘λ₯Ό μ€μν¨μΌλ‘μ¨, μ°λ¦¬λ κΈ°λ₯μ μΌ λΏλ§ μλλΌ μ μΈκ³ λͺ¨λ μ¬λμκ² λ μλ¦λ΅κ³ μ§κ΄μ μΈ μΉμ ꡬμΆν μ μμ΅λλ€.