Styling a group of checkboxes as a dropdown via CSS and JavaScript

The following demonstrates how to create a dropdown list based on a list of checkbox elements. You can view a complete example of how this works at the following fiddle: http://jsfiddle.net/Terkildsen/mTSLa/

In the following I will walk you through the code.

First, I start by creating the HTML:

    <div class="dropdown">
        Choose city
        <ul class="dropdown-list">
            <li>
                <label>
                    <input type="checkbox" value="Vejle" name="city" />Vejle</label></li>
            <li>
                <label>
                    <input type="checkbox" value="Horsens" name="city" />Horsens</label></li>
            <li>
                <label>
                    <input type="checkbox" value="Kolding" name="city" />Kolding</label></li>
            <li>
                <label>
                    <input type="checkbox" value="Fredericia" name="city" />Fredericia</label></li>
        </ul>
    </div>

There’s not much to say about the HTML above. I use a “dropdown” div to contain the entire dropdown – including the default text that is displayed when the checkbox list is hidden. I then assign a “dropdown-list” class to the list of checkboxes.

Then, I start styling the dropdown:

.dropdown {
    width: 200px;
    border: 1px solid silver;
    cursor: pointer; /* use correct mouse pointer when hovering over the dropdown */
    padding: 10px;
    position: relative;
    margin: 0 auto;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

In the CSS above I start by styling the entire dropdown. I provide the dropdown with a width of 200px, some padding and a border to make the dropdown resemble a normal select-list.

Notice that the usage of the “user-select: none;” prevents the user from accidentally highlighting the text in the dropdown.

/* Display CSS arrow to the right of the dropdown text */
.dropdown:after {
    content:'';
    height: 0;
    position: absolute;
    width: 0;
    border: 6px solid transparent;
    border-top-color: #000;
    top: 50%;
    right: 10px;
    margin-top: -3px;
}

Instead of inserting an image to display an arrow in order to indicate that this dropdown can be clicked on, I use a small CSS-trick that will display an arrow using a border-property. You can read more about how this is done in the following blogpost: https://pterkildsen.com/2012/09/16/creating-arrows-using-css/

/* Reverse the CSS arrow when the dropdown is active */
.dropdown.is-active:after {
    border-bottom-color: #000;
    border-top-color: #fff;
    margin-top: -9px;
}

When the user activates the dropdown, the CSS above reverses the direction of the CSS-arrow. It does this by applying the white background-color to the “border-top-color”-property so that this part of the border is hidden, and then displays the bottom part of the border by assigning a black color to the “border-bottom-color”-property.

.dropdown-list {
    list-style: none;
    margin: 0;
    padding: 0;
    position: absolute;
    top: 100%; /* align the dropdown right below the dropdown text */
    border: inherit;
    border-top: none;
    left: -1px; /* align the dropdown to the left */
    right: -1px; /* align the dropdown to the right */
    opacity: 0; /* hide the dropdown */
    -webkit-transition: opacity 0.4s ease-in-out;
    -moz-transition: opacity 0.4s ease-in-out;
    -o-transition: opacity 0.4s ease-in-out;
    -ms-transition: opacity 0.4s ease-in-out;
    transition: opacity 0.4s ease-in-out;
    pointer-events: none; /* avoid mouse click events inside the dropdown */
}

I then style the list of checkboxes. There are a couple of important issues here. First of all, I use the “opacity”-property to hide and display the checkbox-list. And secondly, I use the “pointer-events: none” to prevent click events from happening in the checkbox-list – which would accidentally hide it.

.is-active .dropdown-list {
    opacity: 1; /* display the dropdown */
    pointer-events: auto; /* make sure that the user still can select checkboxes */
}

The is-active class is applied to the checkbox-list whenever the user clicks on the “dropdown-selector”. This class displays the checkbox-list by setting the “opacity”-property to 1 and it also makes sure that the user still can select the checkboxes by setting “pointer-events: auto;”

.dropdown-list li label {
    display: block;
    border-bottom: 1px solid silver;
    padding: 10px;
    -webkit-transition: all 0.2s ease-out;
    -moz-transition: all 0.2s ease-out;
    -o-transition: all 0.2s ease-out;
    -ms-transition: all 0.2s ease-out;
    transition: all 0.2s ease-out;
}

.dropdown-list li label:hover {
    background-color: #c41230;
    color: white;
}

And then finally, I just add some finishing touches to the labels inside the checkbox-list.

In order for this to work, I add a couple of lines of jQuery:

         $(function () {
            $(".dropdown").click(function () {
                $(this).toggleClass("is-active");
            });

            $(".dropdown ul").click(function (e) {
                e.stopPropagation();
            });
        });

The code above detects the click event on the “dropdown”-div – which will toggle the “is-active” class. It also captures the click-event on the list of checkboxes in order to make sure that this doesn’t accidentally close the dropdown.

This code has been tested in Internet Explorer 9+, the latest version of Mozilla Firefox and Google Chrome. I have also tested it on iPhone and iPad. Seems to be working just fine. However, please notice that I’ve had some issues with jsfiddle and Internet Explorer. The code works fine without jsfiddle, though.

CSS performance

Do you ever wonder about the performance of using CSS-reset? Well, until today I didn’t either.

I’m currently in the middle of implementing a new webapp based on AngularJS. We’re implementing extremely complicated swipe-functionality in this webapp, and this presents us with huge performance difficulties – especially on older tablets and smartphones. My old iPad 1 is having a very hard time trying to keep up with the demands.

That’s why I was investigating and debugging performance bottlenecks today.

I used Google Developer Profiler tool to investigate both the JavaScript and the CSS performance on the site. And to my surprise one of the most important performance issues was the usage of a universal CSS-reset matching all elements in the DOM. As you can see in the picture below, the reset uses a lot of processing power. (click on the image in order to view it properly)

CSS_reset_performance

The picture displays the result of a profiling being made of a single swipe. The consequence is that each time a user swipes, the tablet has to do all this rendering over and over again – which makes the screen flicker and gives the end-user a very poor experience. In fact, a single swipe would result in the desktop browser spending as much as 79 ms to render.

The solution to this – of course – is to make the reset more specific. Instead of matching the * selector – match tags. The result of this was that I went from a render time of 79 ms to 20 ms. I know that this is not much – but these measurements were done on my desktop PC with all its processing power. The effect was noticeable when I loaded the site on my iPad 1 – and the end-user will appreciate this simple fix.

CSS3 columns in Internet Explorer 7, 8 and 9

Maybe you already know that CSS3 enables texts to be rendered and flowed automatically in columns in order to obtain a newspaper-like formatting of texts. Just like so:

Diagram-css3multicolumnThe CSS for this is extremely simple:

.column {
    -moz-column-count: 5;
    -moz-column-gap: 20px;
    -ms-column-count: 5;
    -ms-column-gap: 20px;
    -webkit-column-count: 5;
    -webkit-column-gap: 20px;
    column-count: 5;
    column-gap: 20px;
}

In the above CSS, column-count expresses the number of columns the text should be flowed into, and the column-gap expresses the number of pixels between each column.

This approach is extremely simple, and everything would be sweet and wonderful – if it weren’t for the fact that this doesn’t work in Internet explorer 7, 8 or 9. It works fine in IE10, Chrome, Safari and Firefox, but sadly people are still using IE 8 and 9, so we need to accommodate these poor souls.

Luckily, there is a workaround. You can use the following JavaScript-file to obtain exactly the same behavior in Explorer: http://www.csscripting.com/css-multi-column/.

However, if you use just this script, you will get into trouble. It doesn’t work in IE8, and the following blog post explains why: http://blog.gabrielsaldana.org/css3-columns-in-internet-explorer-and-other-unsupported-browsers/. Gabriel Saldaña has created a fix, and you can download it from his blog: Download fix for CSS3 multiple column script

Now, you just link to this script AFTER you include your CSS-file. Just like so:

    <link rel="stylesheet" href="/twitterbootstrap/css/bootstrap-responsive.min.css">
    <link rel="stylesheet" href="/twitterbootstrap/css/main.css">
    <link href="/twitterbootstrap/css/bleau-megamenu-stylesheet.css" rel="stylesheet" type="text/css" media="screen" />

        <!--[if lt IE 10]>
          <script src="TwitterBootstrap/navigation/js/css3-multi-column.js"></script>
        <![endif]-->

The script is loaded if the browser is an Internet Explorer that is older than IE10. It will automatically parse all CSS-files, and find the relevant CSS. It will tweak your HTML in order to obtain the CSS3 column functionality. Please observe, that you have to use an external CSS-file – the script is not able to parse inline CSS.

I normally don’t like to tweak HTML-output like this – by using JavaScript after the browser has loaded all HTML and CSS. I don’t like the “flickering” that appears when the JavaScript is executed in the browser. However, if you look at the browser stats, you will notice that the usage of Internet Explorer 8 and 9 is declining, while the usage of more modern browsers are on the rise. Internet Explorer 10 is included in this. Developing for the modern browsers, while making sure that people with older browsers can still use the site, is a fine approach by me.

Thanks to Cédric Savarese for creating the original JavaScript and Gabriel Saldaña for creating and sharing a patch that works like a charm. People like those makes it so much easier to be a web developer. 🙂

Creating pure CSS-based tabs

I know! There are so many jQuery-plugins out there, that enable you to create dynamic tabs-functionality. One of the most widely used is probably jQuery UI’s tab-plugin (http://jqueryui.com/demos/tabs/). So why bother building a new one?

Well, first of all I’m experimenting a lot with CSS right now, and secondly, I wanted to build a plugin that didn’t utilize any JavaScript at all. Don’t get me wrong – I use jQuery all the time, and I’m a big fan of it. But I want to create UI’s that download and respond extremely fast. Adding one or two jQuery plugins to a page normally doesn’t present a problem, but when you’re working with very rich and dynamic user interfaces, you often need to add several different plugins. Which means that the user will have to download lots of files, and the browser needs to perform a lot of rendering. If you can replace JavaScript with CSS, you can improve performance of the website, and you will improve the user experience.

I searched for a solution to this problem, and I found that the CSS :target pseudo-class could help me out. It is a part of the CSS3-specification and it enables you to create CSS that will respond to the part of a URL that comes after a “#”. You could – for example – create CSS that would respond to the “tab1” in the following URL: https://pterkildsen.com/2012/09/24/creating-pure-css-based-tabs#tab1.

I could write HTML like this:

<section id="tab1">
<h2>
                    <a href="#tab1">Tab 1</a></h2>
                <img src="Images/blue river scenery wallpapers.jpg" alt="" /></section>

And then CSS like this:

section:target h2
{
    color: #FFF;
    background-color: #e21414;
}

The code above will change the font- and the background color of the section with the id of “tab1” when a user enters the URL https://pterkildsen.com/2012/09/24/creating-pure-css-based-tabs#tab1.

This little trick makes it very easy for us to create tabs-functionality. I have provided a small example in the following:

The HTML:

<article class="tabs"><section id="tab1">
<h2>
                    <a href="#tab1">Tab 1</a></h2>
                <img src="Images/blue river scenery wallpapers.jpg" alt="" /></section><section id="tab2">
<h2>
                <a href="#tab2">Tab 2</a></h2>
                <img src="Images/farnsworth-landscaping-firebowl5.jpg" alt="" /></section><section id="tab3">
<h2>
                <a href="#tab3">Tab 3</a></h2>
                <img src="Images/Moonlit_Landscape.jpg" alt="" /></section><section id="tab4">
<h2>
                <a href="#tab4">Tab 4</a></h2>
                
</section><section id="tab5"> <h2> <a href="#tab5">Tab 5</a></h2> <img src="Images/Moonlit_Landscape.jpg" alt="" /></section> </article>

And the CSS:

article.tabs section:target h2
{
    color: #FFF;
    background-color: #e21414;
    background: #F15931;
    background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2YxNTkzMSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNkNDM0MGEiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
    background: -moz-linear-gradient(top,  #F15931 0%, #D4340A 100%); /* FF3.6+ */
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#F15931), color-stop(100%,#D4340A)); /* Chrome,Safari4+ */
    background: -webkit-linear-gradient(top,  #F15931 0%,#D4340A 100%); /* Chrome10+,Safari5.1+ */
    background: -o-linear-gradient(top,  #F15931 0%,#D4340A 100%); /* Opera 11.10+ */
    background: -ms-linear-gradient(top,  #F15931 0%,#D4340A 100%); /* IE10+ */
    background: linear-gradient(to bottom,  #F15931 0%,#D4340A 100%); /* W3C */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#F15931', endColorstr='#D4340A',GradientType=0 ); /* IE6-8 */
}

article.tabs section h2
{
    color: #F15B33;
    background: #eeeeee;
    background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2VlZWVlZSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNjY2NjY2MiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
    background: -moz-linear-gradient(top,  #eeeeee 0%, #cccccc 100%); /* FF3.6+ */
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#eeeeee), color-stop(100%,#cccccc)); /* Chrome,Safari4+ */
    background: -webkit-linear-gradient(top,  #eeeeee 0%,#cccccc 100%); /* Chrome10+,Safari5.1+ */
    background: -o-linear-gradient(top,  #eeeeee 0%,#cccccc 100%); /* Opera 11.10+ */
    background: -ms-linear-gradient(top,  #eeeeee 0%,#cccccc 100%); /* IE10+ */
    background: linear-gradient(to bottom,  #eeeeee 0%,#cccccc 100%); /* W3C */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#cccccc',GradientType=0 ); /* IE6-8 */
}

/* CSS to handle images and videoes in tabs content */
article.tabs section:target p
{
    opacity: 1;
}

article.tabs section p
{
    opacity: 0;
    -webkit-transition: opacity 1s ease-in-out;
    -moz-transition: opacity 1s ease-in-out;
    -o-transition: opacity 1s ease-in-out;
    -ms-transition: opacity 1s ease-in-out;
    transition: opacity 1s ease-in-out;
}

The code mentioned above is very simple. It really defines two different states for the same HTML-elements, and the matching will be based on the id of the HTML-element and the part of the URL that is after the “#”. Therefore, you can create an “active” state and a “passive” state – defined by the :target-class.

Of course, there is a lot more to the tabs-functionality than just this. But this is the most important part – the rest is primarily styling and layout. However, there are two more important things that you need to be aware of.

First of all, if you just implement the code mentioned above, you will run into a problem. You probably don’t want your users to type a difficult URL consisting of hash tags – you want the URL to be as simple as possible. But that would mean that the CSS wouldn’t be able to display the active tab – as it would have no information as to what should be the active tab.

Therefore, you need to inform the CSS by using the following JavaScript, that will append the necessary information to the URL (yeah, I know….it’s JavaScript….):

    <script type="text/javascript">
        window.location.hash = '#tab1'
    </script>

Secondly, this tabs-functionality will not work in Internet Explorer 7 and 8. I have decided that I won’t optimize for Internet Explorer 7 and I’m waiting for the day when I can declare proudly that I won’t optimize for IE8 either. Meanwhile, there’s a solution in the form of a JavaScript-library called Selectivizr (http://selectivizr.com/). This library enables CSS3 pseudo-classes in IE7 and IE8 – however, the :target pseudo-class in Selectivizr only works in IE8.
I know that using this library will add additional JavaScript-overhead to your project – however, you can isolate the problem to those sad people using Internet Explorer by inserting the following lines of code:

<!--[if (gte IE 6)&(lte IE 8)]>
  <script type="text/javascript" src="selectivizr.js"></script>
<![endif]-->

That’s it! This new world of CSS3 continues to amaze me. 🙂

UPDATE! Why you can’t just use plain CSS!

So, I encountered one very difficult obstacle trying to implement the code above into a real life scenario. The problem is that the code above works just fine – as long as the tabs are placed at the top of the page! If you don’t place the tabs at the top, you will observe a scrolling behaviour whenever you click each tab. Not pretty, but still the default behaviour of the a tag. So nothing odd there.

I tried several approaches in order to solve this problem. One possible approach was to prevent the default behaviour of the a-tag whenever the user clicked a tab – but to no success. I therefore ended up implementing a small jQuery JavaScript to make it work. I know that this kinda ruins the idea of implementing a ‘pure’ CSS3 based tabs functionality, but I simply wasn’t able to accomplish it otherwise. I use this blog to document my findings and this time I learned that it’s not possible to create a pure CSS-based tabs-functionality without scroll. If you know how to do it, please don’t hesitate to let me know – for now, I think that the JavaScript below is a very small JavaScript-footprint.

Here’s the code for the jQuery-snippet:

    <script type="text/javascript">
      $(function() {
        $('article.tabs section div h2 a').click(function(e) {
          $('article.tabs li').removeClass("target");
          $(this).parent().parent().parent().addClass("target");
          e.preventDefault();
        });
      });
    </script>

Also, please read my new findings about handling Youtube-videos in tabs: https://pterkildsen.com/2012/09/22/fade-one-image-into-another-via-css/

Fade one image into another via CSS

Currently, I’m in the process of creating my new pure CSS-based tabs-functionality. This functionality is based on the CSS :target pseudo-class, and it replaces the JavaScript/jQuery-based tabs I’m used to.


Now, as a finishing touch I wanted the image to the right to fade in and out each time the user clicks a tab. Luckily, this can also be accomplished with pure CSS, and the approach is supported by almost every modern browser. Internet Explorer 8 doesn’t support it – but those users will just have to live without the fade-feature.

/* CSS to handle images and videoes in tabs content */
article.tabs section:target p
{
    /*display: block;*/
    opacity: 1;
}

article.tabs section p
{
    /*    display: none;*/
    opacity: 0;
    -webkit-transition: opacity 1s ease-in-out;
    -moz-transition: opacity 1s ease-in-out;
    -o-transition: opacity 1s ease-in-out;
    -ms-transition: opacity 1s ease-in-out;
    transition: opacity 1s ease-in-out;
}

/* CSS to handle images and videoes in tabs content */

The code displayed above is pretty straightforward for those of you working with CSS, but it’s just plain revolutionary to me. 🙂 I’m still amazed of the fact that I don’t have to rely on some heavy JavaScript-library to accomplish a feature that looks great and performs amazingly. I use the opacity property to either hide or display the image, and then I use the transition property to enable the fade in and out animation. Of couse, you can control the animation type and length by adjusting the “1s ease-in-out”.

I’m still new to several of the CSS3-methods but I’ll keep on investigating, and I’ll keep on using this blog to document my findings.

UPDATE! Handling Youtube-videos in tabs

It seems that the solution described above had some problems. The problem is that if I don’t use ‘display:none’ and ‘display:block’ to switch between the images, but instead use ‘opacity: 0’ and ‘opacity: 1’ I can’t display Youtube-videos in my tabs. The problem is that the Youtube-video is in an Iframe, and therefore the video will always be on top of every other image – even though the video isn’t displayed. This means that even though a user thinks that the clicks the image being displayed, the Youtube-video will still start.

The obvious solution to this problem would be to switch back to using ‘display:none’ and ‘display:block’. Which works just fine – but then there’s no animation when the user switches between the tabs!

I investigated this problem further – and found a lot of different approaches. Some suggested using ‘visibility:hidden’ and ‘visibility:visible’ – which enabled the animation, but didn’t work with Youtube-videos – and some suggested using CSS3 keyframes. Still some suggested that I adjusted the height of the tabs by using ‘height: 0’ and ‘height: auto’.  I tried several different approaches – none of them worked.

Finally, I ended up implementing the obvious solution. I move the hidden image/Youtube-video off the screen. This works – the slider animates and I can switch between each tab. Great! 🙂

The following is the code I used:


/* CSS to handle images and videoes in tabs content */
ul.tabs li.target p
{
 opacity: 1;

 position: relative !important;
 left: 0px !important;
}

ul.tabs li p
{
 opacity: 0;

 position: absolute !important;
 left: -9999px !important;

 -webkit-transition: visibility 0s ease-in-out 1s,opacity 1s ease-in-out;
 -moz-transition: visibility 0s ease-in-out 1s,opacity 1s ease-in-out;
 -o-transition: visibility 0s ease-in-out 1s,opacity 1s ease-in-out;
 -ms-transition: visibility 0s ease-in-out 1s,opacity 1s ease-in-out;
 transition: visibility 0s ease-in-out 1s,opacity 1s ease-in-out;
}
/* CSS to handle images and videoes in tabs content */

Gradients and rounded corners in Internet Explorer

I ran into a problem today when I tried to build a new CSS tab-functionality. Gradients and rounded corners don’t go very well together in Internet Explorer, and the result of this is displayed in the following screenshot:

This screenshot is from Internet Explorer 9. As you can see, while the corners to the right works just fine, the corners to the left looks a bit “wierd”. The problem appears when you combine gradients and rounded corners in CSS3.

I searched for the solution, and I found that there were several options – I use this blog to document the different approaches:

Wrap the HTML into another div

One solution would be to wrap the current div into another. Just like this:

<div class="corners">
 <div class="gradients">my content</div>
</div>

And then adding the border-radius to the corners-class and the gradients-code to the gradients-class. Just like this:

.corners {
 border-radius: 5px;
 overflow: hidden;
}

.gradients {
 background: linear-gradient(to bottom,  #F15931 0%,#D4340A 100%);
}

This works fine in IE9 – but it doesn’t work in IE7 or IE8.

Use CSS3pie

Another solution would be to use an extension found at http://css3pie.com/. This open source project tries to add CSS3-functionality to Internet Explorer 6 – 9 by injecting code into your CSS. You can read more about how to implement this functionality in the documentation found here: http://css3pie.com/documentation/

However, after some experimentation I decided not to use this approach. The main reason for this is performance. It seems that when you inject code like this into your CSS, the performance of your website degrades – and the more you use this fix, the worse it gets.

Use SVG background-image

Finally, I ended up using a bit of a hack. You can view a much more elaborate description of this hack here: http://abouthalf.com/2010/10/25/internet-explorer-9-gradients-with-rounded-corners/

In the article Michael Barrett explains how to make use of IE9’s support for SVG background-image, and implement a minor hack by applying a filter and then remove that filter again afterwards.

There’s no need to go into much detail about how this works. Instead, I found out that the amazing tool called “Ultimate CSS Gradient Generator” has support for this approach. You can find this tool here: http://www.colorzilla.com/gradient-editor/

The tool will generate cross-browser valid CSS-code like this:

background: #f15931; /* Old browsers */
/* IE9 SVG, needs conditional override of 'filter' to 'none' */
background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2YxNTkzMSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNkNDM0MGEiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
background: -moz-linear-gradient(top, #f15931 0%, #d4340a 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f15931), color-stop(100%,#d4340a)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #f15931 0%,#d4340a 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #f15931 0%,#d4340a 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, #f15931 0%,#d4340a 100%); /* IE10+ */
background: linear-gradient(to bottom, #f15931 0%,#d4340a 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f15931', endColorstr='#d4340a',GradientType=0 ); /* IE6-8 */

This CSS will not be enough in itself. You need to add the following to the HTML – after you include the CSS:

<!--[if gte IE 9]>
  <style type="text/css">
    .gradient {
       filter: none;
    }
  </style>
<![endif]-->

This approach will enable you to use gradients and rounded corners in Internet Explorer 9, while enabling gradients (but not rounded corners) in Internet Explorer 7 and 8. I like this approach because it doesn’t affect performance, and I’m able to obtain an acceptable result. I know that this doesn’t work fully in Internet Explorer 7 and 8 – but the usage of these two browsers are 2 % and 7 % and declining. People using these browsers will have to live with squares.

And finally – the result:

Handling css :hover on iPad

As you are all well aware, there’s a mobile revolution going on right now, and this revolution has several consequences for website implementation.

I encountered one of those today. I needed to implement a mega dropdown navigation that would allow the user to hover over each element in the top navigation in order to produce a dropdown navigation. Clicking the element in the top navigation would forward the user to the page being linked to.

I created the mega dropdown navigation in pure CSS only to realize that I needed special code in order to handle users with tablets and smartphones. You can use the CSS :hover pseudo-class on tablets and smartphones, but it doesn’t work on iOS-devices.

It turned out that the solution was quite simple. You just need to detect the users’ operating environment via JavaScript, and then override the click-event. Just like this:

(function($) {
    $(document).ready(function() {
        // Emulate hover on tablets and smartphones
        if ((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) || (navigator.userAgent.match(/iPad/i))) {
            $("#menu li a").click(function() {
                return false;
            });
        }
    });
});

Thanks to Blake Petersen for the original source code.

Creating arrows using CSS

Quite often you will need to insert small arrow icons into your website in order to create something like this:

This will often be handled by creating small png-icons – one for each state. Instead, I’ve decided to implement it by using CSS. This may sound a bit fanatic, but every time the server has to download something, the user interface becomes a bit less responsive. Every time I can substitute downloads with syntax I’ll improve the user experience.

I didn’t develop this code myself. I’m just using this blog to document my work. The original code originates from this blog: http://www.yuiblog.com/blog/2010/11/22/css-quick-tip-css-arrows-and-shapes-without-markup.

/* Create arrow next to the tabs - thanks to http://www.yuiblog.com/blog/2010/11/22/css-quick-tip-css-arrows-and-shapes-without-markup/*/
article.tabs section:target h2:after {
	content: ' ';
	height: 0;
	position: absolute;
	width: 0;
	border: 15px solid transparent;
    border-left-color: #00B2E0;
	top: 20%;
	left: 100%;
}
/* Create arrow next to the tabs - thanks to http://www.yuiblog.com/blog/2010/11/22/css-quick-tip-css-arrows-and-shapes-without-markup/*/

To use this code snippet, you will need to know the following:

  • The size of the arrow is controlled by the border size. In the above it is 15 pixels. If you wanted a more “flat” arrow you could produce that by changing the dimensions, e.g. border-width: 37px 5px 37px 15px;
  • The direction of the arrow is controlled by the border-color. In the example above it says “border-left-color” which will produce an arrow pointing to the right. If you wanted an arrow pointing to the left, you would use “border-right-color” instead. And of course “border-top-color” and “border-bottom-color” produces arrows pointing down and up.

Finally, a word about browser compatibility. This snippet works in all modern browsers – including IE8. However, it doesn’t work in IE7, so in that case you would need to use the good old way.

I urge you to visit the above mentioned blog in order to learn more about how this code works.

Performance forbedringer på vej i Dynamicweb 7.2

Hvis man er vant til at arbejde med Dynamicwebs administration, så vil man sikkert også have bemærket, at administrationen kan være en tung sag at arbejde med. Masser af frames og javascript skal loades, og editoren er ret tung.

En af forklaringerne på dette er, at der eksempelvis på en side med en editor skal loades 36 javascript og CSS-filer, som alt i alt fylder 571 Kb. Hvis man har droppet at anvende caching i sin browser, så er der dermed en del, som skal downloades.

Dynamicweb ser ud til at gøre noget ved dette i version 7.2. Teknikken bag er velkendt, og opskriften er følgende:

  • Samle alle javascript og CSS-filer sammen i færre filer, så der ikke er så mange forespørgsler til serveren
  • Komprimere filstørrelsen, så der er færre Kb, der skal flyttes hen over netværket.

Samlet set reducerer dette antallet af javascript og CSS-filer til i alt 4 og antal Kb reduceres til 119. Det skal helt sikkert nok kunne mærkes.

Du kan læse mere om teknikken bag på Pavel Volgarevs blog: http://volgarev.spaces.live.com/blog/cns!A1C49A17EFB60688!178.entry