> HW Accelerated Accordion

thumb-accordion

Accordion on mobile webkit is a bad beast. The accordion effect is usually obtained by reducing/incrementing the elements height. Unfortunately, on mobile, height and width are two not hardware accelerated properties, which means choppy animations. Fear not: I just baked for you a translations-only height-changes-free accordion for all your mobile needs.


Project info

Last code update: 2010.08.20 – v1.0
Device compatibility: iPhone/Ipod touch >=2.0, Android >=1.5, iPad.
QR Code opens demo page.

Support development

If this script saved your day or you wish to support future developments you may consider sending some funds via PayPal.





Overview

Coding this widget has been tricky. The code itself is pretty simple (5kb un-minified), the hard part was to find the right mix of HTML and styles to make the magic happens. Please consider that the code is still rough on the edges but it works and I decided to publish it as is to get the community feedback and suggestions. The script seems now pretty stable and ready for production. I’ll probably add the load-with-opened-panel feature in v1.1.

The script uses just CSS “translate” to open the panels, so we are sure that the hardware acceleration is triggered.

How it works

Using the accordion is a piece of cake.

The HTML structure must be as follow (sorry for the extra mark-up, if you have better solutions, please share):

<div id="accordion">
	<div>
		<div>Title</div>
		<div>Content</div>
	</div>
	...
</div>

All you have to do is to creare a new accordion on DOMReady or on window load:

var myAccordion;
function loaded() {
	myAccordion = new accordion('accordion');
}
document.addEventListener('DOMContentLoaded', loaded, false);

'accordion' is the element ID. There’s a bunch of CSS needed by the script, it’s all included in the example.

As an added feature you can have the page to scroll to the opened panel. This can be useful on small screen (ie: everything but iPad), so the clicked panel is always on focus.

Eg:

new accordion('accordion', true);   // Force scrolling to the opened panel

Future development

As I said the script is pretty rough. The first thing to add is the possibility to load the accordion with an opened panel. Also having a version that lets you open multiple panels would be nice.

Revisions history

v1.0, 2010.08.20 – Bug fixes
v1.0 beta 1, 2010.08.15 – Initial release

/Share the joy

