Custom scroll bar only working on Scroll Up?

I have created a custom Dropdown with a custom scrollbar. The scroll for some reason only works properly on the scroll up not on the scroll down. I believe the math and functions should be the same for both but that is not working. Am I missing here or did I set up the functions wrong?

Thank you.

AxShare Prototype HTML
Custom Scroll Issue.rp (107 KB)

Name your widgets! I was able to use the Axshare console to see you have the scroll interactions on an unnamed dynamic panel but I can’t for the life of me find that panel in the file.

That said, the problem seems to be you’re moving by and not to. Notice how as you scroll the bar doesn’t move at a linear speed? That’s because each time the case executes you’re moving less and less or more and more.

You shouldn’t need the boundaries either because you’re going to move the bar based on a percentage of how much of the panel has been scrolled. Let’s say the scrollbar total area is 100 tall. When the panel is scrolled to the top you want the bar to be positioned at 0. When the panel is scrolled to the bottom you want the bar positioned at 100 - scrollBar.height. The panel scrolled to the top is panel.scrollY == 0, and scrolled to the bottom (assuming the full repeater is the only content) is panel.scrollY == repeater.height - panel.height. So now we just need to turn the scrolled amount into a percentage of the total possible scroll amount and we can use that to position the bar.

[[panel.scrollY / (repeater.height - panel.height)]] is what percentage of the total way you’ve scrolled (represented as a value in the range [0,1])

Now to moving the scrollbar. Since we’re moving to a point we only need to use the OnScroll event, this expression won’t care if you’re scrolling up or down since it only cares about where the scroll actually is at the moment. We established that the maximum y-position of the bar is (let barArea be height of the scrollbar area, not the bar itself) barArea - scrollbar.height, therefore we need to move the bar to:

[[(panel.scrollY / (repeater.height - panel.height)) * (barArea - scrollbar.height)]]

Let’s say barArea is 100 and the scroll bar is 25 high. The maximum y-position is 75. Since our earlier expression gives is a range of [0,1], when you’re scrolled to the top the scroll percentage will be 0 thus the bar will be positioned at 0 * 75, or 0. Right where we want it. When you’re scrolled to the bottom the percentage value will be 1, thus the bar will be at 1 * 75.

After writing all this I quickly tested it in Axure and it worked as expected. Sorry for it being so wordy but I wanted to walk through my thinking and how I arrived at the conclusion.


I created this a while back. Funny - it has the same formula as Nathan’s! Excellent explanation, by the way.

This version allows dragging of the scroll handle to scroll as well. The OnDrag interaction is on the handle itself, but instead of moving the handle, OnDrag scrolls the window the desired amount (which in turn moves the handle due to the OnScroll script).

Live sample

File:fake_scrollbar.rp (66.6 KB)


I found an error on the OnDrag script for dragging the slider handle to scroll (which actually instead sets the scroll of the panel, and relies on OnScroll of this panel to move the handle). Here is the new OnDrag expression:

Move scrollTo_rect to [[ (LV_startYloc + TotalDragY) * (LV_contentArea.height - LV_scrollingPanel.height)/(LV_scrollingPanel.height - This.height) ]]

Breaking that down:

[li][](LV_startYloc + TotalDragY): The would-be y position of the scroll handle since that’s actual drag target, even though we’re really setting the scroll on drag and relying on OnScroll to position the slider handle. We don’t have to worry about top/bottom drag limits since the panel’s scroll can’t be less than zero or greater than the amount it’s able to scroll.[/li][li][](LV_contentArea.height - LV_scrollingPanel.height): the number of pixels that the panel can scroll[/li][li][*](LV_scrollingPanel.height - This.height): the distance in pixels that the slider handle can move. “This” here is the slider handle.[/li][/ul]

Updated file:
fake_scrollbar.rp (74.1 KB)

1 Like


Your sample prototype is perfect! Would you take a while to explain the functions? I kinda messed up:confused:…

