Making Better Select Elements with jQuery and CSS3

Beautiful AJAX Form Building Script - FormBuilder
When creating your web designs, you are always striving for a consistent look across the different browsers. Unfortunately, one of the most fundamental elements of your website – the browser controls – also prove the most difficult to style. Some of them, like the select element, are impossible to change beyond a certain extent.
This is why, today we are building a script that is going to take an ordinary select element, and replace it with a better looking, markup powered version, while keeping all the functionality intact.
Per popular demand, this script is now available as a stand-alone jQuery plugin. Read more and download the code at our Converting jQuery Code into a Plugin tutorial.

The HTML

As usual, we are start with the HTML part of the tutorial. I am using the HTML5 markup as it gives us some useful features, such as the data attributes, with which we can add arbitrary data to the markup of the page.

select-jquery.html

01
02<html>
03<head>
04<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
05<title>Making Better Select Elements with jQuery and CSS3 | Tutorialzine Demotitle>
06
07<link rel="stylesheet" type="text/css" href="css/styles.css" />
08
09head>
10<body>
11
12<div id="page">
13    <h1>Your Producth1>
14
15    <form method="post" action="">
16
17        
18
19        <select name="fancySelect" class="makeMeFancy">
20
21            
22
23            <option value="0" selected="selected" data-skip="1">Choose Your Productoption>
24            <option value="1" data-icon="img/products/iphone.png" data-html-text="iPhone 4<i>in stock</i>">iPhone 4option>
25            <option value="2" data-icon="img/products/ipod.png" data-html-text="iPod <i>in stock</i>">iPodoption>
26            <option value="3" data-icon="img/products/air.png" data-html-text="MacBook Air<i>out of stock</i>">MacBook Airoption>
27            <option value="4" data-icon="img/products/imac.png" data-html-text="iMac Station<i>in stock</i>">iMac Stationoption>
28        select>
29    form>
30
31div>
32
34<script src="js/script.js">script>
35
36body>
37html>
You can see that we are using the data attributes to embed information in the option elements of the select. We are including a product icon and a rich text description, both of which are later displayed in the improved version of the select element.
I’ve set an arbitrary data-skip attribute on the first element, so that our script knows not to include it in the generated list. You could alternatively just check for the existence of the data-icon and data-html-text attributes and skip the element if necessary.
At the bottom of the document are included version 1.4.3 of jQuery (the latest version of the library as of this writing) and our script.js, which you can see in the next step.
A Better Select Element with jQuery & CSS3
A Better Select Element with jQuery & CSS3

The jQuery

On the document.ready event, jQuery inspects the select element, and using the data attributes, constructs the markup you can see below, which is appended just after the select:
1<div style="width: 144px;" class="tzSelect">
2    <div class="selectBox">iMac Stationdiv>
3    <ul class="dropDown">
4        <li><img src="img/products/iphone.png"><span>iPhone 4<i>in stocki>span>li>
5        <li><img src="img/products/ipod.png"><span>iPod <i>in stocki>span>li>
6        <li><img src="img/products/air.png"><span>MacBook Air<i>out of stocki>span>li>
7        <li><img src="img/products/imac.png"><span>iMac Station<i>in stocki>span>li>
8    ul>
9div>
As you can see, we are basically constructing an unordered list, with a li element representing each option of the select. The select box itself is represented by a div with a .selectBox class.
Now lets take a closer look at how this code is generated.

js/script.js

