Hydration

하이드레이션

Client code attaches to server-rendered HTML so controls such as buttons become interactive.

···
html
<section class="stage"><div class="heading">HYDRATION <span class="hint">HTML → events</span></div><div class="hydration"><div class="page"><div class="skeleton"></div><div class="skeleton small"></div><button type="button">CLICK <span id="clicks">0</span></button></div><div class="connector"><span>HTML visible</span><span>JS attached</span></div></div><div class="caption">Visible first; interactive after attachment</div></section>
css
.stage{width:min(94vw,780px);height:min(88vh,322px);padding:clamp(12px,3vmin,20px);border:1px solid var(--line);border-radius:16px;background:var(--surface);box-shadow:0 12px 36px #0001;display:flex;flex-direction:column;gap:clamp(7px,2vmin,14px);font:500 clamp(12px,3.5vmin,17px)/1.3 var(--font-sans,system-ui,sans-serif);overflow:hidden}.heading{display:flex;justify-content:space-between;align-items:center;gap:8px;font-weight:750;color:var(--accent)}.hint{color:var(--muted);font-size:clamp(12px,3.2vmin,14px);font-weight:500}.caption{margin-top:auto;color:var(--muted);font-size:clamp(12px,3.2vmin,14px)}.row{display:flex;gap:clamp(5px,1.5vmin,12px);align-items:center}.tile{padding:clamp(6px,1.8vmin,13px);border:1px solid var(--line);border-radius:9px;background:var(--bg);text-align:center;min-width:0}.arrow{color:var(--accent);font-weight:800}.stage [data-on]{transition:background .3s,border-color .3s,opacity .3s,transform .3s}.stage .on{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 14%,var(--surface));color:var(--accent)}.hydration{flex:1;display:flex;align-items:center;justify-content:center;gap:clamp(8px,3vmin,28px)}.page{width:48%;max-width:260px;min-height:100px;border:1px solid var(--line);border-radius:10px;padding:12px;display:flex;flex-direction:column;gap:7px}.skeleton{height:12px;background:var(--accent-2);border-radius:8px;width:80%}.skeleton.small{width:50%;opacity:.55}.page button{margin-top:auto;border:1px solid var(--line);border-radius:7px;background:var(--bg);color:var(--muted);padding:6px;font:inherit}.connector{display:flex;flex-direction:column;gap:10px;color:var(--muted)}.connector span:last-child{opacity:.25}.stage[data-step="1"] .connector span:last-child,.stage[data-step="2"] .connector span:last-child{opacity:1;color:var(--accent)}.stage[data-step="1"] button,.stage[data-step="2"] button{border-color:var(--accent);color:var(--accent);background:color-mix(in srgb,var(--accent) 12%,var(--surface))}.stage small,.stage button,.stage .cards b,.stage .phase b,.stage .pair b,.stage .tree-mini b{font-size:clamp(12px,3.2vmin,14px)!important}
js
const stage=document.querySelector(".stage"),clicks=document.getElementById("clicks");let step=0;function tick(){stage.dataset.step=String(step);clicks.textContent=step===2?"1":"0";step=(step+1)%3}tick();let timer=setInterval(tick,950);stage.addEventListener("pointerdown",()=>{clearInterval(timer);tick()})

Hydration is the client renderer attaching events and state to HTML that the server already sent. Content may be visible before clicks work.

If the server and client produce different initial output, hydration mismatches can occur. Treat time, randomness, and browser-only state carefully during the initial render.

When to use

Use it when an SSR page needs interaction, and check visible and usable moments separately.

Open as page ↗