Home Blog Learn how to customize jQuery Mobile application

Learn how to customize jQuery Mobile application

     
    12
    Before I show you how to customize jQuery Mobile pages and widgets let us first discuss what is jQuery Mobile and how it works. Standard jQuery Mobile application is built from at least one page up to any number you can think of.
     
    The page is the primary unit of interaction in jQuery Mobile and is used to group content into logical views that can be animated in and out of view with page transitions. An HTML document may start with a single “page” and the AJAX navigation system will load additional pages on demand into the DOM as users navigate around. Alternatively, an HTML document can be built with multiple “pages” inside it and the framework will transition between these local views with no need to request content from the server.
     

    Page structure


     
     
    Inside a body tag each page is identified with the  data-role=”page”  attribute:
     
    <div data-role="page">
        <!-- Inner content -->
    </div>
    
     
    Inside the page container, any valid HTML markup can be used, but for typical pages in jQuery Mobile, the immediate children of a page are divs with data-roles of  header ,  content , and  footer :
     
    <div data-role="page">
        <div data-role="header">
            <!-- Inner content -->
        </div>
        <div data-role="content">
            <!-- Inner content -->
        </div>
        <div data-role="footer">
            <!-- Inner content -->
        </div>
    </div>
    
     
    This structure is what page looks like before jQuery Mobile can enhance its markup. Markup enhancement is the process that triggers after  pagecreate  page event and gives page its final look. Take a look what page looks like during the  pageinit  page event:
     
    <div data-role="page" data-url="/_display/" tabindex="0" class="ui-page ui-body-c ui-page-active" style="min-height: 498px;">
        <div data-role="header" class="ui-header ui-bar-a" role="banner">
            <!-- Inner content -->
        </div>
        <div data-role="content" class="ui-content" role="main">
            <!-- Inner content -->
        </div>
        <div data-role="footer" class="ui-footer ui-bar-a" role="contentinfo">
            <!-- Inner content -->
        </div>
    </div>
    
     
    As you can see basic page structure stayed the same, only difference is inclusion of some new classes. Every part of a page, including a page has received new  style  and  class  attributes. What I want you as a reader to do is look at new header, content and footer classes. You will need to use / change them if that proves to be a needed.
     

    How to change page look


     
     
    Lets create our first example. I will show you how to change application background color and remove content padding. First let me tell you few notes before we start. Page  data-role=”content”  will never automatically cover whole available space, unless it is filled, so instead of with content  background we will change with  page  background. This may sound as a boring and easy example (everyone can change a little bit of CSS) but bear with me, I will explain everything at the end of this chapter.
     
    CSS
     
    .ui-page {
        background: royalblue !important;
    }
    .ui-content {
        padding: 0 !important;
        background: orange !important;    
    }
    
     
    Notice the use of  !important  property. Usually its use is considered narcissistic & selfish or lazy but in our case it is only thing we can do to change those values, unless you consider changing the CSS on a framework level (never do this unless you are 100% sure what are you doing). Surprisingly a lot of web developers never hear of it, that’s why around 1/5 of jQuery Mobile related StackOverflow questions are related to the inability to successfully change page content.
     
    A working example can be found here: http://jsfiddle.net/Gajotres/LJfJF/
     
     
    CSS can also be used easily to resize page content, just use this few lines:
     
    .ui-content {
        padding: 0 !important; 
        position : absolute !important; 
        top : 40px !important;  
        right : 0 !important; 
        bottom : 40px !important;  
        left : 0 !important;     
    }
    
     
    Top and bottom should be / / 40 px depending on header / footer visibility. So use 0 if header and footer don’t exist. This is a great solution if you need clear page for Google maps implementation (article about that topic can be found here).
     

    Widgets


     
     
    All widgets begin with native form elements with rich HTML semantics that are enhanced to make them more attractive and finger-friendly. Let’s take a look how basic jQuery Mobile button looks like:
     
    <a href="#" data-role="button">Link button</a>
    
    Just like with a previously mentioned page, button structure looks different after the page markup enhancement:
     
    <a data-role="button" href="#" data-corners="true" data-shadow="true" data-iconshadow="true" data-wrapperels="span" data-theme="c" class="ui-btn ui-shadow ui-btn-corner-all ui-btn-up-c">
        <span class="ui-btn-inner">
            <span class="ui-btn-text">Link button</span>
        </span>
    </a>
    
     
    Button HTML structure has been completely redesigned. This is not all, there’s another type of button and it looks like this:
     
    <input type="button" value="Classic HTML button"/>
    
     
    This one looks a little bit different after the markup enhancement process:
     
    <div data-corners="true" data-shadow="true" data-iconshadow="true" data-wrapperels="span" data-theme="c" data-disabled="false" class="ui-btn ui-shadow ui-btn-corner-all ui-btn-up-c" aria-disabled="false">
        <span class="ui-btn-inner">
            <span class="ui-btn-text">Classic HTML button</span>
        </span>
        <input type="button" value="Classic HTML button" class="ui-btn-hidden" data-disabled="false"/>
    </div>
    
     
    It is different than the previous button example. There are two major difference here, <div> is now parent button container (previously <a> tag was the container ) and original <input> button is now hidden part of a newly formed button.
     
     
    This is a major difference. Let us give every button an id attribute. With it, we can easily change first button CSS but a second button is a mission impossible. Input tag is no more a parent element so id can’t be used to modify newly create button style. To do this we will wrap it inside an another <div> tag.
     

    How to change widget look


     
     
    Everything we talked about page modifications can also be used here, with a little twist.
     
    HTML
     
    <a href="#" data-role="button" class="custom-btn">Link button</a>
    <div id="wrapper">
        <input type="button" value="Classic HTML button"/>
    </div>
    
     
    CSS
     
    /* <a> tag button */
    .custom-btn {
        background: green !important;
    }
    .custom-btn .ui-btn-inner .ui-btn-text {
        color: #013301 !important;
    }
    /* <input> tag button */
    #wrapper .ui-btn {
        background: orange;    
    }
    #wrapper .ui-btn .ui-btn-inner .ui-btn-text {
        color: #472f01;   
    }
    
     
    Notice how second button CSS declaration is not using !important. That is because wrapper div has only an id attribute so our declaration starts with # sign. If declaration is starting with the # sign it don’t requires  !important  to override CSS rules.
     
    A working example can be found here: http://jsfiddle.net/Gajotres/eAA9Z/
     
     

    How to change widget look – Advanced example

     
    Let’s do something a little bit different, we will still play with a button widget but this time it will be more complex example.
     
    For this example, I will show you how to move button icon. This is still an easy example and it requires only one line of CSS. Our our button:
     
    <a href="#" data-role="button" class="custom-btn" data-icon="bars">Link button</a>
    
     
    First step is to look at this buttons enhanced markup:
     
    <a data-icon="bars" class="custom-btn ui-btn ui-shadow ui-btn-corner-all ui-btn-icon-left ui-btn-up-c" data-role="button" href="#" data-corners="true" data-shadow="true" data-iconshadow="true" data-wrapperels="span" data-theme="c">
        <span class="ui-btn-inner">
            <span class="ui-btn-text">Link button</span>
            <span class="ui-icon ui-icon-bars ui-icon-shadow">&nbsp;</span>
        </span>
    </a>
    
     
    If you compare this to the button from our previous example you will notice that it has one <span> element more. That precise <span> holds our icon.
     
    It also has this CSS definition:
     
    .ui-btn-icon-left .ui-icon {
        left: 10px;
    }
    
     
    This is another great and specific example. To move this button to the right it will not be enough to set new rule like this:  right: 10 !important; . Button will stay on the left side, even if we force right with  !important  rule. There are 2 distinct solutions to this problem. Java script could be used to remove that specific class  .ui-btn-icon-left , or in our case we need to reuse left so that button still moves to the right side.
     
    To do that just use large percentage number for our left definition:
     
    .custom-btn .ui-icon {
        left: 94% !important;
    }
    
     
    94% will be enough to move a button to the right. Point of this specific example was to teach you that some cases can’t be overridden, but there are always some other option, even if they requires javascript.
     
    A working example can be found here: http://jsfiddle.net/Gajotres/eAA9Z/4/
     
     

    Don’t worry about valid HTML


     
     
    jQuery Mobile developers don’t care about valid HTML markup so why would you.
     
    Let me prove that point, this is what collapsible element looks like before its content is enhanced:
     
    <div data-role="collapsible">
        <h6>Heading</h6>
        <p>I'm the collapsible content. By default, I'm closed, but you can click the header to open me.</p>
    </div>
    
     
    And this is what it looks after a markup enhancement:
     
    <div data-role="collapsible" class="ui-collapsible ui-collapsible-inset ui-corner-all ui-collapsible-collapsed">
        <h6 class="ui-collapsible-heading ui-collapsible-heading-collapsed"><a class="ui-collapsible-heading-toggle ui-btn ui-fullsize ui-btn-icon-left ui-btn-up-c" href="#" data-corners="false" data-shadow="false" data-iconshadow="true" data-wrapperels="span" data-icon="plus" data-iconpos="left" data-theme="c" data-mini="false">
            <span class="ui-btn-inner">
                <span class="ui-btn-text">Heading
                    <span class="ui-collapsible-heading-status"> click to expand contents</span>
                </span>
                <span class="ui-icon ui-icon-plus ui-icon-shadow">&nbsp;</span>
            </span>
            </a>
        </h6>
        <div class="ui-collapsible-content ui-collapsible-content-collapsed" aria-hidden="true">
    
            <p>I'm the collapsible content. By default, I'm closed, but you can click the header to open me.</p>
        </div>
    </div>
    
     
    As you can see <h6 > is filled with additional content and according to valid HTML markup this is an error. Point is, don’t care about valid HTML.
     

    Tools


     
     
    There are few tools that can make our lives much easier in this case.
     
    For Firefox browsers use  Firebug  plugin for real time HTML / CSS manipulation. It will give you a ability to see enhanced page markup, change CSS on the fly (much easier if you want to see what will happen when changes are applied without doing it manually) and copy inner HTML structure.
     
    Download Link can be found here.
     
    Chrome also has a firebug plugin but you should steer clear of it. It is a much much lighter version of Firefox firebug and at the same time Chrome has an excellent built tool called  “Developer tools” . It can be easily invoked with  CTRL + SHIFT + I  combination. My Macintosh users can open it with this combination:  Command + Option + i .
     
    My final advice would be stick with a Chrome developer tools, Firebug plugin is known for been extremely resource hungry.
     

    Table of contents

     
    This article is a part of a long lasted series where I’m discussing/offering solutions to various jQuery Mobile related problems.
     
     

    12 COMMENTS

    1. Very nice post. I was waiting for it. Thanks for sharing!!!

      I have a simple question for you. Why do you need the !important directive in the following snippet of code?

      #wrapper .ui-btn .ui-btn-inner .ui-btn-text {
      color: #472f01 !important;
      }

      There is already an identifier. Is this a typo or am I missing something else?

      Thanks.

    2. Sorry that was a big fat typo.

      It is fixed now, including the jsFiddle example.

      Thank you for your comment, I missed it completely and it is a vital point of this article.

    3. I think the approach above can be used to move elements around (e.g. the position of an icon’s button, the overflow of the text in a button, etc.). Am I wrong?

      Thank you again!!

      • Give me few hours and I will update my article with that specific information, for example how to move icon inside a button. Maybe even something more. So come back tomorrow.

    4. I’m using jquery mobile to build a website containing two accordion widgets. I want all collapsible elements in one set to be collapsed (for small-screen devices), and all collapsible elements in the other set to be expanded (for large-screen devices), based on screen width, when the page loaded.

      I’m using two classes of ‘s and based on a media-query device-width test, one or the other div’s will have display:none attribute, therefore only one of the collapsible sets will be appear. This works fine, but I also want the collapsed/expanded state of the one that is presented to be based on the screen size.

      My plan was to use a js script to modify ____ based on screen.width that would be triggered by the onload event. Can you fill in the blank for me? (I’m a novice js programmer, I’m pretty much live in the world of php which is not useful for this.)

    5. So if I copy and paste your code from http://jsfiddle.net/Gajotres/eAA9Z/ and save it locally to run it in my browser it doesn’t work any more. Obviously I uncomment out line 8 which holds “jquery-1.9.1.min.js”…what could I be doing wrong, the example is not using any external resources (it still works on jsfiddle if you remove them) what cud I be doing wrong…thank you.

    Leave a Reply


    one + one =