How do I vertically fix an element in a mobile browser but still allow for horizontal scroll?

474 views Asked by At

On a Desktop browser, I can use the following javascript to vertically fix an element, but still allow for horizontal scroll. As you see, it re-positions the element on every scroll event. To see what I mean, try horizontally and vertically scrolling in this JSFiddle.

var verticallyFixedBox = document.getElementById('verticallyFixedBox');

window.addEventListener('scroll', function() {
    verticallyFixedBox.style.top = '' + document.body.scrollTop + 'px';
});

However, this logic fails for mobile browsers since mobile browsers apparently do not paint until an entire drag completes, leading to a choppy experience.

What's a good way to vertically fix an element, but still allow for horizontal scrolling for mobile browsers?

4

There are 4 answers

1
m1. On BEST ANSWER

If you use a container box that is set to height: 100% and set the height of the html and body elements to 100%, then you can use position: absolute; top: 0; for the fixed header and set overflow: auto (or scroll) for the box that you want to scroll vertically.

Remember to set your body and html margins to 0 to avoid browser default styles.

I've updated the fiddle you had: http://jsfiddle.net/jb489ddL/1/

This solution doesn't use javascript at all so it will work on mobile browsers, since you're not relying on the scroll event.

0
Hauke S On

You actually need JavaScript when using position:fixed; but only to implement the horizontal scrolling part. I updated my fiddle so it also provides horizontal scrolling.

What I did was keeping the verticalFixedBox with position:fixed in its place but adding onother div with the same content but opacity 0.01 and position:absolute; to retain the horizontal scrollbar.

Like here: http://jsfiddle.net/8jzhtg9w/7/

HTML:

<div id='verticallyFixedBox'>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sed ipsum nec sapien fermentum luctus. Fusce varius arcu ut nibh efficitur, quis euismod elit lobortis. Cras at fringilla lectus. Proin ac vulputate metus. Fusce eu mattis urna, at cursus elit. Aliquam erat volutpat. Ut tincidunt et lacus in faucibus. Donec et mi venenatis, condimentum urna vel, ultrices ante.
</div> 
<div class='scroller'> 
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sed ipsum nec sapien fermentum luctus. Fusce varius arcu ut nibh efficitur, quis euismod elit lobortis. Cras at fringilla lectus. Proin ac vulputate metus. Fusce eu mattis urna, at cursus elit. Aliquam erat volutpat. Ut tincidunt et lacus in faucibus. Donec et mi venenatis, condimentum urna vel, ultrices ante.
</div>
<div id='padder'></div>

<p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sed ipsum nec sapien fermentum luctus. Fusce varius arcu ut nibh efficitur, quis euismod elit lobortis. Cras at fringilla lectus. Proin ac vulputate metus. Fusce eu mattis urna, at cursus elit. Aliquam erat volutpat. Ut tincidunt et lacus in faucibus. Donec et mi venenatis, condimentum urna vel, ultrices ante.
</p>

<p>
Nunc non turpis non orci consectetur bibendum eget vitae urna. Nulla dictum, orci sit amet luctus consectetur, nisi nisl rutrum sapien, ut fermentum urna dui a ipsum. Mauris commodo convallis mi, sed ullamcorper enim mollis eget. Maecenas risus felis, lobortis eu interdum elementum, facilisis a justo. Ut semper velit at enim convallis mollis. Interdum et malesuada fames ac ante ipsum primis in faucibus. Duis a orci magna. Duis blandit orci ac fermentum auctor. In hac habitasse platea dictumst. Aliquam sit amet molestie felis, et congue purus. Proin porta mauris sed tincidunt ultrices. Curabitur tristique felis ac sodales aliquet.
</p>

<p>
Etiam placerat lorem non sem feugiat, non tristique neque maximus. Maecenas ultrices scelerisque ante, ut bibendum nunc tincidunt maximus. Proin placerat tincidunt quam in scelerisque. Sed nunc tortor, ultricies ut tincidunt eu, molestie id nunc. Nam nisl mauris, scelerisque at pharetra vitae, lacinia vitae sapien. Etiam sollicitudin eget magna ornare eleifend. Praesent molestie quam a mollis accumsan.
</p>

<p>
Nullam gravida, est ac gravida vulputate, nibh quam bibendum nisl, et posuere eros enim ac ante. Nullam eu tortor vel dui aliquam mattis non a mi. Sed porttitor sem id purus efficitur, at maximus nisi placerat. Integer imperdiet quam a risus varius, feugiat commodo diam dictum. Donec ac viverra risus. Duis rhoncus mi sit amet augue malesuada, et tincidunt magna aliquet. Phasellus fermentum lorem vel ullamcorper commodo. Proin laoreet feugiat ullamcorper. Mauris auctor leo eu imperdiet consectetur. Donec et diam vel ligula elementum consequat. Pellentesque nisl urna, sagittis iaculis venenatis non, varius non nibh.
</p>

<p>
Mauris fermentum eros quis metus tempor venenatis. Suspendisse est nisl, finibus sit amet malesuada vel, pharetra eget neque. Curabitur malesuada non nibh eu pellentesque. Aenean ultrices ante sed lorem rhoncus, ac volutpat urna condimentum. Mauris tincidunt mauris et pretium pellentesque. Sed viverra arcu at risus tempor, sed mattis ex maximus. Proin euismod feugiat tortor sit amet semper. Duis ornare finibus nunc at commodo. Suspendisse dignissim metus quis facilisis vulputate. Nunc eu ultricies leo. Morbi cursus id justo eget tempus. In hac habitasse platea dictumst. In tempor, libero sed ullamcorper aliquam, elit libero mattis magna, sit amet tincidunt mi tellus eu purus. Aenean sed velit nunc. Nunc quis lobortis enim, non sodales neque.
</p>

