Cours Svelte et SvelteKit · Module 5: Liaisons

Bindings de dimensions et bindings spéciaux

2 min de lecture ·
Dans cette leçon4

Dimensions d'un élément

<script>
  let w = $state(0);
  let h = $state(0);
  let text = $state('Resize the window!');
</script>

<div
  bind:clientWidth={w}
  bind:clientHeight={h}
  class="box"
>
  <p>{text}</p>
  <p>Dimensions: {w} x {h}px</p>
</div>

<style>
  .box {
    width: 100%;
    height: 200px;
    background: #2a2a4a;
    padding: 1rem;
  }
</style>

Bindings de dimensions disponibles :

  • clientWidth / clientHeight
  • offsetWidth / offsetHeight

Scroll

<script>
  let scrollY = $state(0);
</script>

<svelte:window bind:scrollY />

<div class="header" class:scrolled={scrollY > 50}>
  Viking Saga
</div>

<style>
  .header {
    position: fixed;
    top: 0;
    transition: background 0.3s;
  }
  .header.scrolled {
    background: rgba(0, 0, 0, 0.8);
  }
</style>

Statut En ligne/Hors ligne

<script>
  let online = $state(true);
</script>

<svelte:window bind:online />

<p>Status: {online ? 'Online' : 'Offline'}</p>

Exemple pratique : Formulaire viking

<script>
  let warrior = $state({
    name: '',
    rank: 'drengr',
    skills: [],
    bio: ''
  });

  function submit(e) {
    e.preventDefault(); // empêche le rechargement de la page
    console.log('Saved:', $state.snapshot(warrior));
  }
</script>

<form onsubmit={submit}>
  <label>
    Name:
    <input bind:value={warrior.name} required />
  </label>

  <label>
    Rank:
    <select bind:value={warrior.rank}>
      <option value="drengr">Drengr</option>
      <option value="jarl">Jarl</option>
    </select>
  </label>

  <fieldset>
    <legend>Skills:</legend>
    <label>
      <input type="checkbox" bind:group={warrior.skills} value="sailing" />
      Sailing
    </label>
    <label>
      <input type="checkbox" bind:group={warrior.skills} value="combat" />
      Combat
    </label>
  </fieldset>

  <label>
    Biography:
    <textarea bind:value={warrior.bio}></textarea>
  </label>

  <button type="submit">Save warrior</button>
</form>

Le formulaire utilise l'attribut onsubmit, et e.preventDefault() empêche le rechargement de la page (en Svelte 4, le modificateur |preventDefault s'en chargeait). $state.snapshot(warrior) transforme l'objet réactif en simple copie, lisible dans la console.

Code de cette leçon : App.svelte
<script>
  // DOM bindings - bind:this, bind:clientWidth etc.

  // bind:this only needs a plain variable (used in a function, not in the markup)
  let inputRef;

  // Values shown in the markup must be $state to update the view
  let containerWidth = $state(0);
  let containerHeight = $state(0);
  let scrollY = $state(0);

  function focusInput() {
    inputRef?.focus();
  }

  $effect(() => {
    console.log('Scroll position:', scrollY);
  });
</script>

<svelte:window bind:scrollY />

<main class="dom-demo">
  <h1>DOM Bindings</h1>

  <section>
    <h2>bind:this - element reference</h2>
    <input
      bind:this={inputRef}
      type="text"
      placeholder="Click button to focus"
    />
    <button onclick={focusInput}>Focus input</button>
  </section>

  <section bind:clientWidth={containerWidth} bind:clientHeight={containerHeight}>
    <h2>bind:clientWidth/Height</h2>
    <p>Width: <strong>{Math.round(containerWidth)}px</strong></p>
    <p>Height: <strong>{Math.round(containerHeight)}px</strong></p>
    <p class="hint">Resize the window to see changes</p>
  </section>

  <section>
    <h2>svelte:window - scroll</h2>
    <p>Scroll Y: <strong>{Math.round(scrollY)}px</strong></p>
    <div class="scroll-area">
      <p>Scroll the page down...</p>
      <div class="spacer"></div>
      <p>...and observe the scrollY value</p>
    </div>
  </section>
</main>

<style>
  .dom-demo {
    font-family: 'Georgia', serif;
    max-width: 600px;
    margin: 0 auto;
    padding: 2rem;
    background: #1a0f0a;
    color: #e8d5b7;
    min-height: 150vh;
  }

  h1 {
    color: #d4af37;
    text-align: center;
    position: sticky;
    top: 0;
    background: #1a0f0a;
    padding: 1rem 0;
  }

  section {
    background: rgba(212, 175, 55, 0.1);
    border: 1px solid #d4af37;
    border-radius: 8px;
    padding: 1rem;
    margin: 1rem 0;
  }

  h2 {
    color: #d4af37;
    font-size: 1rem;
    margin-top: 0;
  }

  input {
    width: 100%;
    padding: 0.75rem;
    background: rgba(0,0,0,0.3);
    border: 1px solid #3d2914;
    border-radius: 4px;
    color: #e8d5b7;
    margin-bottom: 0.5rem;
  }

  input:focus {
    border-color: #d4af37;
    outline: none;
  }

  button {
    padding: 0.5rem 1rem;
    background: #3d2914;
    color: #e8d5b7;
    border: 1px solid #d4af37;
    border-radius: 4px;
    cursor: pointer;
  }

  button:hover {
    background: #4d3924;
  }

  strong {
    color: #ffd700;
  }

  .hint {
    font-size: 0.85rem;
    color: #8b7355;
    font-style: italic;
  }

  .scroll-area {
    padding: 1rem;
    background: rgba(0,0,0,0.3);
    border-radius: 4px;
  }

  .spacer {
    height: 200px;
  }
</style>

Entrées de la documentation utilisées dans cette leçon

Tu as repéré une erreur dans cette leçon ?

Teste tes connaissances

Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.

  1. 1. Comment suivre la position du scroll de la fenêtre ?

Articles utiles