Creating an iOS-like back button using CSS3 without images is an interesting challenge. It gets tricky when you try to do it within the boundaries of jQuery Mobile 1.1.0. To get started, let’s consider a basic HTML code for a jQuery Mobile page with a simple back button located inside the header:
1 2 3 4 5 6 7 8 9 | <div data-role="page" id="main"> <div data-theme="c" data-role="header"> <h3> Header </h3> <a href="#" data-role="button" data-rel="back" data-icon="arrow-l">Back</a> </div> <div data-role="content"></div> </div> |
<div data-role="page" id="main"> <div data-theme="c" data-role="header"> <h3> Header </h3> <a href="#" data-role="button" data-rel="back" data-icon="arrow-l">Back</a> </div> <div data-role="content"></div> </div>
When the page is done loading, jQuery Mobile auto-magically modifies the structure of the back button. It adds new elements to accommodate and generate borders and shadows that look really professional.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <!-- original button --> <a href="#" data-role="button" data-rel="back" data-theme="a" data-icon="arrow-l" > Back </a> <!-- modified button --> <a href="#" data-role="button" data-rel="back" data-theme="a" data-corners="true" data-shadow="true" data-iconshadow="true" data-wrapperels="span" class="ui-btn-left ui-btn ui-shadow ui-btn-corner-all ui-btn-up-a" > <span class="ui-btn-inner ui-btn-corner-all"> <span class="ui-btn-text"> Back </span> <span class="ui-icon ui-icon-arrow-l ui-icon-shadow"> </span> </span> </a> |
<!-- original button --> <a href="#" data-role="button" data-rel="back" data-theme="a" data-icon="arrow-l" > Back </a> <!-- modified button --> <a href="#" data-role="button" data-rel="back" data-theme="a" data-corners="true" data-shadow="true" data-iconshadow="true" data-wrapperels="span" class="ui-btn-left ui-btn ui-shadow ui-btn-corner-all ui-btn-up-a" > <span class="ui-btn-inner ui-btn-corner-all"> <span class="ui-btn-text"> Back </span> <span class="ui-icon ui-icon-arrow-l ui-icon-shadow"> </span> </span> </a>
As you can see the trickiness comes from the fact that we have to add a point to the left side of the button. This point should use the same background as the button without relying on any bitmap image. I am sure there are many ways to accomplish this task. For the purpose of this article I will take the following steps:
When we assign a custom theme to a button, jQuery Mobile generates several CSS classes that allow us to modify the different states of the button. In this example I will assign a custom theme named app-ios which will expose the following CSS classes: ui-btn-up-app-ios; ui-btn-hover-app-ios; and ui-btn-down-app-ios.
1 | <a data-role="button" data-rel="back" data-icon="arrow-l" data-theme="app-ios">Back</a> |
<a data-role="button" data-rel="back" data-icon="arrow-l" data-theme="app-ios">Back</a>
To remove the icon we can simply select the .ui-icon element and remove it from the DOM. In addition to this, we will have to add an element to render the point. The goal is to create a small square and apply a gradient to it. We will also need to scale it and re-position it on the left side of the button.
1 2 3 4 5 | // Javascript code to manipulate the DOM $(document).ready(function(){ $('a[data-theme="app-ios"]').find('.ui-icon').remove(); $('a[data-theme="app-ios"]').append('<div class="ios-tip"><span> </span></div>'); }); |
// Javascript code to manipulate the DOM $(document).ready(function(){ $('a[data-theme="app-ios"]').find('.ui-icon').remove(); $('a[data-theme="app-ios"]').append('<div class="ios-tip"><span> </span></div>'); });
Now that we have the modified structure we can start applying CSS rules to make the default button theme look like an iPhone button.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | /* button background and borders color */ a[data-theme="app-ios"] { border: none; } a[data-theme="app-ios"] .ui-btn-corner-all { border: 1px solid rgba(0,0,0, 0.4); -webkit-border-radius: 5px; background: -webkit-gradient(linear, left top, left bottom, from(#9fb3cc), to(#5b80ab), color-stop(0.5, #6b8bb2), color-stop(0.51, #597eaa)); -webkit-box-shadow: 0 1px 0 rgba(255,255,255, 0.25), inset 0 1px 1px rgba(0,0,0, 0.2); overflow: visible; padding-left: 8px !important; padding-right: 8px !important; } /* shadows and label color */ a[data-theme="app-ios"].ui-shadow, a[data-theme="app-ios"] { box-shadow: none; -moz-box-shadow: none; -webkit-box-shadow: none; background-clip: none; -webkit-background-clip: none; -moz-background-clip: none; color: white; font-weight: bold; top: 5px; text-decoration: none; text-shadow: 0 -1px 0 rgba(0,0,0, 0.4); } |
/* button background and borders color */ a[data-theme="app-ios"] { border: none; } a[data-theme="app-ios"] .ui-btn-corner-all { border: 1px solid rgba(0,0,0, 0.4); -webkit-border-radius: 5px; background: -webkit-gradient(linear, left top, left bottom, from(#9fb3cc), to(#5b80ab), color-stop(0.5, #6b8bb2), color-stop(0.51, #597eaa)); -webkit-box-shadow: 0 1px 0 rgba(255,255,255, 0.25), inset 0 1px 1px rgba(0,0,0, 0.2); overflow: visible; padding-left: 8px !important; padding-right: 8px !important; } /* shadows and label color */ a[data-theme="app-ios"].ui-shadow, a[data-theme="app-ios"] { box-shadow: none; -moz-box-shadow: none; -webkit-box-shadow: none; background-clip: none; -webkit-background-clip: none; -moz-background-clip: none; color: white; font-weight: bold; top: 5px; text-decoration: none; text-shadow: 0 -1px 0 rgba(0,0,0, 0.4); }
This is now looking like an iPhone button –nice!– but we still have to render the point. To do so I will apply a gradient to the span tag inside the div container. I will also apply rotation and scale effects to the container itself using CSS transformation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | /* make room for the point */ a[data-theme="app-ios"].ui-btn-left { left: 14px; } a[data-theme="app-ios"].ui-btn-left .ui-btn-corner-all { padding-left: 5px !important; } /* position the DIV that contains the point */ a[data-theme="app-ios"] .ios-tip { float: left; left: -9px; top: 4px; position: absolute; -webkit-transform: scale(.7, 1.0); } /* apply gradient */ a[data-theme="app-ios"] .ios-tip span { display: block; width: 18px; height: 18px; border: 2px solid rgba(0,0,0, 0.4); border-right: 0; border-top: 0; /* the gradient color mus be slightly different since the point is within the body of the button */ background: -webkit-gradient(linear, left top, right bottom, from(#94a8c2), to(#5b80ab), color-stop(0.5, #6b8bb2), color-stop(0.51, #597eaa)); border-radius: 1px; -webkit-border-radius: 1px; -moz-border-radius: 1px; box-shadow: 0 1px 0 rgba(255,255,255, 0.25); -webkit-box-shadow: 0 1px 0 rgba(255,255,255, 0.25); -moz-box-shadow: 0 1px 0 rgba(255,255,255, 0.25); -webkit-transform: rotate(45deg) scale(.9, .9); } |
/* make room for the point */ a[data-theme="app-ios"].ui-btn-left { left: 14px; } a[data-theme="app-ios"].ui-btn-left .ui-btn-corner-all { padding-left: 5px !important; } /* position the DIV that contains the point */ a[data-theme="app-ios"] .ios-tip { float: left; left: -9px; top: 4px; position: absolute; -webkit-transform: scale(.7, 1.0); } /* apply gradient */ a[data-theme="app-ios"] .ios-tip span { display: block; width: 18px; height: 18px; border: 2px solid rgba(0,0,0, 0.4); border-right: 0; border-top: 0; /* the gradient color mus be slightly different since the point is within the body of the button */ background: -webkit-gradient(linear, left top, right bottom, from(#94a8c2), to(#5b80ab), color-stop(0.5, #6b8bb2), color-stop(0.51, #597eaa)); border-radius: 1px; -webkit-border-radius: 1px; -moz-border-radius: 1px; box-shadow: 0 1px 0 rgba(255,255,255, 0.25); -webkit-box-shadow: 0 1px 0 rgba(255,255,255, 0.25); -moz-box-shadow: 0 1px 0 rgba(255,255,255, 0.25); -webkit-transform: rotate(45deg) scale(.9, .9); }
With this final addition we can see the point on the left of the button. Now let’s put everything together.
CSS code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | /* button background and borders color */ a[data-theme="app-ios"] { border: none; } a[data-theme="app-ios"] .ui-btn-corner-all { border: 1px solid rgba(0,0,0, 0.4); -webkit-border-radius: 5px; background: -webkit-gradient(linear, left top, left bottom, from(#9fb3cc), to(#5b80ab), color-stop(0.5, #6b8bb2), color-stop(0.51, #597eaa)); -webkit-box-shadow: 0 1px 0 rgba(255,255,255, 0.25), inset 0 1px 1px rgba(0,0,0, 0.2); overflow: visible; padding-left: 8px !important; padding-right: 8px !important; } /* shadows and label color */ a[data-theme="app-ios"].ui-shadow, a[data-theme="app-ios"] { box-shadow: none; -moz-box-shadow: none; -webkit-box-shadow: none; background-clip: none; -webkit-background-clip: none; -moz-background-clip: none; color: white; font-weight: bold; top: 5px; text-decoration: none; text-shadow: 0 -1px 0 rgba(0,0,0, 0.4); } /* make room for the point */ a[data-theme="app-ios"].ui-btn-left { left: 14px; } a[data-theme="app-ios"].ui-btn-left .ui-btn-corner-all { padding-left: 5px !important; } /* position the DIV that contains the point */ a[data-theme="app-ios"] .ios-tip { float: left; left: -9px; top: 4px; position: absolute; -webkit-transform: scale(.7, 1.0); } /* apply gradient */ a[data-theme="app-ios"] .ios-tip span { display: block; width: 18px; height: 18px; border: 2px solid rgba(0,0,0, 0.4); border-right: 0; border-top: 0; /* the gradient color mus be slightly different since the point is within the body of the button */ background: -webkit-gradient(linear, left top, right bottom, from(#94a8c2), to(#5b80ab), color-stop(0.5, #6b8bb2), color-stop(0.51, #597eaa)); border-radius: 1px; -webkit-border-radius: 1px; -moz-border-radius: 1px; box-shadow: 0 1px 0 rgba(255,255,255, 0.25); -webkit-box-shadow: 0 1px 0 rgba(255,255,255, 0.25); -moz-box-shadow: 0 1px 0 rgba(255,255,255, 0.25); -webkit-transform: rotate(45deg) scale(.9, .9); } |
/* button background and borders color */ a[data-theme="app-ios"] { border: none; } a[data-theme="app-ios"] .ui-btn-corner-all { border: 1px solid rgba(0,0,0, 0.4); -webkit-border-radius: 5px; background: -webkit-gradient(linear, left top, left bottom, from(#9fb3cc), to(#5b80ab), color-stop(0.5, #6b8bb2), color-stop(0.51, #597eaa)); -webkit-box-shadow: 0 1px 0 rgba(255,255,255, 0.25), inset 0 1px 1px rgba(0,0,0, 0.2); overflow: visible; padding-left: 8px !important; padding-right: 8px !important; } /* shadows and label color */ a[data-theme="app-ios"].ui-shadow, a[data-theme="app-ios"] { box-shadow: none; -moz-box-shadow: none; -webkit-box-shadow: none; background-clip: none; -webkit-background-clip: none; -moz-background-clip: none; color: white; font-weight: bold; top: 5px; text-decoration: none; text-shadow: 0 -1px 0 rgba(0,0,0, 0.4); } /* make room for the point */ a[data-theme="app-ios"].ui-btn-left { left: 14px; } a[data-theme="app-ios"].ui-btn-left .ui-btn-corner-all { padding-left: 5px !important; } /* position the DIV that contains the point */ a[data-theme="app-ios"] .ios-tip { float: left; left: -9px; top: 4px; position: absolute; -webkit-transform: scale(.7, 1.0); } /* apply gradient */ a[data-theme="app-ios"] .ios-tip span { display: block; width: 18px; height: 18px; border: 2px solid rgba(0,0,0, 0.4); border-right: 0; border-top: 0; /* the gradient color mus be slightly different since the point is within the body of the button */ background: -webkit-gradient(linear, left top, right bottom, from(#94a8c2), to(#5b80ab), color-stop(0.5, #6b8bb2), color-stop(0.51, #597eaa)); border-radius: 1px; -webkit-border-radius: 1px; -moz-border-radius: 1px; box-shadow: 0 1px 0 rgba(255,255,255, 0.25); -webkit-box-shadow: 0 1px 0 rgba(255,255,255, 0.25); -moz-box-shadow: 0 1px 0 rgba(255,255,255, 0.25); -webkit-transform: rotate(45deg) scale(.9, .9); }
CSS code:
1 2 3 4 5 6 | $(document).ready(function(){ // make sure we only add the point the back buttons var backButton = $('a[data-theme="app-ios"]').filter('[data-rel="back"]'); backButton.find('.ui-icon').remove(); backButton.append('<div class="ios-tip"><span> </span></div>'); }); |
$(document).ready(function(){ // make sure we only add the point the back buttons var backButton = $('a[data-theme="app-ios"]').filter('[data-rel="back"]'); backButton.find('.ui-icon').remove(); backButton.append('<div class="ios-tip"><span> </span></div>'); });
Here is a final example of a page with a back button and non-back buttons:
Not registered? Create an Account.
Lost your password? Click here to recover.
Create, customize, and publish mobile web applications using the Appcropolis Mobile Builder.
Get StartedWe offer 1,000's of mobile templates that are fully designed, coded, and ready to use. Learn more.
Download Free Templates
I tried using the css and html+js that you show in this page, but I get an extra blue quadrilateral superimposed and the icon inserted by jquery mobile does not go away. Can you post the exact html file you used for the demo (not the image that you put in the page). I think there may be some jQueryMobile versioning problem. Is this compatible with jqm 1.2?
Gary, We will be updating all articles and templates to jQuery Mobile 1.2 in the coming weeks. Thanks in advance for your patience. --Raul
When you update for jqm 1.2, can you also post the css for the background of the header bar and the font information for the header bar title. thx
Hey.. this is trick on jquery touch css???
The concepts and techniques used in this article can certainly be applied to other frameworks. However, the scope of this tutorial is jQuery Mobile.
Awesome tutorial. Exactly what I needed for my next project. Thanks for sharing.
Has anyone tried this with jQuery Mobile 1.3.1? This is exactly what I'm looking for, but it doesn't seem to be working on my app.
Hi Ron, This article will be updated shortly to be compatible with jQM 1.3.1. If you visit the Appcropolis Builder you will find an new code example that addresses this issue using CSS only. Please check out http://appcropolis.com/builder/ --Thanks for your feedback