CSS:

#verticallyFixedBox {
    background: #ccc;
    border-bottom: 2px solid #000;
    left: 0;
    padding: 10px;
    position: fixed;
    top: 0;
    white-space: nowrap;
}
.scroller {
    opacity:0.01;
    position:absolute;
    white-space: nowrap;
    padding: 10px;
    top:0px;
    left:0px;
}
#padder {
    height: 30px;
}

JavaScript:

$(window).scroll(function() {
$('#verticallyFixedBox').css({
        'left': -1 * $(this).scrollLeft()
    });
});

Only problem: opera-mini doesn't seem to support the position:fixed feature yet: http://caniuse.com/#feat=css-fixed

0
Oriol On

You can do it in pure CSS.

#verticallyFixedBox {
  position: sticky;
  top: 0;
}

body {
  margin: 0;
}
#verticallyFixedBox {
  position: sticky;
  top: 0;
  background: #ccc;
  border-bottom: 2px solid #000;
  padding: 10px;
  white-space: nowrap;
}
<div id='verticallyFixedBox'>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sed ipsum nec sapien fermentum luctus. Fusce varius arcu ut nibh efficitur, quis euismod elit lobortis. Cras at fringilla lectus. Proin ac vulputate metus. Fusce eu mattis urna, at cursus elit. Aliquam erat volutpat. Ut tincidunt et lacus in faucibus. Donec et mi venenatis, condimentum urna vel, ultrices ante.
</div>
<p>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sed ipsum nec sapien fermentum luctus. Fusce varius arcu ut nibh efficitur, quis euismod elit lobortis. Cras at fringilla lectus. Proin ac vulputate metus. Fusce eu mattis urna, at cursus elit. Aliquam erat volutpat. Ut tincidunt et lacus in faucibus. Donec et mi venenatis, condimentum urna vel, ultrices ante.
</p>
<p>
  Nunc non turpis non orci consectetur bibendum eget vitae urna. Nulla dictum, orci sit amet luctus consectetur, nisi nisl rutrum sapien, ut fermentum urna dui a ipsum. Mauris commodo convallis mi, sed ullamcorper enim mollis eget. Maecenas risus felis, lobortis eu interdum elementum, facilisis a justo. Ut semper velit at enim convallis mollis. Interdum et malesuada fames ac ante ipsum primis in faucibus. Duis a orci magna. Duis blandit orci ac fermentum auctor. In hac habitasse platea dictumst. Aliquam sit amet molestie felis, et congue purus. Proin porta mauris sed tincidunt ultrices. Curabitur tristique felis ac sodales aliquet.
</p>
<p>
  Etiam placerat lorem non sem feugiat, non tristique neque maximus. Maecenas ultrices scelerisque ante, ut bibendum nunc tincidunt maximus. Proin placerat tincidunt quam in scelerisque. Sed nunc tortor, ultricies ut tincidunt eu, molestie id nunc. Nam nisl mauris, scelerisque at pharetra vitae, lacinia vitae sapien. Etiam sollicitudin eget magna ornare eleifend. Praesent molestie quam a mollis accumsan.
</p>
<p>
  Nullam gravida, est ac gravida vulputate, nibh quam bibendum nisl, et posuere eros enim ac ante. Nullam eu tortor vel dui aliquam mattis non a mi. Sed porttitor sem id purus efficitur, at maximus nisi placerat. Integer imperdiet quam a risus varius, feugiat commodo diam dictum. Donec ac viverra risus. Duis rhoncus mi sit amet augue malesuada, et tincidunt magna aliquet. Phasellus fermentum lorem vel ullamcorper commodo. Proin laoreet feugiat ullamcorper. Mauris auctor leo eu imperdiet consectetur. Donec et diam vel ligula elementum consequat. Pellentesque nisl urna, sagittis iaculis venenatis non, varius non nibh.
</p>
<p>
  Mauris fermentum eros quis metus tempor venenatis. Suspendisse est nisl, finibus sit amet malesuada vel, pharetra eget neque. Curabitur malesuada non nibh eu pellentesque. Aenean ultrices ante sed lorem rhoncus, ac volutpat urna condimentum. Mauris tincidunt mauris et pretium pellentesque. Sed viverra arcu at risus tempor, sed mattis ex maximus. Proin euismod feugiat tortor sit amet semper. Duis ornare finibus nunc at commodo. Suspendisse dignissim metus quis facilisis vulputate. Nunc eu ultricies leo. Morbi cursus id justo eget tempus. In hac habitasse platea dictumst. In tempor, libero sed ullamcorper aliquam, elit libero mattis magna, sit amet tincidunt mi tellus eu purus. Aenean sed velit nunc. Nunc quis lobortis enim, non sodales neque.
</p>

Note not all browsers support sticky positioning yet.

0
msinnes On

Avoid using JavaScript for a layout problem. If I understand what you are looking for, you want the top-most element, verticallyFixedBox, to remain in one place, and you want its contents scrollable regardless of screen size.

Put the content of verticallyFixedBox into a separate div element. Then set that child div to be the scrollable element. You have to make sure that you fix the top, left, and right sides of verticallyFixedBox to the top, left, and right of the browser window as well.

#verticallyFixedBox
    background: #ccc;
    border-bottom: 2px solid #000;
    padding: 10px;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
}

#scroll {
    position: relative;
    overflow: scroll;
    white-space: nowrap;
}

<div id='verticallyFixedBox'>
    <div id='scroll'>
    Lorem ipsum dolor...rest of text. 
    </div>
</div>

By fixing the outer div and scrolling inside of it, you should get a pretty consistent display across the majority of devices. Updated it on your JSFiddle Hope this is what you were looking for.

And here is an extra page with the code on a unlinked folder on my server: Test Page. It looks like it works on my phone.