Cross-browser iOS-style tab bar
Since starting to work with Jquery Mobile I have been looking for a more "app-like" navigation bar. There are examples abound, but most can be used on webkit-browsers only. Since I did not find a real cross-browser solution, I made one myself. I call it the bartender plugin.
- based on JQM elements
- CSS-only, no Jquery needed
- tested on IE7+, latest FF, Opera, Chrome, Safari, Android, iOS
- retina icons on all browsers except IE7-8
- single retina-regular or separate sprites
- All CSS-gradients
Below you can find a walkthrough on how to setup the plugin. If you have the icon cut-outs it's pretty much copy & paste.
All files can be found on Github, including icon-background templates and minified CSS.
If you are using Jquery Mobile, just copy & paste the CSS and add a class of apple-navbar-ui plus a class of comboSprite (retina-regular combined sprite) or soloSprite (separate sprites & media query) to the navbar <ul> element. In the CSS change the data-icon="names" and replace the sprite URL(s) with your own. That's it. If you want to use bartender on a stand-alone basis, make sure your <ul> has the following (JQM-rendered) element structure (you will still need some of JQM-CSS from both the containing divs):
<div class="ui-footer"> <div> <ul class="apple-navbar-ui comboSprite"> <li> <a class="ui-btn"> <span class="ui-btn-inner"> <span class="ui-btn-text"><span class="ui-li-count"></span></span> <span class="ui-icon"></span> </span> </a> </li> </ul> </div> </div>
As all gradients are CSS-made, you can change the gradient colors to fit your specific page theme. Matching to JQM data-themes is on my Todo list.
Since I don't think there is a way to stop IE-filters linear-gradients running across an element's full height, ui-icon has to be "wasted" for IE7+8.
Setting the outmost <div>'s background to black and ui-icon height to 50% takes care of IE7+8. The button backgrounds for all other browsers are inserted using pseudo-element ::before, which is placed above .ui-icon and is thankfully ignored by both IE7 (:before) and IE8 ( ::before).
I figured this out using Nicolas Gallaghers "Multiple Backgrounds and Borders" article, which helped me understand how to properly use pseudo-elements ::before and ::after as well as Reinhard von der Waydbrinks "Linear and Radial Gradients for all Browsers Script", which I found to be an excellent source on how to get gradients on all browsers - especially IE.
For idle and hover-active state you will need to attach two gradient backgrounds to ui-btn. While the idle gradient is straightforward, the hover-active background is difficult, as it's using multiple linear and radial background-images, color-stops and transparency.
Too much for IE7+8, who get a plain linear gradient with transparency. All other browser are working smoothly - except for Opera, which supports multiple background-images with linear gradients only. Once you add a radial gradient the whole background breaks. There is a fallback .png image provided, but since some browsers load this although not being necessary, the fallback is commented out to not fire an unwanted http-request.
Credits for the gradients go to Jordan Dobsons iOS Tab Bar with Webkit Gradients for his excellent walkthrough on how to mimic the iOS active gradient with plain webkit-CSS (I still needed forever for all the other browsers) and to CSS3Please! for showing how to get opacity into IE-filter. The current gradients aren't perfect. Feel free to chip in and make them closer to the original.
Button Text and Hover Gradient
As the Icon background required the <a> ui-btn to be shrunk to 30x30px, the clickable area needs to be reset. This is done using ui-btn-text, which has to be expanded to full button size and therefore also holds the :hover gradient. Here you need the only CSS-"Hack", as IE9 renders both the RGBA and MS-filter background resulting in stacked transparent gradients (20%+20% = looks bad). I found the "Dummy-Hack" solution on Stack Overflow.
Unfortunately only webkit supports -webkit-mask-image, so a cross browser solution needs to be set-up differently. The way to go for me are "cut-out" png-icons (think stamping cookies out of dough and keeping the dough). This works great across all browsers - including IE.
Of course you cannot simply cut-out icons from a plain background, because the icon background needs to match the gradient button background previously assigned to ui-icon. If you can live with the current button backgrounds simply download the templates from Github and start cutting your icons. If you make your own button-background, you will also need to redraw the icon-background accordingly.
To see how it works - for this page, the plain icon background looks like this:
And the finished cut-out with a background image to show the effect:
There is also a nice way of putting "retina-icons" on non-retina devices. If you define an element being 30x30px and then specify a background with background-size 60x60px you are basically loading retina resolution into normal browsers with an artificial 2:1 ratio. Works on all browsers that support the background-size property, which are all but IE7 and IE8. Zoom in to the following two images to see the difference.
Combo "retina-regular" or seperate sprites
You can put both the retina and regular CSS sprite into a single png image. This way you can serve hi-res icons to all browsers except IE7+8, which get lo-res icons from the same sprite. To do so you need to add a class of comboSprite to the navbar <ul> element.
Alternatively you can use CSS media-queries (like JQM does) to check for retina and then serve the respective sprite. Here you need to add a class of soloSprite. Both ways are included in the CSS and translate to a single HTTP request, so if you want good cross-browser looks you will have a few KB extra file size.
The icon positioning is also straightforward, although it still needs some tweaking. IE7+8 ignore background-size and render correctly by default. All other browsers get the artifical ratio and background-position-x/y. IE9+ is still 1px off, any clues on how to get the navbar to render correctly are welcome.
The sprite is attached to ui-btn-inner. Putting it all together:
Notifiers and Coming Soon
You can also use the JQM class of ui-li-count to add count bubbles, which are CSS-ed into notifier icons. The bubbles expand automatically depending on included text and as the background is a gradient CSS, too, you can tweak the colors according to your desired theme as well.
And there it is, the bartender-plugin.
You can grab the template and sample sprites from Github. I'm planing to add some more features to the plugin (make it scrollable to carry more buttons, look at stick-2-top/left/right, so make sure to fork the bartender or check back to see how things are coming along. Please post issues, suggestions and such on Github.