I was studying various CSS accordions and found that better ones are built using CSS3; as expected, they didn’t work in Internet Explorer. More noticeably, they didn’t even degrade properly. This was mainly due to use of CSS3 “:target” pseudo class to open accordion panels.

So why every CSS3 accordion I came across used “:target” pseudo class. There are two main reasons: opening an accordion with a click (“target”) is much better than opening it on mouse over (“hover”); and it provides RESTful URLs for each panel. Sounds like solid reasons – but there are serious drawbacks, which can’t be overlooked:
We will be using CSS3 to add transition effect and you can even add other cool CSS3 features like gradients, font-face, etc to jazz it up. But the main structure and behavior will be written in cross-browser CSS that will work in IE7+ and all other modern browsers.
Our accordion will degrade to an unordered list in IE6 (which will be completely untouched by our CSS). You can use conditional CSS to style unordered list for IE6 or older browsers however you like.
Note:

Note:

Note:
CSS3 transition effect is currently available in Safari, Chrome and Opera. It will soon be available on Firefox with version 3.7. IE7 and IE8 will continue to display CSS accordion without any transition effect.
The above lines of code will add gradient effect to panel heads in all browsers
(including IE7 & 8) except for Opera. We also need to add gradient effect to panel
heads, when mouse is over the panel (i.e., li:hover>h3). To achieve this add following
CSS3 and IE filters:
Note: you can also add a background image here to display gradient effect,
which will also work in Opera and older browsers. In this case you may also get rid
of IE filters.
Note:
sources
So why every CSS3 accordion I came across used “:target” pseudo class. There are two main reasons: opening an accordion with a click (“target”) is much better than opening it on mouse over (“hover”); and it provides RESTful URLs for each panel. Sounds like solid reasons – but there are serious drawbacks, which can’t be overlooked:
- May Cause Usability Nightmare
Unless your accordion is always above the fold and user cannot scroll your page; pure CSS accordions using “target” will cause usability nightmare by jumping to top with every click. - Not Ready For Production Environment
CSS3 “:target” pseudo class is not yet supported in any version of Internet Explorer – which occupies big share of web browser market. This fact simply means we cannot use these CSS3 accordions in production.
Lets Build Our Own
So lets build our own CSS3 accordion that should work on all modern browsers and degrade gracefully for less fortunate ones. To achieve this we will use “hover” instead of “target”.We will be using CSS3 to add transition effect and you can even add other cool CSS3 features like gradients, font-face, etc to jazz it up. But the main structure and behavior will be written in cross-browser CSS that will work in IE7+ and all other modern browsers.
Our accordion will degrade to an unordered list in IE6 (which will be completely untouched by our CSS). You can use conditional CSS to style unordered list for IE6 or older browsers however you like.
Accordion Markup
Nothing much here, we are going to use simple markup that is self explanatory:01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 | <div class="verticalaccordion"><ul> <li> <h3>Heading 1</h3> <div>Content For Panel 1.</div> </li> <li> <h3>Heading 2</h3> <div>Content For Panel 2</div> </li> <li> <h3>Heading 3</h3> <div>Content For Panel 3.</div> </li> <li> <h3>Heading 4</h3> <div>Content For Panel 4</div> </li></ul></div> |
- Each “li” element inside unordered list represents a panel
- Each “h3” element inside a list item represents panel head
- Each “div” element inside a list item represents panel content
Styling Accordion Structure
With our markup all ready, it is fairly easy to style the structure. Take a look at following CSS – it will create an accordion with all its panels collapsed:01 02 03 04 05 06 07 08 09 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 | .verticalaccordion>ul { margin: 0; padding: 0; list-style:none; width: 500px;}.verticalaccordion>ul>li { display:block; overflow: hidden; margin: 0; padding: 0; list-style:none; height:40px; width: 500px; /* Decorative CSS */ background-color:#f0f0f0;}.verticalaccordion>ul>li>h3 { display:block; margin: 0; padding:10px; height:19px; /* Decorative CSS */ border-top:#f0f0f0 1px solid; font-family: Arial, Helvetica, sans-serif; text-decoration:none; text-transform:uppercase; color: #000; background: #cccccc;}.verticalaccordion>ul>li>div { margin:0; overflow: auto; padding:10px; height:220px;} |

Note:
- Child Combinators
I have purposely used child combinators to make sure that CSS applies only to the elements used in creating accordion structure and not inherited by elements that are used in accordion content. - Default State: Panels
Since we are not using “:target” pseudo class, we are not able to specify accordion’s state. That’s why we have to set all panels in collapsed state by default. This is done by setting height of “li” equal to the height of “h3” elements (i.e., total height of each panel is equal to the height of its head). Overflow in “li” is set to hide, so that “div” element containing the content is not visible by default. - Default State: Panel Head
There is not much to note here except that total height of “h3” element is calculated by adding height, padding-top, padding-bottom and height of the border (if any). - Panel Content
For panel content “div”, you may want to note that overflow is set to “auto”. This will add scrolling bar(s) if content doesn’t fit inside the content area. Total height (height + padding-top + padding-bottom) of the content area is determined by using this formula: accordion-height - (number-of-panels x height-of-panel-head).
Styling Accordion Behavior
As discussed earlier, our accordion will respond when mouse is moved over it using “hover”. Adding following CSS will do the trick:01 02 03 04 05 06 07 08 09 10 11 12 13 | .verticalaccordion>ul>li:hover { height: 280px;}.verticalaccordion:hover>ul>li:hover>h3 { /* Decorative CSS */ color:#fff; background: #000000;}.verticalaccordion>ul>li>h3:hover { cursor:pointer;} |

Note:
- Opening Panel With Hover
In order to add behavior to our accordion – all we need to do is increase height of the Panel (“li” element) when mouse is moved over it. Panel height is determined by using this formula: accordion-height – ((number-of-panels – 1) x height-of-panel-head). - Highlighting Current Panel Head
We have highlighted current or open panel by changing the background property of the “h3” element when mouse moves over “li”. It is important to do this on “li:hover” instead of “h3:hover”, because you want to highlight panel head even mouse is hovering over its content. - Changing Mouse Pointer
Since we are not using anchors, we have changed mouse pointer using CSS when mouse hovers over “h3” element.
Adding Transition Effect
By adding structure and behavior, we have successfully created pure CSS vertical accordion. It looks and works perfectly in all modern browsers including IE7+. Now its time to use CSS3 to do something that is not possible with older versions of CSS. The most essential CSS3 feature that we need to add is transition effect. Lets just do it, by adding following style to our panels (i.e., “li” element):1 2 3 4 | transition: height 0.3s ease-in-out;-moz-transition: height 0.3s ease-in-out;-webkit-transition: height 0.3s ease-in-out;-o-transition: height 0.3s ease-in-out; |
Sprinkling Little Bit of Additional CSS3 Magic
You can add several other CSS3 effects like border-radius, text-shadow, font-face,etc to enhance the accordion. To get you started, here is some CSS3 that will add gradient effect to the panel head (i.e., “h3” element):1 2 3 4 | background: -moz-linear-gradient( top, #999999, #cccccc);background: -webkit-gradient(linear, left top, left bottom, from(#999999), to(#cccccc));filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff999999, endColorstr=#ffcccccc); /* IE 7 */-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff999999, endColorstr=#ffcccccc)"; /* IE 8 */ |
(including IE7 & 8) except for Opera. We also need to add gradient effect to panel
heads, when mouse is over the panel (i.e., li:hover>h3). To achieve this add following
CSS3 and IE filters:
1 2 3 4 | background: -moz-linear-gradient( top, #454545, #000000);background: -webkit-gradient(linear, left top, left bottom, from(#454545), to(#000000));filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff454545, endColorstr=#ff000000); /* IE 7 */-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff454545, endColorstr=#ff000000)"; /* IE 8 */ |
which will also work in Opera and older browsers. In this case you may also get rid
of IE filters.
Complete Code
That’s it – we are done. This is how complete CSS file will look like:01 02 03 04 05 06 07 08 09 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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | .verticalaccordion>ul { margin: 0; padding: 0; list-style:none; width: 500px;}.verticalaccordion>ul>li { display:block; overflow: hidden; margin: 0; padding: 0; list-style:none; height:40px; width: 500px; /* Decorative CSS */ background-color:#f0f0f0; /* CSS3 Transition Effect */ transition: height 0.3s ease-in-out; -moz-transition: height 0.3s ease-in-out; -webkit-transition: height 0.3s ease-in-out; -o-transition: height 0.3s ease-in-out;}.verticalaccordion>ul>li>h3 { display:block; margin: 0; padding:10px; height:19px; /* Decorative CSS */ border-top:#f0f0f0 1px solid; font-family: Arial, Helvetica, sans-serif; text-decoration:none; text-transform:uppercase; color: #000; background: #cccccc; /* CSS3 Gradient Effect */ background: -moz-linear-gradient( top, #999999, #cccccc); background: -webkit-gradient(linear, left top, left bottom, from(#999999), to(#cccccc)); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff999999, endColorstr=#ffcccccc); /* IE 7 */ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff999999, endColorstr=#ffcccccc)"; /* IE 8 */}.verticalaccordion>ul>li>div { margin:0; overflow: auto; padding:10px; height:220px;}.verticalaccordion>ul>li:hover { height: 280px;}.verticalaccordion:hover>ul>li:hover>h3 { /* Decorative CSS */ color:#fff; background: #000000; /* CSS3 Gradient Effect */ background: -moz-linear-gradient( top, #454545, #000000); /* FF, Flock */ background: -webkit-gradient(linear, left top, left bottom, from(#454545), to(#000000)); /* Safari, Chrome */ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff454545, endColorstr=#ff000000); /* IE 5.5 - IE 7 */ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff454545, endColorstr=#ff000000)"; /* IE 8 */}.verticalaccordion>ul>li>h3:hover { cursor:pointer;} |
- You must specify DOCTYPE in your web page in order for this CSS to work in IE.
- You can have more than one Accordion in a single page. If they have different properties, you can simply copy the above code, give different class name, and change the properties.
- If number of panels are different from our example, you will need to adjust “height” properties in the CSS accordingly.
- This accordion uses CSS “hover” and works with a mouse. (Point added after reading concerns in comments below – Sorry for taking this point for-granted)
Cross Browser Pure CSS3 Vertical Accordion
0 comments:
Post a Comment