The forums ran from 2008-2020 and are now closed and viewable here as an archive.

Home Forums JavaScript Horizontal drag scrolling

  • This topic is empty.
Viewing 15 posts - 1 through 15 (of 51 total)
  • Author
  • #205670

    I’m trying to create a layout for my portfolio website, I thought there’d be a javascript plug-in for this but I’m struggling to fine one.

    Basically I want my work thumbnails to be displayed in 2 rows, vertically centred on the page, running from the left of the page and off the right. Here’s a quick wireframe I’ve prepared: Layout Wireframe

    Clicking + dragging will slide the content horizontally in the viewport. Clicking on an item will open a new page.

    Has anyone done something like this or seen a plug-in that can achieve this?

    I imagine when the browser has less vertical space, the content would move into 1 row. And when on mobile devices/narrow viewports, this would be disabled and stand horizontal scrolling would be used.


    Seems like you would have a few things going on here – CSS for responsiveness and then two scripts. One for making the content draggable and another for creating opacity on the sides. For the latter, I debugged something similar on SO not too long ago :

    But it might be easier to put a gradient on the sides to simulate a fade. For the dragging, I’d just use some basic jQuery :

    Not sure what you mean with the ‘click and dragging’, should separate thing happen or is that a single event (where click is actually a mousedown)?


    Thanks for the reply @Shikkediel, to be honest with ‘click and dragging’ I just mean dragging – badly worded!

    The fade was an after thought and something I’d probably look at when everything else was working, but until then I agree a gradient either side would be fine.

    I don’t really want to div to glide/slow etc so jQuery should be good for this. Looking at the documentation it looks like I can restrict the drag to a certain axis as well. The stackoverflow Codepen doesn’t work for me, is there another version?


    I started making a quick CodePen:

    When I add containment: "[role='main']" to jQuery though it breaks the drag. I’ve just set a CSS value of 2000px for the container width for now.

    More of a CSS question, but is it possible to have items 1 and 2 in a column, followed by 3 and 4, then so on and so on. Rather than having the first half on the top line and the second half on the bottom?

    I suppose once this is working, it’ll be tricky to have a media query for the jQuery to only display 1 row when the browser height is under a certain value. And likewise when the width is below a certain value disable the drag?


    Looking at the documentation

    From the jQuery UI draggable, you mean? That is a bit different from the embedded pen, that one is just basic jQuery without an additional plugin. For the UI draggable you would need to at least add the core of the UI library and a couple of widgets, something I think is sort of unnecessary because you can code most of it yourself without too much trouble. It’ll be more efficient and I recall the UI version has some trouble with touch devices (I used it a while back and had to add Touch Punch but that may have been improved by now). In the pen above, you could simply remove the lines that are relevant to vertical dragging.

    The stackoverflow Codepen

    The one with the edge opacity? Maybe you could elaborate on what’s not working (could be a browser issue, works for me on FF).

    Edit – had not seen the new post yet…


    Not sure what the best CSS approach would be to be honest. Sounds like you might need some script for that while you’re at it. And I’m not too familiar with the usage of roles or the UI jargon (I prefer to see if I can write some basic code that’ll do the trick).


    I can make an example with JQ alone though if you like. That function should really be independent from (but responsive to) the exact further layout anyway.


    The CSS ordering doesn’t matter too much. I could always wrap every 2 items in a doc and float the Div’s left, if I wanted it ordered that way – I think. It was just so the ones in view on desktop would be at the top when on mobile.

    [role=’main’] is just treat like an ID, so #main would work as well.


    @Shikkediel I’ve just realised my Codepen example does scroll …but not when the items are cropped off screen. If you reduce the width set on the container and/or reduce the number of <figure>s you can see you can drag the layout around, restricted to a horizontal axis.

    It looks like on clicking on the background a value is set inline with javascript which makes the layout jump?

    I’ve actually forked a version of my Codepen where I have the columns set up using css-columns and centred:

    I’ve set [role="main"] {overflow: hidden;} which hides the horizontal scroll bar. The content is draggable but doesn’t behave as expected. Also after initiating a ‘drag’, a top value is set inline so it kinda messes up the responsiveness/centre alignment.


    First thing you mentioned is dependent on the size and positioning of the parent object, it is missing room on the left to be dragged into. I think you’d have to dynamically calculate the size – the amount of additional space needed would have to be as large as the part of the draggable that is sticking out on the right :

    var dragwidth = $('#draggable').width(),
    overflow = Math.max(0, dragwidth-$(window).width()),
    mainwidth = dragwidth+overflow
    $('#main').css({width: mainwidth, left: -overflow});
    $('#draggable').css({left: overflow});

    One thing that is still missing here is the positioning (so left positions will not be in effect). This should also solve the issue with the top positioning. If you make the parent relative and the draggable absolute (for example), that should always make the child’s top position zero.

    Hope that helps a bit and is clear enough.


    Sorry @Shikkediel, I was away for a few days. Unfortunately I couldn’t get the code working …my limited javascript skills rather than to code you provided!

    I had a look/play around and I found another plug-in, the example below kinda works.

    I’ve used a bit of javascript to calculate the width the containing div needs to be. Though when the viewport’s height is less than 600px (for example) this might be a problem when I just want to display 1 row?

    There is a few issues and I was wondering if you think it’s worth persevering with the plug-in. The drag works great on this example but as soon as I add other elements to the mark-up, anchors + text it’s difficult to drag the interface as you need to find a ‘gap’ to do so. Is it be possible to have the div draggable like when using a phone or tablet as default, so a drag movement on any element works and only a click on the anchors would go to a new page/act like a click.

    I was going to use some javascript to get the height of the project-index div and vertically centre it on the page but a bit like the height/number of rows, I’m a bit worried about the amount of overwriting I’ll need to do when the viewport is less than 480px.


    Okay, the bit of code I posted doesn’t work because I hadn’t noticed you were using flexbox. The column width will be returned with $('#draggable').width() and not so much the total. That complicated things but I see you took another approach with the second pen.

    I think this particular case could be better solved by not using the UI or that plugin. It would need some custom code to distinguish between a click and a drag – if it’s dragged it should not fire a click. Such things could be put together by using e.preventDefault() and some internal switching and I don’t think any off-the-shelf code is suitable for that. But let me see if I can slap something together (with the draggable pen I posted initially as a starting point).


    Thanks @Shikkediel, I know sometimes I think, “This plug-in does 75% of what I want so it just needs a few tweaks” but a lot of the time it can be easier to write it from scratch rather than reverse-engineer/hack something to get it to work the way you want.

    For some reason I thought this might of been a common request with how iOS works. I’m really a designer/front-end dev who does the odd bit of javascript so sometimes I can get a bit lost! If you need any design stuff looking at you must give me a holla :)

    EDIT: I did think about using waypoints.js to add/remove a class as each item (figure) moved into in the viewport but figured I’d get this sorted first, one step at a time.


    For some reason I thought this might of been a common request with how iOS works.

    One would think so but there isn’t a whole lot out there describing the behaviour other than the Apple and Android documentation (not even on SO). So to figure out how it works, there’s no real alternative to reading a lot and experimentation. I’ve done a bit of that though so I have a pretty good idea by now (I think at least but I’ve overestimated myself before on the subject). Anyway, here’s an untweaked example of some basic jQuery only code :

    Link to pen

    If I get the general idea correctly of course. Most tweaks can probably be solved with the CSS.


    @Shikkediel that’s great!! Only issue I can see if the last item is cut off slightly, I think that’s to do with the padding on the body element though? Really appreciate that, thanks a lot.

    Out of interest, if I have the 3 layout types:

    1. Mobile (width less than 480px): normal vertical scrolling.
    2. Desktop/tablet (height less than 400px): horizontal scrolling (1 row)
    3. Desktop/tablet (width greater than 480px): horizontal scrolling (2 rows), half width of container div.

    How would you advise managing the javascript. I don’t need any for mobile but I will apply it for the desktop/tablet layouts when the browser is wider than 480px (for example). Then I’d need a slightly different version for when the height is less than 400px (for example). Would you say use if/else statements or do you know of a javascript plug-in where you can treat javascript code like media queries and manage it that way?


    I added a couple of tweaks, one to make it only respond to left mouse clicks :

    if (e.type == 'mousedown' && e.which != 1) return;

    And another so it doesn’t fire a click (and redirect on links) after mouse dragging :

    .click(function() {return false});

    cut off slightly

    Fixed, it was getting the screen width instead of #main

    I usually rely on this little function for ‘media queries’ :

        var gate = $(window),
        window_width = gate.width(),
        window_height = gate.height();
        // some JS magic using the above
        gate.resize(function() {
            window_width = gate.width();
            window_height = gate.height();
            // other resizing calculations

    I’m gonna have to have a small brainstorm about how to best enable or disable the draggable. On touch devices it will prevent default (momentum) scrolling, which is undesirable of course if it’s more than just the top section of the visible screen.

Viewing 15 posts - 1 through 15 (of 51 total)
  • The forum ‘JavaScript’ is closed to new topics and replies.