htmxλ CSS μ νμ μ¬μ©νμ¬ CSSμ HTMLλ§μΌλ‘ μΉ νμ΄μ§μ λΆλλ¬μ΄ μ λλ©μ΄μ κ³Ό μ ν ν¨κ³Όλ₯Ό μΆκ°ν μ μλλ‘ μ€κ³λμμ΅λλ€. μλμλ λ€μν μ λλ©μ΄μ κΈ°λ²μ λͺ κ°μ§ μμκ° λμ μμ΅λλ€.
λν htmxλ μλ‘μ΄ View Transitions APIλ₯Ό μ¬μ©νμ¬ μ λλ©μ΄μ μ μμ±ν μ μλλ‘ ν©λλ€.
htmxμμ κ°μ₯ κ°λ¨ν μ λλ©μ΄μ
κΈ°λ²μ μ½ν
μΈ κ΅μ²΄ μ€μ μμμ id
λ₯Ό μ μ§νλ κ²μ
λλ€. μμμ id
κ° μ μ§λλ©΄,
htmxλ CSS μ νμ ν΅ν΄ ν΄λΉ μμμ μ΄μ λ²μ κ³Ό μ λ²μ μ¬μ΄μ μ ν ν¨κ³Όλ₯Ό μμ±ν μ μλλ‘ κ΅μ²΄λ₯Ό ꡬ쑰νν©λλ€.
λ€μμ divλ₯Ό μλ‘ λ€μ΄λ³΄κ² μ΅λλ€:
<style>
.smooth {
transition: all 1s ease-in;
}
</style>
<div id="color-demo" class="smooth" style="color:red"
hx-get="/colors" hx-swap="outerHTML" hx-trigger="every 1s">
Color Swap Demo
</div>
μ΄ divλ 맀μ΄λ§λ€ ν΄λ§(polling)νλ©° color
μ€νμΌμ μλ‘μ΄ κ°(μ: blue
)μΌλ‘ λ³κ²½νλ μλ‘μ΄ μ½ν
μΈ λ‘ κ΅μ²΄λ©λλ€:
<div id="color-demo" class="smooth" style="color:blue"
hx-get="/colors" hx-swap="outerHTML" hx-trigger="every 1s">
Color Swap Demo
</div>
μ΄ divλ color-demo
λΌλ μμ μ μΈ idλ₯Ό κ°μ§κ³ μκΈ° λλ¬Έμ, htmxλ κ΅μ²΄λ₯Ό ꡬ쑰ννμ¬ .smooth
ν΄λμ€μ μ μλ CSS μ νμ΄ red
μμ blue
λ‘ μ€νμΌ μ
λ°μ΄νΈμ μ μ©λκ³ ,
λ μμ μ¬μ΄λ₯Ό λΆλλ½κ² μ νν μ μλλ‘ ν©λλ€.
μ§νλ₯ νμμ€ λ°λͺ¨μμλ μ§νλ₯ νμμ€ μμμ length
μμ±μ μ
λ°μ΄νΈνμ¬ λΆλλ¬μ΄ μ λλ©μ΄μ
μ ꡬννλ μ΄ κΈ°λ³Έ CSS μ λλ©μ΄μ
κΈ°λ²λ μ¬μ©νκ³ μμ΅λλ€.
μμ²μ΄ μ’
λ£λ λ μ κ±°λ μμλ₯Ό νμ΄λ μμνλ €λ©΄ μΌλΆ CSSλ₯Ό μ¬μ©νμ¬
htmx-swapping
ν΄λμ€λ₯Ό νμ©νκ³ μ λλ©μ΄μ
μ΄ μλ£λ λκΉμ§ κ΅μ²΄ λ¨κ³λ₯Ό μΆ©λΆν κΈΈκ² μ°μ₯ν μ μμ΅λλ€.
μ΄λ κ² νλ©΄ λ©λλ€:
<style>
.fade-me-out.htmx-swapping {
opacity: 0;
transition: opacity 1s ease-out;
}
</style>
<button class="fade-me-out"
hx-delete="/fade_out_demo"
hx-swap="outerHTML swap:1s">
Fade Me Out
</button>
λ§μ§λ§ μμ λ₯Ό κΈ°λ°μΌλ‘ μ€μ λ¨κ³μμ htmx-added
ν΄λμ€λ₯Ό μ¬μ©νμ¬ μ μ½ν
μΈ λ₯Ό νμ΄λ μΈν μ μμ΅λλ€.
μ μ½ν
μΈ κ° μλ νκΉμ λν CSS Transitionμ htmx-settling
ν΄λμ€λ₯Ό μ¬μ©νμ¬ μμ±ν μλ μμ΅λλ€.
<style>
#fade-me-in.htmx-added {
opacity: 0;
}
#fade-me-in {
opacity: 1;
transition: opacity 1s ease-out;
}
</style>
<button id="fade-me-in"
class="btn primary"
hx-post="/fade_in_demo"
hx-swap="outerHTML settle:1s">
Fade Me In
</button>
μμ²μ νΈλ¦¬κ±°νλ μμμ μ μ©λλ htmx-request
ν΄λμ€λ₯Ό νμ©ν μλ μμ΅λλ€.
μλλ μ μΆ μ μμ²μ΄ μ²λ¦¬ μ€μμ λνλ΄κΈ° μν΄ λͺ¨μμ΄ λ³κ²½λλ Formμ
λλ€:
<style>
form.htmx-request {
opacity: .5;
transition: opacity 300ms linear;
}
</style>
<form hx-post="/name" hx-swap="outerHTML">
<label>Name:</label><input name="name"><br/>
<button class="btn primary">Submit</button>
</form>
class-tools
Extensionclass-tools
νμ₯μ μ¬μ©νλ©΄ ν₯λ―Έλ‘μ΄ μ λλ©μ΄μ
μ λ§μ΄ λ§λ€ μ μμ΅λλ€.
λ€μμ divμ λΆν¬λͺ
λλ₯Ό ν κΈνλ μμ μ
λλ€. ν κΈ μκ°μ μ ν μκ°λ³΄λ€ μ½κ° κΈΈκ² μ€μ ν κ²μ μ£Όλͺ©νμΈμ.
μ΄λ κ² νλ©΄ ν΄λμ€ λ³κ²½μΌλ‘ μΈν΄ μ νμ΄ μ€λ¨λ λ λ°μν μ μλ κΉλ°μμ λ°©μ§ν μ μμ΅λλ€.
<style>
.demo.faded {
opacity:.3;
}
.demo {
opacity:1;
transition: opacity ease-in 900ms;
}
</style>
<div class="demo" classes="toggle faded:1s">Toggle Demo</div>
htmxλ hx-swap
μμ±μ transition
μ΅μ
μ ν΅ν΄ μλ‘μ΄
View Transitions APIμ μ κ·Όν μ μλλ‘ μ§μν©λλ€.
μλλ λ·° μ νμ μ¬μ©νλ κ΅μ²΄(swap)μ μμμ
λλ€. μ΄ μ νμ CSSμμ view-transition-name
μμ±μ ν΅ν΄ μΈλΆ divμ μ°κ²°λλ©°, ν΄λΉ μ νμ
::view-transition-old
μ ::view-transition-new
λ₯Ό μ¬μ©νμ¬ μ μλλ©°, @keyframes
λ₯Ό ν΅ν΄ μ λλ©μ΄μ
μ μ μν©λλ€.
(View Transition APIμ λν μμΈν λ΄μ©μ Chrome Developer Pageμμ νμΈν μ μμ΅λλ€.)
μ΄ μ νμ μ΄μ μ½ν μΈ λ μΌμͺ½μΌλ‘ μ¬λΌμ΄λ μμλκ³ , μλ‘μ΄ μ½ν μΈ λ μ€λ₯Έμͺ½μμ μ¬λΌμ΄λ μΈλμ΄μΌ ν©λλ€.
μμ± μμ μμ μ΄ μκ°μ μ νμ Chrome 111+μμλ§ λ°μνμ§λ§, κ°κΉμ΄ λ―Έλμ λ λ§μ λΈλΌμ°μ μμ μ΄ κΈ°λ₯μ ꡬνν κ²μΌλ‘ μμλ©λλ€.
<style>
@keyframes fade-in {
from { opacity: 0; }
}
@keyframes fade-out {
to { opacity: 0; }
}
@keyframes slide-from-right {
from { transform: translateX(90px); }
}
@keyframes slide-to-left {
to { transform: translateX(-90px); }
}
.slide-it {
view-transition-name: slide-it;
}
::view-transition-old(slide-it) {
animation: 180ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}
::view-transition-new(slide-it) {
animation: 420ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}
</style>
<div class="slide-it">
<h1>Initial Content</h1>
<button class="btn primary" hx-get="/new-content" hx-swap="innerHTML transition:true" hx-target="closest div">
Swap It!
</button>
</div>
μμ κΈ°λ²μ μ¬μ©νλ©΄ htmxλ₯Ό μ¬μ©νλ©΄μ μΌλ° HTMLλ‘ ν₯λ―Έλ‘κ³ μ¦κ±°μ΄ ν¨κ³Όλ₯Ό κ½€ λ§μ΄ λ§λ€ μ μμ΅λλ€.