Archive for April 4th, 2010
The War Room Part 2
Cross Browser Pure CSS3 Horizontal Accordion
Just few days ago, I shared pure CSS3 vertical accordion that works in all modern browsers, including Internet Explorer. Now it is time to share its twin – a pure CSS3 horizontal accordion. It uses same markup enabling you to switch from vertical to horizontal accordion and vice versa by simply changing the class name.

We will continue to use “:hover” instead of “:target” pseudo class to cater Internet Explorer and other usability issues (You should read “Cross Browser Pure CSS3 Vertical Accordion” article to find out why we are not using “:target” pseudo class).
Lets Start
In order to support text based panel heads, we will need to rotate entire panel head to create horizontal accordion. Interestingly, we have the ability to rotate elements in Internet Explorer (using Microsoft’s BasicImage filter) for a while. Other browsers are only able to do this with CSS3 transform. Rest of the structure and behavior will be written in cross-browser CSS that will work in IE7+ and all other modern browsers.
You can add other CSS3 features like gradients, font-face, etc to enhance it further. 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
We are going to use exactly the same markup that we used to create vertical accordion:
<div class="horizontalaccordion">
<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>
Note:
* 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
Unlike vertical accordion, our horizontal accordion depends on CSS3 (transform) to complete its structure. What this means is that it will work in Internet Explorer but not in older versions of other web browsers. Luckily older versions of Firefox, Safari, Chrome and Opera have negligible market share. CSS3 transform is supported in these browsers: Firefox 3.5+, Opera 10.5+, Safari 3+ and Chrome.
Following CSS will create a horizontal accordion with all its panels collapsed:
.horizontalaccordion>ul {
margin: 0;
padding: 0;
list-style:none;
height: 300px;
}
.horizontalaccordion ul>li {
display:block;
overflow: hidden;
float:left;
margin: 0;
padding: 0;
list-style:none;
width:40px;
height: 300px;
/* Decorative CSS */
background:#f0f0f0;
}
.horizontalaccordion ul>li>h3 {
display:block;
float:left;
margin: 0;
padding:10px;
height:19px;
width:280px;
/* Decorative CSS */
border-left:#f0f0f0 1px solid;
font-family: Arial, Helvetica, sans-serif;
text-decoration:none;
text-transform:uppercase;
color: #000;
background:#cccccc;
/* CSS3 Transform Rotate & Translate */
white-space:nowrap;
-moz-transform: rotate(90.0deg) translate(-40px,0px); /* FF3.5+ */
-moz-transform-origin: 0 100%;
-o-transform: rotate(90.0deg) translate(-40px,0px); /* Opera 10.5 */
-o-transform-origin: 0 100%;
-webkit-transform: rotate(90.0deg) translate(-40px,0px); /* Saf3.1+, Chrome */
-webkit-transform-origin: 0 100%;
transform: rotate(90.0deg) translate(-40px,0px); /* Saf3.1+, Chrome */
transform-origin: 0 100%;
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1.0); /* IE6,IE7 */
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1.0)"; /* IE8 */
}
.horizontalaccordion ul>li>div {
display:none;
float:left;
overflow: auto;
position:relative;
top:-40px;
left:40px;
*top:0px; /* IE7 Hack */
*left:0px; /* IE7 Hack */
margin:0;
width:320px;
height:280px;
padding:10px;
}

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 width of “li” equal to the height (which becomes width after rotation) of “h3” elements (i.e., total width of each panel is equal to the width of its head). - Panel Head
This is the trickiest part of horizontal accordion. Note that height specified here will become width and width will become height after rotating the panel head. So the total height (which will become width after transform) of “h3” element is calculated by adding height, padding-top, padding-bottom and height of the border (if any). Transformation is done using CSS3 transform property and filter for Internet Explorer. In addition to rotating the h3 element, we are also adjusting its position using “translate” so that panel’s content area will adjust its position accordingly. - 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 width (width + padding-left + padding-right) of the content area is determined by using this formula: accordion-width - (number-of-panels x width-of-panel-head). Also note that we have to keep content panel’s position relative to its head (i.e., “h3” element) and adjust the position here as well. Since Internet Explorer 7’s behavior during transformations is different from other browsers, I have used a little hack to accommodate its position.
Styling Accordion Behavior
Now we will add behavior in our accordion using “hover”. Adding following CSS will do the trick:
.horizontalaccordion ul>li:hover {
overflow: hidden;
width: 380px;
}
.horizontalaccordion:hover ul>li:hover>div {
display:block;
}
.horizontalaccordion:hover ul>li:hover>h3 {
/* Decorative CSS */
color:#fff;
background:#000000;
}
.horizontalaccordion 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 width of the Panel (“li” element) when mouse is moved over it. Panel width is determined by using this formula: accordion-width – ((number-of-panels – 1) x width-of-panel-head). We also need to “display” content panel’s as “block” when mouse is moved its 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 horizontal accordion. It looks and works perfectly in all modern browsers including IE7+. Now to add transition effect. apply following CSS3 style to our panels (i.e., “li” element):
transition: width 0.3s ease-in-out; -moz-transition: width 0.3s ease-in-out; -webkit-transition: width 0.3s ease-in-out; -o-transition: width 0.3s ease-in-out;
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.
Complete Code
That’s it – we are done. This is how complete CSS file will look like (note: I have also added gradient effect to our panel head):
.horizontalaccordion>ul {
margin: 0;
padding: 0;
list-style:none;
height: 300px;
}
.horizontalaccordion ul>li {
display:block;
overflow: hidden;
float:left;
margin: 0;
padding: 0;
list-style:none;
width:40px;
height: 300px;
/* Decorative CSS */
background:#f0f0f0;
/* CSS3 Transitions */
transition: width 0.3s ease-in-out;
-moz-transition: width 0.3s ease-in-out;
-webkit-transition: width 0.3s ease-in-out;
-o-transition: width 0.3s ease-in-out;
}
.horizontalaccordion ul>li>h3 {
display:block;
float:left;
margin: 0;
padding:10px;
height:19px;
width:280px;
/* Decorative CSS */
border-left:#f0f0f0 1px solid;
font-family: Arial, Helvetica, sans-serif;
text-decoration:none;
text-transform:uppercase;
color: #000;
background:#cccccc;
/* CSS3 Transform Rotate & Translate */
white-space:nowrap;
-moz-transform: rotate(90.0deg) translate(-40px,0px); /* FF3.5+ */
-moz-transform-origin: 0 100%;
-o-transform: rotate(90.0deg) translate(-40px,0px); /* Opera 10.5 */
-o-transform-origin: 0 100%;
-webkit-transform: rotate(90.0deg) translate(-40px,0px); /* Saf3.1+, Chrome */
-webkit-transform-origin: 0 100%;
transform: rotate(90.0deg) translate(-40px,0px); /* Saf3.1+, Chrome */
transform-origin: 0 100%;
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1.0)
progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff999999, endColorstr=#ffcccccc); /* IE6,IE7 */
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1.0)"
"progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff999999, endColorstr=#ffcccccc)"; /* IE8 */
/* CSS3 Gradient Effect */
background: -moz-linear-gradient( top, #999999, #cccccc);
background: -webkit-gradient(linear, left top, left bottom, from(#999999), to(#cccccc));
}
.horizontalaccordion ul>li>div {
display:none;
float:left;
overflow: auto;
position:relative;
top:-40px;
left:40px;
*top:0px; /* IE7 Hack */
*left:0px; /* IE7 Hack */
margin:0;
width:320px;
height:280px;
padding:10px;
}
.horizontalaccordion ul>li:hover {
overflow: hidden;
width: 380px;
}
.horizontalaccordion:hover ul>li:hover>div {
display:block;
}
.horizontalaccordion: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.BasicImage(rotation=1.0)
progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff454545, endColorstr=#ff000000); /* IE 5.5 - IE 7 */
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1.0)"
"progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff454545, endColorstr=#ff000000)"; /* IE 8 */
}
.horizontalaccordion ul>li>h3:hover {
cursor:pointer;
}
Note:
- 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” & “width” properties in the CSS accordingly.
- CSS3 gradient effect will work in all browsers except for Opera. You can also add a background image to display gradient effect, which will also work in Opera and older browsers. In this case you can also get rid of IE filters.
- Also note that IE filters must be grouped together in order to work, otherwise only the last filter is applied. This has forced me to use rotation again on mouse over. I personally like to keep structure and behavior separate – I have therefore provided two version of the horizontal accordion in the download file: one with gradient effect for IE and another one without it.
I hope you have enjoyed this post and found it to be useful. I am looking forward to reading your feedback, opinion and suggestions.
Similar Posts:
You can also stay updated by following us on Twitter, becoming a fan on Facebook or by subscribing to our FriendFeed.
What Is Cloud Computing Exactly?
I take for granted that many folks really understand what "Cloud Computing" is. Speaking at different events and talking with clients in the fitness, wellness, franchising and other industries, I've recently become more aware that many don't truly understand what the term "Cloud Computing" means.
Its really important for people in any organization to graps the concept of the "Cloud" because it is going to touch everything in our lives and organizations, if it hasn't already started to. Catch up on the basics with this video which is an excellent and short explaination of how Virtualization, Utility Computer and Software as a Service are converging to make Cloud Computing an important aspect of the world today.
Multi-Touch enabling Silverlight Simon using Blend behaviors and the Surface sample for Silverlight
I have already blogged about using Blend behaviors to add Multi-Touch gestures and inertia effects to a generic Silverlight user control, so I wanted to use the same approach to add the same behaviors to the CodePlex project Simon.
I think that inserting multi-touch manipulation effects to a Silverlight application using Blend behaviors is an elegant way which makes the code very clear and readable.
To start you need to download the Multi-touch manipulation and inertia behavior (wow, more than 7000 downloads, great feedback!
), which I already published on the Expression site.
This behavior is based on the code available in the Microsoft Surface Manipulations and Inertia Sample for Microsoft Silverlight, in my opinion the best example available for using multi-touch in Silverlight at this time.
The solution available contains a project named “MultiTouch.behaviors.Silverlight” which must be included in your application to enable the multi-touch functionalities.
To make the Silverlight/Blend Behavior work with Simon I’ve modified some code relative to the Zoom gesture in order to use a ScaleTransform (check out the source code on CodePlex: http://simon.codeplex.com).
To use the Behavior in XAML just add a reference to the “MultiTouch.Behaviors.Silverlight” project and use the following code:
<UserControl x:Class="SimonSilverlight.MainPage"
....
xmlns:interactivity="clr-namespace:System.Windows.Interactivity; assembly=System.Windows.Interactivity"
xmlns:multitouch="clr-namespace:MultiTouch.Behaviors.Silverlight; assembly=MultiTouch.Behaviors.Silverlight">
....
<Canvas>
<uc:Simon x:Name="Says">
<interactivity:Interaction.Behaviors>
<multitouch:MultiTouchManipulationBehavior InertiaEnabled="True" TouchRotateEnabled="True"
TouchScaleEnabled="True" TouchTranslateEnabled="True"/>
</interactivity:Interaction.Behaviors>
</uc:Simon>
</Canvas>
Since we are using a Blend Behavior, we can also open the solution in Expression Blend, select the “MultiTouchManipulationBehavior” from the “Assets” section and drag it over the Simon control:
Happy Silverlighting!



