# Scroll Based Velocity

> Text marquee rows whose speed follows scroll velocity. Rows can lean and stretch with speed, be thrown with inertia and alternate with outlined text.

Rows of repeated text drift sideways, odd rows the other way. Scroll and they speed up in the direction you scroll, then ease back to their cruising pace. Rows can lean and stretch with speed, and with `draggable` you can grab a row, scrub it and throw it so it glides on. Scroll inside the demo, drag a row and try the presets in the panel.

<demo-scroll-based-velocity>



</demo-scroll-based-velocity>

## Installation

```bash
npx shadcn-vue@latest add "https://nxui.geoql.in/r/scroll-based-velocity.json"
```

## Usage

```vue
<script setup lang="ts">
  import ScrollBasedVelocity from '~/components/ui/scroll-based-velocity/ScrollBasedVelocity.vue';
</script>

<template>
  <!-- "Skew" preset -->
  <ScrollBasedVelocity
    :texts="['Vue ✦ nxui', 'Scroll Down']"
    :velocity="70"
    :skew-with-velocity="16"
    :scale-with-velocity="0.18"
    :font-size="104"
    :font-weight="900"
    fade-edges
    draggable
  />
</template>
```

The rows follow the window scroll by default. Pass `scroll-container` to follow a scrolling element instead.

## Props

<table>
<thead>
  <tr>
    <th>
      Prop
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        texts
      </code>
    </td>
    
    <td>
      <code>
        string[]
      </code>
    </td>
    
    <td>
      <code>
        []
      </code>
    </td>
    
    <td>
      One row per entry. Odd rows run the other way.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        velocity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        100
      </code>
    </td>
    
    <td>
      Base speed in px/s. The sign is flipped for odd rows.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Text color. Follows the surrounding text color when left out.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        font-size
      </code>
    </td>
    
    <td>
      <code>
        number | string
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Text size. Numbers are px. Left out, the rows use <code>
        text-4xl
      </code>
      
       / <code>
        5rem
      </code>
      
       on md screens.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        font-weight
      </code>
    </td>
    
    <td>
      <code>
        number | string
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Text weight. Left out, the rows are bold.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        skew-with-velocity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      How far the rows lean into their motion at full speed, in degrees. Eases back when they slow.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        scale-with-velocity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      How much the rows stretch taller at full speed, as a fraction. Negative values squash them.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        draggable
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Grab a row to scrub it, then throw it to glide on with inertia.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        outline-alternate
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Draws every other row as outlined text.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        gap
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Extra space between copies in px, split evenly around the separator.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        separator
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Shown between the copies, like a dot or a slash. Empty leaves a space.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        fade-edges
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Softly fades the rows out at the left and right edges.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        pause-on-hover
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Glides the rows to a stop while the pointer is over them.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        num-copies
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        6
      </code>
    </td>
    
    <td>
      Copies rendered per row for a seamless loop.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        damping
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        50
      </code>
    </td>
    
    <td>
      Damping of the scroll-velocity spring.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        stiffness
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        400
      </code>
    </td>
    
    <td>
      Stiffness of the scroll-velocity spring.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        velocity-mapping
      </code>
    </td>
    
    <td>
      <code>
        { input: number[]; output: number[] }
      </code>
    </td>
    
    <td>
      <code>
        { input: [0, 1000], output: [0, 5] }
      </code>
    </td>
    
    <td>
      Maps scroll velocity (px/s) to a movement multiplier. Not clamped.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        scroll-container
      </code>
    </td>
    
    <td>
      <code>
        HTMLElement | null
      </code>
    </td>
    
    <td>
      <code>
        null
      </code>
    </td>
    
    <td>
      Scrolling element to follow. Defaults to the window.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        text-class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Classes on each repeated text copy.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        parallax-class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes on each row's clipping container.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        scroller-class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes on each row's moving track.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        parallax-style
      </code>
    </td>
    
    <td>
      <code>
        StyleValue
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Inline styles on each row's clipping container.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        scroller-style
      </code>
    </td>
    
    <td>
      <code>
        StyleValue
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Inline styles on each row's moving track.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes on the root.
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- Only the first copy in each row is read by screen readers; the repeats are `aria-hidden`.
- With `prefers-reduced-motion: reduce` the rows stand still. Dragging still works.
- Each row stops its animation loop while it is off screen.
- A drag of more than a few pixels swallows the click that follows, so links inside a row are not opened by accident.
- Ported from [React Bits](https://reactbits.dev/text-animations/scroll-velocity) by David Haz.