01$(document).ready(function(){
02
03    // The select element to be replaced:
04    var select = $('select.makeMeFancy');
05
06    var selectBoxContainer = $('
',{
07        width       : select.outerWidth(),
08        className   : 'tzSelect',
09        html        : '
'
10    });
11
12    var dropDown = $('
    ',{className:'dropDown'});
13    var selectBox = selectBoxContainer.find('.selectBox');
14
15    // Looping though the options of the original select element
16
17    select.find('option').each(function(i){
18        var option = $(this);
19
20        if(i==select.attr('selectedIndex')){
21            selectBox.html(option.text());
22        }
23
24        // As of jQuery 1.4.3 we can access HTML5
25        // data attributes with the data() method.
26
27        if(option.data('skip')){
28            return true;
29        }
30
31        // Creating a dropdown item according to the
32        // data-icon and data-html-text HTML5 attributes:
33
34        var li = $('


  • ',{





  • 35            html:   '+option.data('icon')+'" />'+
    36                    option.data('html-text')+''
    37        });
    38
    39        li.click(function(){
    40
    41            selectBox.html(option.text());
    42            dropDown.trigger('hide');
    43
    44            // When a click occurs, we are also reflecting
    45            // the change on the original select element:
    46            select.val(option.val());
    47
    48            return false;
    49        });
    50
    51        dropDown.append(li);
    52    });
    53
    54    selectBoxContainer.append(dropDown.hide());
    55    select.hide().after(selectBoxContainer);
    56
    57    // Binding custom show and hide events on the dropDown:
    58
    59    dropDown.bind('show',function(){
    60
    61        if(dropDown.is(':animated')){
    62            return false;
    63        }
    64
    65        selectBox.addClass('expanded');
    66        dropDown.slideDown();
    67
    68    }).bind('hide',function(){
    69
    70        if(dropDown.is(':animated')){
    71            return false;
    72        }
    73
    74        selectBox.removeClass('expanded');
    75        dropDown.slideUp();
    76
    77    }).bind('toggle',function(){
    78        if(selectBox.hasClass('expanded')){
    79            dropDown.trigger('hide');
    80        }
    81        else dropDown.trigger('show');
    82    });
    83
    84    selectBox.click(function(){
    85        dropDown.trigger('toggle');
    86        return false;
    87    });
    88
    89    // If we click anywhere on the page, while the
    90    // dropdown is shown, it is going to be hidden:
    91
    92    $(document).click(function(){
    93        dropDown.trigger('hide');
    94    });
    95});
    On page load, the script scans through the options of the select element, and generates the markup according to the HTML5 data attributes that these items contain. As of jQuery 1.4.3, it is possible to access the values of these attributes directly with the jQuery data() method. This is a really handy feature, which makes it really easy to read the embedded data.
    The original select element is not destroyed – it is only hidden with the hide() method. This is important, because as you can see from the code above, we are reflecting any changes of the selection back to that original select element. This way, when you use the select as part of a form, the values will be properly recorded and passed to your backend script.
    Now that we have our code in place, lets take a closer look at the CSS3 magic that makes it all possible.

    The CSS

    As you can see from the markup at the top of the previous step, we are only using a minimal amount of markup to display the select box and the drop down. If we were confined to use pre-CSS3 techniques, we would have to add significantly more divs and spans.

    css/styles.css

    01#page{
    02    width:230px;
    03    margin:100px auto;
    04}
    05
    06#page h1{
    07    font-weight:normal;
    08    text-indent:-99999px;
    09    overflow:hidden;
    10    background:url('../img/your_product.png') no-repeat;
    11    width:230px;
    12    height:36px;
    13}
    14
    15#page form{
    16    margin:20px auto;
    17    width:200px;
    18}
    19
    20.tzSelect{
    21
    22    /* This is the container of the new select element */
    23
    24    height:34px;
    25    display:inline-block;
    26    min-width:200px;
    27    position:relative;
    28
    29    /* Preloading the background image for the dropdown */
    30    background:url("../img/dropdown_slice.png") no-repeat -99999px;
    31}
    32
    33.tzSelect .selectBox{
    34    position:absolute;
    35
    36    height:100%;
    37    width:100%;
    38
    39    /* Font settings */
    40
    41    font:13px/34px "Lucida Sans Unicode", "Lucida Grande", sans-serif;
    42    text-align:center;
    43    text-shadow:1px 1px 0 #EEEEEE;
    44    color:#666666;
    45
    46    /* Using CSS3 multiple backgrounds and a fallback */
    47
    48    background:url('../img/select_slice.png') repeat-x #ddd;
    49    background-image:url('../img/select_slice.png'),url('../img/select_slice.png'),url('../img/select_slice.png'),url('../img/select_slice.png');
    50    background-position:0 -136px, right -204px, 50% -68px, 0 0;
    51    background-repeat: no-repeat, no-repeat, no-repeat, repeat-x;
    52
    53    cursor:pointer;
    54
    55    -moz-border-radius:3px;
    56    -webkit-border-radius:3px;
    57    border-radius:3px;
    58}
    59
    60.tzSelect .selectBox:hover,
    61.tzSelect .selectBox.expanded{
    62    background-position:0 -170px, right -238px, 50% -102px, 0 -34px;
    63    color:#2c5667;
    64    text-shadow:1px 1px 0 #9bc2d0;
    65}
    CSS3 allows us to assign multiple background images to elements by just adding multiple url() declarations divided by a comma. They are added to the element from top to bottom, with each consecutive background displayed below the previous.
    The Select Item Deconstructed
    The Select Item Deconstructed
    Currently multiple backgrounds are supported by Firefox, Safari, Chrome and Opera. For Internet Explorer and older versions of the first browsers, a fallback is defined, which is basically just a regular version of the background. When parsing the CSS document, browsers that do not understand multiple background will just ignore the rule and use the plain one.
    01.tzSelect .dropDown{
    02    position:absolute;
    03    top:40px;
    04    left:0;
    05    width:100%;
    06    border:1px solid #32333b;
    07    border-width:0 1px 1px;
    08    list-style:none;
    09
    10    -moz-box-sizing:border-box;
    11    -webkit-box-sizing:border-box;
    12    box-sizing:border-box;
    13
    14    -moz-box-shadow:0 0 4px #111;
    15    -webkit-box-shadow:0 0 4px #111;
    16    box-shadow:0 0 4px #111;
    17}
    18
    19.tzSelect li{
    20    height:85px;
    21    cursor:pointer;
    22    position:relative;
    23
    24    /* Again, using CSS3 multiple backgrounds */
    25
    26    background:url('../img/dropdown_slice.png') repeat-x #222;
    27    background-image:url('../img/dropdown_slice.png'),url('../img/dropdown_slice.png'),url('../img/dropdown_slice.png');
    28    background-position: 50% -171px, 0 -85px, 0 0;
    29    background-repeat: no-repeat, no-repeat, repeat-x;
    30}
    31
    32.tzSelect li:hover{
    33    background-position: 50% -256px, 0 -85px, 0 0;
    34}
    35
    36.tzSelect li span{
    37    left:88px;
    38    position:absolute;
    39    top:27px;
    40}
    41
    42.tzSelect li i{
    43    color:#999999;
    44    display:block;
    45    font-size:12px;
    46}
    47
    48.tzSelect li img{
    49    left:9px;
    50    position:absolute;
    51    top:13px;
    52}
    The box-sizing property that I’ve used for the .dropDown class, specifies how borders add up to the total size of the element. Normally, the borders here would increase the overall width with 2px and ruin the alignment. With box-sizing set to border-box, however, the overall width will not exceed the one specified in the definition and borders will take up space on the inside.
    With this our jQuery and CSS3 powered select box  is complete!

    Parting Words

    In this tutorial we demonstrated some of the handy features that were introduced with jQuery 1.4.3 and a bit more of CSS3′s abilities. A good thing about this script, is that it keeps the original select box hidden on the page, and changes its value according to the fancy replacement. This way, when you submit the form the correct value is also passed along.
    Making Better Select Elements with jQuery and CSS3 Making Better Select Elements with jQuery and CSS3 Reviewed by BloggerSri on 4:36 AM Rating: 5

    No comments:

    Powered by Blogger.