# Issue with vertical scrolling marquee

**URL:** https://community.xibo.org.uk/t/issue-with-vertical-scrolling-marquee/38487
**Category:** CMS Features and Functionality
**Created:** [October 16, 2026, 10:14am UTC](https://community.xibo.org.uk/t/issue-with-vertical-scrolling-marquee/38487 "2026-10-16T10:14:26Z")
**Posts on this page:** 1
**Page:** 1

<div class="post-metadata">

### Author: ![Romolo\_Manfredini](https://community.xibo.org.uk/user_avatar/community.xibo.org.uk/romolo_manfredini/32/19662_2.png) [@Romolo\_Manfredini](https://community.xibo.org.uk/u/Romolo_Manfredini)
#### Post date: [October 16, 2026, 10:14am UTC](https://community.xibo.org.uk/t/issue-with-vertical-scrolling-marquee/38487/1 "2026-10-16T10:14:26Z")

</div>

# CMS Version

4.5.3

# Player Type

Any

# Marquee scroll too fast

I’m analyzing the `jquery.marquee` plugin block in the bundle and the two functions that call it (`xiboElementsRender` and `xiboTextRender`). .

**What I verified in the code**

Vertical scrolling is handled by the `jquery.marquee` plugin (module 59080), with this flow:

1. Xibo sets `data-speed = speed / 25 * 1000`, in both `xiboElementsRender` and `xiboTextRender`. If `speed` is 0 it is forced to 1.
2. As soon as the plugin reads the options, it computes `duration = c.width() / speed * 1000`. It always uses the container’s **width** , even when the direction is `up` or `down`. The vertical-direction flag (`i`) is only set after this line.
3. In the vertical branch the duration is then rescaled: `duration = (h + O) / O * duration`, where `O` is the container height and `h` is the content height plus the gap.
4. With `seamless` enabled (`data-duplicated`) the duration is divided by 2.

**Why `speed` doesn’t behave as you’d expect**

For vertical scrolling, the actual speed in pixels per second works out to `speed * 40 * (container height / container width)`, rather than `speed * 40`. The result therefore depends on the container’s aspect ratio. A tall, narrow ticker scrolls much faster than it should, while a wide, short one scrolls much slower. This is an inference from the code, and something that can be observed at runtime in anyplayer.

**Why `duration` has no effect**

In the `marqueeUp` and `marqueeDown` branches of both functions, the widget’s `duration` parameter is never used. It only appears in the `cycle` branch (`e.duration / numItems`), i.e. for slide effects. For the marquee, the scroll time depends on `speed` and the content height, while the widget `duration` only determines when the layout moves on to the next widget. If the text is longer than the scroll can complete in the configured time, it gets cut off. This is the current code’s behavior, not necessarily the intended one.

By example with a 240 × 740 container, the formula puts the vertical scroll at about 3.1 times the speed it should have. This is a calculation from the code, not a runtime measurement. I’m assuming those are the dimensions of the element the marquee runs on (`.scroll` or its parent) and that `O` in the code equals 740.

**The calculation**

- The plugin computes the base duration from the width: `240 / (speed × 40) × 1000` ms. For example, with `speed = 2` (the default in the elements renderer) this is about 2.99 s.
- It then multiplies by `(h + 740) / 740`, where `h` is the content height plus gap. The distance travelled is `h + 740`, so the actual velocity is `740 / base duration`, which cancels out `h`.
- With `speed = 2` that gives about 248 px/s instead of the intended 80 px/s.
- In general, the actual velocity is `speed × 40 × (740 / 239)`, which is `speed × 40 × 3.096`. That is about **124 px/s per speed unit** instead of 40.

I’m treating `data-speed` as pixels per second because that is what the horizontal case produces: there, `width / duration` works out to exactly `data-speed`. This is my reading of the intended behavior, not something documented.

**Consequences**

- Since `speed = 0` is forced to 1, the slowest scroll you can get with a similar aspect ratio is about 124 px/s.
- The vertical scroll will never match the horizontal one, because the correction factor depends on the aspect ratio.

I have prepared a small python script to patch bundle.min.js to take into account height instead of width for vertical scolling plugins:

```auto

#!/usr/bin/env python3

"""Patch jquery.marquee in Xibo bundle: use height for vertical scroll."""

import sys
OLD = 's.speed&&(s.duration=parseInt(c.width(),10)/s.speed*1e3),i="up"===s.direction||"down"===s.direction,'

NEW = 'i="up"===s.direction||"down"===s.direction,s.speed&&(s.duration=parseInt(i?c.height():c.width(),10)/s.speed*1e3),'

src, dst = sys.argv[1], sys.argv[2]
data = open(src, encoding="utf-8").read()

n = data.count(OLD)
if n != 1:
sys.exit(f"ERROR: Expected 1 occurrences, found {n}. Not modifying.")
open(dst, "w", encoding="utf-8").write(data.replace(OLD, NEW))
print("Patch have been applied:", dst)

```

Usage: python3 apply\_marquee\_patch.py bundle\_min.js bundle\_min.patched.js  
And then substitute the bundle…
