Kurs Svelte i SvelteKit · Moduł 5: Wiązania

Bindings wymiarów i specjalne

2 min czytania ·
W tej lekcji4

Wymiary elementu

<script>
  let w = $state(0);
  let h = $state(0);
  let text = $state('Zmień rozmiar okna!');
</script>

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

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

Dostępne bindings wymiarów:

  • 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>

Online/Offline status

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

<svelte:window bind:online />

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

Praktyczny przykład: Formularz wikinga

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

  function submit(e) {
    e.preventDefault(); // zatrzymaj przeładowanie strony
    console.log('Zapisano:', $state.snapshot(warrior));
  }
</script>

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

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

  <fieldset>
    <legend>Umiejętności:</legend>
    <label>
      <input type="checkbox" bind:group={warrior.skills} value="sailing" />
      Żeglarstwo
    </label>
    <label>
      <input type="checkbox" bind:group={warrior.skills} value="combat" />
      Walka
    </label>
  </fieldset>

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

  <button type="submit">Zapisz wojownika</button>
</form>

Formularz obsługuje atrybut onsubmit, a e.preventDefault() zatrzymuje przeładowanie strony (w Svelte 4 robił to modyfikator |preventDefault). $state.snapshot(warrior) zamienia reaktywny obiekt w zwykłą kopię, czytelną w konsoli.

Kod do tej lekcji: 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>

Hasła z dokumentacji w tej lekcji

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. Jak śledzić pozycję scrolla okna?

Przydatne artykuły