Responsive Horizontal Scrolling Menu
Asked Answered
L

4

3

http://healthunit.com has a clean horizontal scrolling menu at the top of the screen once you view it from a mobile phone device. I'm trying to mimic that same exact functionality thanks to a site I'm redesigning with a huge level of navigation elements.

Requirements:

  1. Left and right scroll click options
  2. Centered list item option centered in the space
  3. Only one list item visible at a time
  4. Horizontal Scrolling & Responsive
  5. Clicking the last or first option in the list will take you to either the first option or last option in the list

My current html for this section is:

<nav id="sub" class="clearfix">
  <ul class="wrapper">
    <a href="#"><li>Estimate</li></a>
    <a href="#"><li>About</li></a>
    <a href="#"><li>Customer Information</li></a>
    <a href="#"><li>Financing</li></a>
    <a href="#"><li>Careers</li></a>
    <a href="#"><li>Locate Us</li></a>
    <a href="#"><li>Inspiration</li></a>
  </ul>
</nav>

The CSS currently attached to it is:

nav#sub {
  background: #004173;
  background: linear-gradient(to bottom, #004173 0%,#014f8d 100%);
  background: -moz-linear-gradient(top, #004173 0%, #014f8d 100%);
  background: -ms-linear-gradient(top, #004173 0%,#014f8d 100%);
  background: -o-linear-gradient(top, #004173 0%,#014f8d 100%);
  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#004173), color-stop(100%,#014f8d));
  background: -webkit-linear-gradient(top, #004173 0%,#014f8d 100%);
  border-bottom: #00325a solid 3px;
  box-shadow: 0 4px 6px 0 #BFBFBF;
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#004173', endColorstr='#014f8d',GradientType=0 );
  webkit-box-shadow: 0 4px 6px 0 #BFBFBF;
}

#sub ul {
  text-align: center;
}

#sub ul li {
  padding: 10px 3.3%;
}

#sub a {
  color: #fff;
  font-size: 10pt;
  font-weight: 400;
  text-decoration: none;
}

#sub ul a:hover li {
  background: #007FEB;
}
Lamere answered 16/7, 2014 at 15:21 Comment(4)
Do you want it to be controlled with scrolling or 2 Buttons on the left and the right ("<" and ">")? (...or both?)Petroleum
Hi Stefan, I am aiming for it to be controlled with the 2 Buttons on the left and right (< and >).Lamere
You probably want to add to the post some specific details you would like help with :).Dolphin
Added on the requirements as requested BlunderfestLamere
P
10

So, finally I think I have what you are looking for:

Fiddle: http://jsfiddle.net/fzXMg/2/

CSS and HTML is in the Fiddle...

JS:

$(function(){
    var state = 0;
    var maxState = 6;
    var winWidth = $(window).width();
    $(window).resize(function(){
        winWidth = $(window).width();
        $('.box,.container_element').width(winWidth-100);
    }).trigger('resize');
    $('#lefty').click(function(){
        if (state==0) {
           state = maxState;
        } else {
           state--;
        }
        $('.container_element').animate({scrollLeft:((winWidth-100)*state)+'px'}, 800);
    });
    $('#righty').click(function(){
        if (state==maxState) {
           state = 0;
        } else {
           state++;
        }
        $('.container_element').animate({scrollLeft:((winWidth-100)*state)+'px'}, 800);
    });
});

This uses jQuery again.

Petroleum answered 16/7, 2014 at 17:32 Comment(3)
Exactly it! very nice Stefan. +1 Badass Token to your coding skills.Lamere
Wow it's a best answer. +1Caboodle
what if I want more than 1 item to be show at a time ? something like < item1 item2 item3 >, like split in 4, and every time the user hits <, > it moves a shift to the side.Childbed
B
3

Now that the healthunit site has changed the original question is not completely clear.

To make a nav menu that scrolls horizontally uses arrow buttons (instead of scrollbar) can be implemented with a little jQuery and easily converted to pure JavaScript.

var $bar = $('.nav');
var $container = $('#outer');
var widths = {};
var scrollOffset = 0;

var container = document.getElementById("outer");
var bar = document.getElementById("bar");

function setMetrics() {
    metrics = {
        bar: bar.scrollWidth||0,
        container: container.clientWidth||0,
        left: parseInt(bar.offsetLeft),
        getHidden() {
            return (this.bar+this.left)-this.container
        }
    }

    updateArrows();
}

function doSlide(direction){
    setMetrics();
    var pos = metrics.left;
    if (direction==="right") {
        amountToScroll = -(Math.abs(pos) + Math.min(metrics.getHidden(), metrics.container));
    }
    else {
        amountToScroll = Math.min(0, (metrics.container + pos));
    }
    $bar.css("left", amountToScroll);
    setTimeout(function(){
        setMetrics();
    },400)
}

function updateArrows() {
    if (metrics.getHidden() === 0) {
        $(".toggleRight").addClass("text-light");
    }
    else {
        $(".toggleRight").removeClass("text-light");
    }

    if (metrics.left === 0) {
        $(".toggleLeft").addClass("text-light");
    }
    else {
        $(".toggleLeft").removeClass("text-light");
    }
}

function adjust(){
    $bar.css("left", 0);
    setMetrics();
}

$(".toggleRight").click(function(){
    doSlide("right");
});

$(".toggleLeft").click(function(){
    doSlide("left");
});

$(window).on("resize",function(){
    // reset to left pos 0 on window resize
    adjust();
});

setMetrics();

Demo: https://www.codeply.com/go/HgAVBVfQFY

Barrel answered 30/1, 2019 at 19:10 Comment(0)
P
1

Check out that fiddle: http://jsfiddle.net/zEPQ5/15/

It's not perfect in meaning of design, but it shows off the concept.

I used jQuery with that.

$(function(){
    var state = 0;
    $('#up').click(function(){
        state += 1;
        $('ul.wrapper').animate({marginTop:(15-state*35)+'px'},400);
    });
    $('#down').click(function(){
        state -= 1;
        $('ul.wrapper').animate({marginTop:(15-state*35)+'px'},400);
    });
});
Petroleum answered 16/7, 2014 at 16:5 Comment(1)
Definitely heading in the right direction, the main differences I think that I see between the example and yours is that yours is scrolling vertically opposed to horizontally, and that you can go past your first and last option without returning to the top or end of the list. I'll edit the requirements to include the last part. Nice work so far though, you definitely got the idea.Lamere
H
0

Check out this jsfiddle: http://jsfiddle.net/7vvdB/

Basically, create an outer container with a max-width of 100% and a overflow-x:scroll, then create an inner container with a fixed width large enough to fit all of your elements, then put all of your elements in the inner container.

.container_element
{ white-space:nowrap
    min-width:100%;
    overflow-x:scroll;
    overflow-y:hide;

}

.inner_container
{
    width:5000px;
}
}
Hodge answered 16/7, 2014 at 15:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.