What’s the function of v_startYloc ?

[[ (LV_startYloc + TotalDragY) * (LV_contentArea.height - LV_scrollingPanel.height)/(LV_scrollingPanel.height - This.height) ]]

[[This.height/LV_contentArea.height*This.height) ]]

fake_scrollbar.rp (74.1 KB)


TotalDragY is a keyword that tells you the total Y offset that you have dragged the mouse from the drag start point, regardless of whether you choose to move the drag target. As you drag down, the number gets bigger; as you drag up, it gets smaller, and it will become a negative number if it is dragged above the drag start point.

LV_startLoc is a local variable referring to a text label that is set to the Y location of the dragged object at the beginning of the drag. When you add TotalDragY to this, it gives you the location that the dragged object would be.


Thanks for your reply. I was trying hard to understand the cases. Before I get through the functions/formula, I think I need to figure out the following cases:

Why is there an OnResize on DP_viewport (the most outside dynamic panel), since it is not set to FIT TO CONTENT? Its size is fixed, not resizable… And why when DP_viewport OnResize, the width of DP_content increases 20?

And for this condition: if [[contentArea.height]]<=[[DPcontent.height]]
I cannot get it…since
contentArea.height=540, it’s fixed…
DPcontent.height=200, also fixed…

DP_content OnResize
(Still DP_content is not set to FIT TO CONTENT, how can it have a OnResize case…)
Fire OnLoad on this What’s this for?


Hi Tintin!

These are all good questions. The main thing is that just because a panel in not set to Fit to Content doesn’t mean it can’t be resized. There is a Resize command, which you might utilize in a responsive situation. In which case OnResize would respond to the resizing and adjust everything appropriately.

It’s also good not to use hardcoded numbers but use instead object properties (object.width, object.height, object.x) that those hardcoded numbers are based on. That way you can change the size of something or move it - even in Axure - and not update any code.

You did catch an oddity in the resize code. The event firing (OnLoad firing OnResize) should have taken place on the outermost panel, not the inner scrollng one. I’m attaching the updated version.

When you open it, resize the outer panel to whatever size you want and then run it. I think you’ll immediately understand why we are not using hardcoded numbers, because everything will automatically adjust to this new size.

Here’s why:

Because the outer panel’s OnLoad is firing OnResize, all its OnResize code runs when the prototype loads: It resizes the inner scrolling panel to its own size plus an extra 20 in width (to hide the real scrollbar off-panel). And when, in turn, the inner scrolling panel is resized (by the aforementioned code), its own OnResize handler gets fired and adjusts the scrollbar height, etc.

New file: fake_scrollbar.rp (73.1 KB)


Hi Jose, thanks for your patience!

So this prototype is made highly reusable… Now everything is clear to me.:smiley:

Thanks again.

Hi Jose, thanks for your patience!

So this prototype is made highly reusable… Now everything is clear to me.

Thanks again.

Hi josephxbrick,:slight_smile:
I am trying to achieve the same scroll effect
Here live-product example:
But my scroll is “scrolling half way”. scroll.rp (744.7 KB)

If you could please help me out with advise how to solve it, I would greatly appreciate it!

Hi Natalie!

The reason the scrollbar isn’t working is that a local variable in the OnScroll expression is pointing at an undefined widget. I still get caught by this.

It’s supposed to be pointing at the hotspot that defines the size of the scrolling area in the content. Take a look at the original file. Also, It’s my experience that if there’s one instance of an undefined widget, you’ll likely run into others. So I’d open all of those fx boxes and make sure everything is assigned.

Let me know if this doesn’t fix it!

1 Like

Hi Joseph, :slight_smile:
Thank you for your reply and suggestions!!! I follow your advice and fixed all ‘unidentified’ fields.

scroll-updated.rp (744.1 KB)

I have resolved scrolling issue. :slight_smile:

1 Like