/Reactions

  • Looking great, Matteo! :)

    Regarding the extra markup, have you considered using definition lists?

    Reply
    • yes, initially I used DLs, but each title+description has to be wrapped inside a div and as far as I know dt and dd can’t be wrapped.

      Reply
    • Right, gotcha. Bummer. :(

      I am guessing ULs also won’t work?

      Reply
    • Same problem. I have to wrap each title/description pair.

      Reply
    • Author: James
    • Posted on: 2010/08/16
    • At: 05:36

    Can I ask how GhostTouch is going? It looked great in the video! I like how it doesn’t have a dependency on jQuery, for optimal speed. Although saw your post on supporting jQuery mobile and that could also be great with everyones help.

    Reply
    • I don’t know which direction I will take. Jquery mobile is a long way to go I suppose, while the basic ghosttouch is almost ready. I suspect that targeting so many devices will force the dev team to have a “core” as big as desktop jquery (but it seems that nobody cares). Also could be a real pain for plugin developers to make add-ons compatible with –say– windows mobile.
      If I’ll like jquerymobile I may just start developing plugins for it, if it becomes bloated I’ll continue my own way.

      Reply
    • Author: Erik
    • Posted on: 2010/08/17
    • At: 16:59

    Matteo,

    I’m with you on the jQuery Mobile thing. They say they’re just adding the fixes to the core “desktop” jQuery. Not a tactic I agree with. Keep going with GhostTouch, there’s more than enough space in the market for a good, lightweight, focused framework.

    Reply
    • As far as I understand it will be more of a mobile UI than a dedicated framework. Not what I expected/wished.

      Reply
    • Author: justin
    • Posted on: 2010/08/28
    • At: 22:24

    Trying to use your accordion script inside of an iscroll with some interesting results. Have you played around with this, do you have any pointers?

    Reply
    • I’m doing just translations so there shouldn’t be big conflicts with iScroll. If it doesn’t work, maybe a refresh at the end of the accordion animation is needed.

      Reply
      • Author: Sam
      • Posted on: 2011/03/15
      • At: 18:26

      “I’m doing just translations so there shouldn’t be big conflicts with iScroll. If it doesn’t work, maybe a refresh at the end of the accordion animation is needed.”

      How do you bind to the accordion animation to initiate a scroll refresh?

      Reply
    • Author: moni
    • Posted on: 2010/10/18
    • At: 23:31

    Hi Matteo,
    thanks for this and iScroll. A version that allows multiple expands and a case where certain fields can start open would be really great.

    @justin, I’ve demoed using this and iscroll together – no problems at all. Just add the .js, the initialization code, the css and add the appropriate html in the body and you’re golden.

    Reply
      • Author: Sophiya
      • Posted on: 2011/07/15
      • At: 11:39

      Plz give me the code if u have as at my end it’s not workin

      Reply
    • Author: pedro
    • Posted on: 2010/12/02
    • At: 17:43

    this is not workin on opera and firefox browsers :( anybody can hellp me fixes this ?

    Reply
    • Accordion is based around Webkit exclusively – you’ll have to look around for a different solution for Opera and FireFox. Why WebKit only? It’s designed for iPhone / iPad / Android, etc. mobile platforms, not desktop machines.

      Reply
      • Because desktop platforms already have accordion solutions. This is a very tricky-hacky way to have it working on mobile

  • Speeding up HW Accelerated Accordion (Part 1)

    I’ve got a project that’s got a lot of sections for the accordion to parse, and inside of each section is quite a bit of extra layout stuff. It was taking as long as four seconds for all the layout stuff to be done and the page to display on an iPad. Hrm.

    So, part 1 is for people who are supporting iOS and Android (part 2 breaks Android), particularly when using PhoneGap.

    First, in accordion.js, comment out:
    /* that.wrappers[i].style.webkitTransitionProperty = ‘-webkit-transform’;
    that.wrappers[i].style.webkitTransitionTimingFunction = ‘cubic-bezier(0,0,0.25,1)’;
    that.wrappers[i].style.webkitTransitionDuration = ’0′; */ (lines 35 – 37)

    And

    /* accordions[i].style.webkitTransitionProperty = ‘-webkit-transform’;
    accordions[i].style.webkitTransitionTimingFunction = ‘cubic-bezier(0,0,0.25,1)’;
    accordions[i].style.webkitTransitionDuration = ’0′; */

    In your CSS under #accordian > div add:

    -webkit-transition-property: -webkit-transform;
    -webkit-transform-duration: 0;
    -webkit-Transition-Timing-Function: cubic-bezier(0,0,0.25,1);

    and under #accordion > div > div:last-child add the same bit.

    You won’t get a HUGE speed burst, but you’ll get a bit extra out of it – it’s 6 extra style assignments in the javascript that doesn’t have to happen (everybit counts). This reduced my load time from about 4 seconds to just over 2 seconds.

    Reply
  • Speeding up HW Accelerated Accordion (Part 2)

    Now, if you’re not worried about Android, or can do separate compiles for iOS and other platforms (for instance, using PhoneGap rather than loading from a website, or if you can do platform dependent includes), then there’s a second speed boost you can pull off that’s more significant.

    And I’ll make sure this is clear :-) THIS ONLY WORKS ON iOS AND BREAKS ANY NON-3D ACCELERATED WEBKIT PLATFORM. (There, that made me feel better. ;-)

    First, do everything that’s described in part 1. Then…

    Comment out:
    // accordions = document.querySelectorAll(‘#’ + el + ‘ > div > div:last-child’); (Line 30)

    // that.wrappers[i].style.webkitTransform = translateOpen + ’0,0′ + translateClose; (line 38)

    /* for (i=0, l=accordions.length; i div and #accordion > div > div:last-child

    Now load time for my complex page goes from just over 2 seconds to instant. :-)

    The translate3d bit is what breaks Android – no 3d transform for the webkit version. Sorry. However, if you’re compiling using PhoneGap or similar, you can always make two CSS files and just include the right one in each project, and use the non-3D transform for other platforms besides iOS.

    Hope that helps anyone who’s ran into some slowdown before! :-)

    Reply
    • Oops – a piece got dropped.

      /* for (i=0, l=accordions.length; i div and #accordion > div > div:last-child

      Should read as lines 49 – 45 in accordion.js.

      Reply
    • Looks like I missed a second piece in my description… sheesh.

      In your CSS under #accordion > div and #accordion > div > div:last-child, add:

      -webkit-transform = translate3d(0,0,0);

      Reply
    • thank you Midnight for your contribution. I think I’ll update this script soon.

      Reply
    • Author: ProCom
    • Posted on: 2011/02/20
    • At: 15:00

    Hello

    Is it possible to integrate an RSS feed to this script.

    What is the method?

    Reply
    • Author: Fred
    • Posted on: 2011/03/01
    • At: 21:19

    Hi,
    As you mentioned in ‘Future Development’, it would be nice to open multiple panels. Do you plan it for a very close future ?

    Reply
    • Author: amimenu.es
    • Posted on: 2011/05/05
    • At: 08:07

    Here you have an absolute fan! Congratulation for all of your plugins, really GREAT!

    Reply
    • Author: Mahesh Awati
    • Posted on: 2011/07/22
    • At: 18:35

    Hi,any update on load the accordion with an opened panel?

    Reply
      • Author: Viktor
      • Posted on: 2011/09/07
      • At: 16:13

      Great work!

      I’m also eager to see this functionality.

      Reply
    • Author: Parker
    • Posted on: 2011/12/01
    • At: 09:25

    Thanks for this! I’m having one issue though :(

    I’m using this accordion with JQTouch and everything works great if I put the code on the front/welcome div. However, if I put it in another div (JQTouch navigates to divs on one page), it only shows me the last header :( Any ideas?

    I’m hoping a good solution would be to put this in an external ajax file, but I’m too much of a n00b to go that direction right away. Thanks so much!

    Reply
      • Author: Samuel
      • Posted on: 2012/03/05
      • At: 12:21

      Hey Parker, I experience the same problem! Did you fixed it ? Or Matteo, do you have any idea why this problem occurs ?

      Reply
        • Author: Keith
        • Posted on: 2012/03/28
        • At: 22:28

        I’m experiencing the same issue. If I’m unable to solve it, I may look for another library, or fork this.

      • Author: Richard Murphy
      • Posted on: 2013/02/15
      • At: 06:07

      Actually just solved it.

      Find the following in the JS file:
      top += that.wrappers[i].offsetHeight;

      And change it to (or whatever size you want):
      top += 48;

      that.wrappers[i].offsetHeight is always 0 unless the accordion is being shown initially (not in a hidden div).

      Great accordion!

      Reply
        • Author: Felipe Pini
        • Posted on: 2013/03/01
        • At: 16:14

        Must change:
        fullHeight+= that.handles[i].offsetHeight;
        to
        fullHeight+= 48;
        too

    • Author: Tony
    • Posted on: 2011/12/04
    • At: 09:46

    Vital request! I need the accordion to close after clicking a link. JQTouch navigates within sections of one page. If an accordion remains open, any time I navigate back to that page, the transition glitches. So, having the option of the accordion collapsing after a link is clicked would be amazing. Hope to hear back from you soon!

    Reply
    • Author: Pascal
    • Posted on: 2012/01/05
    • At: 18:56

    First: I really love your work!
    But it seems like this accordion is partially broken on Android: if you open and close some of the elements it scrolls automatically down so you have to scroll up again

    Reply
    • Author: Pitto
    • Posted on: 2012/04/04
    • At: 17:20

    Italians do it better!

    Great work.

    Reply
    • Author: Lewinzki
    • Posted on: 2012/04/05
    • At: 15:35

    Load with opened panel

    Hi guys,
    you can open a panel by simulating a click event after the accordion is created. You can do something like this:


    // the first parameter is the title-div of the panel to open (simply change the id to your accordion-div's id). eventFire(document.getElementById("accordion").firstChild.firstChild, "click");

    function eventFire(el, etype){
    if (el.fireEvent) {
    (el.fireEvent('on' + etype));
    } else {
    var evObj = document.createEvent('Events');
    evObj.initEvent(etype, true, false);
    el.dispatchEvent(evObj);
    }
    }

    Reply
    • Author: Matt
    • Posted on: 2012/04/19
    • At: 06:20

    How do you keep other panels open once clicked? and only close when you click on the header, so take away the auto collapsing after clicking on another header.

    Thanks!

    Reply
    • Author: Avi
    • Posted on: 2012/06/28
    • At: 22:20

    I’m using this script on zlango.com (check out the page on a mobile device and then click “FAQs”, thanks!) and have the following issue:

    iPhone 4 and Galaxy S are fine but
    iPhone 4s and Galaxy SII and SII have issues. Any way to modify the code so it looks good on all mobile devices? Thanks!

    Reply
    • Author: Mike
    • Posted on: 2012/07/21
    • At: 01:02

    Hi, can you incorporate this html5 page into an iOS app? If you can how would you do this? Having some trouble and it would be really neat if i could do an accordion feature.

    If there is an alternative way, can someone reply to my post?

    Thanks

    Reply
    • Author: Doug
    • Posted on: 2012/07/31
    • At: 19:39

    Does anyone know how to make the expandable bars a bit smaller?

    Reply
    • Author: Randy
    • Posted on: 2012/09/19
    • At: 23:53

    Hey. Love your work. Im having an issue with collapsing the accordion. When you click on an open pane to close it, the content starts to contaminate other panes. This is also happening in your live demo. Any thoughts?

    Reply
    • probably the script needs a revision, it has been developed on iOS3 or 4 and things are moving fast

      Reply
    • Author: Randy
    • Posted on: 2012/09/20
    • At: 02:58

    Update: Strange, but once i inspect the rogue element with safari, it fixes the problem. Do I need to do some sort of refresh after the close animation? If so how would I go about doing that? I’ve tried .trigger(‘create’) to no avail.

    Reply
    • Author: Jason
    • Posted on: 2012/09/26
    • At: 11:09

    Hi, this is not working for me with firefox15.blah or Firefox mobile. The formatting is not applied and it doesn’t re-collapse after each click.

    Does Work under default browser on Galaxy s3.
    Does Work under desktop Chrome21.blah

    Reply
    • Author: kit
    • Posted on: 2012/11/19
    • At: 18:37

    does anyone know how to keep it from pushing the open container up to the top?

    Reply
    • Author: pinca george
    • Posted on: 2012/12/10
    • At: 11:04

    can I use iscroll inside your accordion ?

    Reply

/Leave a reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>