Tuesday 5 November 2013

Fixed jQuery Mobile footers on Windows Phone 8

    Here's a solution to something which baffled me for a while: making a jQuery Mobile footer that stayed at the bottom of the screen and didn't scroll away with the content in a PhoneGap app on Windows Phone 8.
    jQuery Mobile is usually pretty good at making fixed footers. The code below works fine on Android, using data-role and data-position attributes on the footer div.

<body> 
<div id="container" data-role="page" data-theme="f">
    <div id="header"  data-role="header" data-position="fixed" data-tap-toggle="false">
    Header content here
    </div><!-- /header -->

    <div id="content" data-role="content">
    Page content here
    </div><!-- /content -->

    <div data-role="footer" data-position="fixed" id="footer" data-tap-toggle="false">
     Footer content here
    </div><!-- /footer -->
</div><!-- /page -->
</body>

    Unfortunately, on Windows Phone 8 it places the footer at the base of the screen but does not allow the content to scroll underneath it. Thus your footer scrolls up the screen with the content, hiding a bit of content as it goes and looking really horrible.
    You might think breaking out of jQuery Mobile by losing the data-role and data-position attributes and then applying a fixed position and a z-index to your footer would do the job. After all, it's the standard fix for some of jQuery Mobile's footer quirks on iOS. But sadly all that does on WP8 is anchor the footer to the bottom of the page rather than the bottom of the screen, resulting in a long scroll to see it. Less obviously broken, but still not what we want.
    My solution then was to apply a fixed height to the content div and allow the default WP8 overflow:auto; CSS to make its content scroll out of sight beneath it. I removed the data-role and data-position attributes from the footer and used a little piece of javascript to calculate the height of the content div from the heights of the surrounding divs and set it. Not necessarily the most elegant solution, but one that should reliably work across a range of devices.

<body> 
<div id="container" data-role="page" data-theme="f">
    <div id="header"  data-role="header" data-position="fixed" data-tap-toggle="false">
    Header content here
    </div><!-- /header -->

    <div id="content" data-role="content">
    Page content here
    </div><!-- /content -->

    <div data-role="footer">
     Footer content here
    </div><!-- /footer -->
</div><!-- /page -->
<script>

//NB the code below references jQuery, not included in this HTML for simplicity

var headerSpace = parseInt($('#header').css("height")) + parseInt($('#header').css("marginTop")) + parseInt($('#header').css("marginBottom")) + parseInt($('#header').css("paddingTop")) + parseInt($('#header').css("paddingBottom"));

var contentSpace = parseInt($('#content').css("marginTop")) + parseInt($('#content').css("marginBottom")) + parseInt($('#content').css("paddingTop")) + parseInt($('#content').css("paddingBottom"));

var footerSpace = parseInt($('#footer').css("height")) + parseInt($('#footer').css("marginTop")) + parseInt($('#footer').css("marginBottom")) +
parseInt($('#footer').css("paddingTop")) + parseInt($('#footer').css("paddingBottom");

var contentHeight = window.innerHeight-headerSpace-contentSpace-footerSpace;


$('#content').css("height", contentHeight + "px");

</script>
</body>

    I hope this helps put you on the right path. There seems to be frustratingly little documentation out there on what WP8 does and does not support, and on workarounds for what seem to be common problems. With luck this fix has plugged one such hole.

No comments:

Post a Comment