This is usually a first problem every jQuery Mobile developers stumbles upon. Every jQuery Mobile page can hold one or more data-role elements (header, content and footer). Since jQuery Mobile 1.2 header and footer and fixed elements, you may or may not use them. On the other hand, content is one element you will always want to use, basically almost everything you need to show must be placed inside a content.
 
Now comes the fun part. If header and footer are fixed you would think that content covers rest of available space. And you would be wrong. In some cases, this is not a problem, but what if you want to add a background image to content div or you want to apply a theme background gradient all over the available space.
 
Empty content div height is 0 and it will stretch vertically only to cover its inner (child) content. I don’t have information why jQuery Mobile developer choose this solution mainly because there are several easy solutions to this problem, some CSS only and some that combine CSS and javascript.
 
 

Note: If this tutorial was helpful, need further clarification, something is not working or do you have a request for another Ionic post? Furthermore, if you don't like something about this blog, if something is bugging you, don't like how I'm doing stuff here, again leave me a comment below. I'm here to help you, I expect the same from you. Feel free to comment below, subscribe to my blog, mail me to dragan.gaic@gmail.com, or follow and mention me on twitter (@gajotres). Thanks and have a nice day!

PS. If you want my help, if possible (even if it takes you some time to do that), create a working example I can play with. Use Plunker for AngularJS based questions or jsFiddle for jQuery/jQuery Mobile based questions.


 

Solution 1 – Pure CSS

 
As always there’s a solution to every problem. If we have a good idea how our page is going to look we can force content div to resize according to available space even before pageshow event. This can be done with this CSS rules:
 
#content {
    padding: 0;
    position: absolute !important; 
    top : 40px !important;  
    right : 0; 
    bottom : 40px !important;  
    left : 0 !important;     
}
 
This CSS will remove classic content padding and absolutely position content div to cover all available space, giving only some space to a page header. Bottom rule can be changed to 40px in case footer is also needed. Keyword !important is also needed because we want to enforce new values over old ones.
 
Working jsFiddle example can be found here: http://jsfiddle.net/Gajotres/hJVuM/
 
<!DOCTYPE html>
<html>
    <head>
        <title>jQM Complex Demo</title>
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.css" /> 
        <script src="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.js"></script>  
        <style>
            #content {
                padding: 0;
                position : absolute !important; 
                top : 40px !important;  
                right : 0; 
                bottom : 40px !important;  
                left : 0 !important; 
                background-image:url('http://images4.fanpop.com/image/photos/14700000/Sweet-puppy-with-bunny-puppies-14749075-1600-1200.jpg');    
            }
        </style>
        <script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>   
    </head>
    <body>
        <div data-role="page" id="index">
            <div data-theme="a" data-role="header">
                <h3>
                    First Example Header
                </h3>
            </div>
            
            <div data-role="content" id="content">

            </div>
            
            <div data-theme="a" data-role="footer" data-position="fixed">
                <h3>
                    First Example Footer
                </h3>
            </div>
        </div>
    </body>
</html>    
 
 
This solution works with every jQuery Mobile version from 1.2 up to 1.4.2 (current version). I never tested it on older versions and you should stay away from them.
 

Solution 2 – CSS/Javascript Mix

 
Unfortunately, the first solution will not be useful every time. If you are using a modified version of jQuery Mobile (be it by yourself or someone else) sometimes page dimensions will not match usual values so we can’t rely on pure CSS solution. This is where jQuery comes to help.
 
Here’s a nifty function that will calculate available content height. It can be then used to dynamically set new content height. That combined with window resize event will give you best responsiveness.
 
function getRealContentHeight() {
	var header = $.mobile.activePage.find("div[data-role='header']:visible");
	var footer = $.mobile.activePage.find("div[data-role='footer']:visible");
	var content = $.mobile.activePage.find("div[data-role='content']:visible:visible");
	var viewport_height = $(window).height();

	var content_height = viewport_height - header.outerHeight() - footer.outerHeight();
	if((content.outerHeight() - header.outerHeight() - footer.outerHeight()) <= viewport_height) {
		content_height -= (content.outerHeight() - content.height());
	} 
	return content_height;
}
 
And here’s also a working jsFiddle example: http://jsfiddle.net/Gajotres/5Qu6P/
 
<!DOCTYPE html>
<html>
<head>
    <title>jQM Complex Demo</title>
    <meta name="viewport" content="initial-scale=1, maximum-scale=1"/>
    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.css" /> 
    <style>
	#content {
		padding: 0 !important;
		background-image:url('http://images4.fanpop.com/image/photos/14700000/Sweet-puppy-with-bunny-puppies-14749075-1600-1200.jpg');    
	}
    </style>
    <script src="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.js"></script>  
    <script>
	$(document).on('pageshow', '#index',function(e,data){   
		$('#content').height(getRealContentHeight()); 
	});

	function getRealContentHeight() {
		var header = $.mobile.activePage.find("div[data-role='header']:visible");
		var footer = $.mobile.activePage.find("div[data-role='footer']:visible");
		var content = $.mobile.activePage.find("div[data-role='content']:visible:visible");
		var viewport_height = $(window).height();

		var content_height = viewport_height - header.outerHeight() - footer.outerHeight();
		if((content.outerHeight() - header.outerHeight() - footer.outerHeight()) <= viewport_height) {
			content_height -= (content.outerHeight() - content.height());
		} 
		return content_height;
	}
    </script>
</head>
<body>
    <div data-role="page" id="index">
        <div data-theme="a" data-role="header">
            <h3>
                First Page
            </h3>
        </div>

        <div data-role="content" id="content">

        </div>

        <div data-theme="a" data-role="footer" data-position="fixed">
            <h3>
                First Page
            </h3>
        </div>
    </div>
</body>
</html>     
 
 
This approach also suffers from several unique problems:
 
  • jQuery Mobile versions 1.3 + have additional 1px added to header and footer so you will need to modify top function to accommodate this difference. Just subtract 1px from header and footer variables. jQuery Mobile 1.2 and below don’t suffer from this problem. To be honest I didn’t know about this problem until my friend Omar told me about it. Omar is also jQuery Mobile developer so you should visit his jQuery Mobile related blog.

  • Second problem is related to how jQuery Mobile works. Correct page height can only be calculated during pageshow event (this is related to all jQuery Mobile versions up to 1.4.2, 1.5 will come with different set of page events so I don’t want to speculate) so have that on mind, for reference take a look at attached jsFiddle example.
 

Who Am I?

Between working as a senior Java developer in one of the largest insurance companies in the world and traveling, in my free time, I work as a professional mobile development adviser. I'm also a major jQuery Mobile supporter back at StackOverflow and a forum moderator at the official Ionic Framework forum.

Blogs worth reading

If you're here looking for information related to the Ionic Framework, you will also like these blogs:






  • Peter

    Hi, it was very useful, but I can’t find a solution to whole page background. Not just for the content, but the body? In that case the page stretch the background during transition…

    • Try googling your problem but limit it to stackoverflow only, I know there should by several answers.

      • Peter

        I tried… I’ve been trying to solve the issue for months now, but there is no perfect solution. I can get this to work beautifully on desktops, but on iPad something always goes wrong…
        – If I add an image tag to the body (the best solution so far) works but there are issues with image ratio.
        – if I add the image as css to the body, it will stretch to 200% width during the page change transition..
        – if I add a div to the body and set the image as a css background and position fixed ,either the content not scrollable, scrolling sluggish, or the image stays in the same place during scrolling and jumps to the correct place when the scroll finished, so not perfect. No solution… :S