Variable size custom button with CSS

Posted on Tuesday February 16th, 2010 by Matt

Introduction

Recently, I’ve been looking at what is called “elastic” css layout.
Basically, il’t about using the “em” unit instead of the pixel. This unit is a relative unit, as the “%”, but it is relative to the current font size instead of the container size.
To understand its usefulness, one has to know that some people with vision problems usually make use of an option in their browser that that allows them to upsize the default font size.
Texts become bigger and more easily readable. Unfortunately, it is quite rare that the visited site has anticipated this change, and usually the whole layout becomes all broken.

Imagine for example that you have decided to put a nice image behind a link to have a good looking button. If the font size is augmented, the text will most probably get out of that image. All of a sudden, the button becomes less of an eye candy.

Looking for a solution to this problem, I ran accross a post on the excellent site positioniseveything.net that offers a solution allowing to apply semi-transparent drop shadows on any image. The post is visible here : http://www.positioniseverything.net/articles/dropshadows2.html

The approach seemed interesting to me, but not flexible enough to my taste. Indeed, it is based on a huge image, hoping the container will never go beyond that size. Not even mentioning the ever growing screen sizes, this method has a cost in terms of bandwidth. Also, it assumes that we are looking for a “linear” image border, which is not always the case.

With Flash, there is a way to handle round corners that is called Scale9Grid : we divide a bloc in 9 distinct bits as illustrated in the picture below, and those located in the corners are never resized.
scale9grid

Based on this method and the positioniseverything technic, I crafted a way to have a custom button that adapts to its content. You can visit the interactive cutom scalable button demonstration.
But I hear you getting impatient already, so here is the said technic :

Image preparation

We are going to cut out our button as done in the above picture, with one minor difference.
Counter to Flash, CSS2 doesn’t allow us to stretch images. So we will keep only a 1 pixel width bit for the parts that have to spread horizontally and repeat this bit as many times as necessary.
Idem for the verical parts, keeping only a 1 pixel high bit.
This step is not really necessary, but it allows not to overload the bandwidth with unneeded data.

The HTML

<div class="tl">
    <div class="tr">
        <div class="bl">
            <div class="br">
                <div class="t">
                    <div class="b">
                        <div class="l">
                            <div class="r">
                                <div class="content">
                                    Place your content here
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

As you can see, an certain quantity of tags that have for only use to help construct the button is needed. This goes against the principle stating that html always should keep its semantic meaning (which is good for search engines), but one doesn’t make an omelette without breaking any eggs !

The classes represent the image part that will be used. “l” for “left”, “b” for “bottom”, “br” for “bottom-right”, etc.

The CSS

Comments are placed directly within the CSS.

.tl{
    background:url('tl.gif') no-repeat top left;
    display:inline-block;
}

.ie7root .tl, .ie7root .tl div{ /* ie7 fix : any haslayout trigger can replace this */
    float:left;
}

.tr{
    background:url('tr.gif') no-repeat top right;
}
.bl{
    background:url('bl.gif') no-repeat bottom left;
}
.br{
    background:url('br.gif') no-repeat bottom right;
    padding-right:23px; /* depends on your right images width */
}
.t{
    background:url('t.gif') repeat-x top left;
    margin-left:23px; /* depends on your left images width */
    padding-top:18px; /* depends on your top images height */
}
.b{
    background:url('b.gif') repeat-x bottom left;
    padding-bottom:18px; /* depends on your bottom images height */
}
.l{
    background:url('l.gif') repeat-y top left;
    margin-left:-23px; /* depends on your left images width */
}
.r{
    background:url('r.gif') repeat-y top right;
    margin-left:23px; /* depends on your left images width */
    margin-right:-23px; /* depends on your right images width */
    padding-right:23px; /* depends on your right images width */
}
.content{
    overflow:hidden; /* prevents non breakable content from overflowing */
    vertical-align:bottom; /* fixes a weird bug about a 3pixel gap in the bottom */
    background-color:#28bcd9;
}

Conclusion

This method works with all tested browsers, including the dreadful IE6 (which it seems might at last go to retirement soon!).
You can use images with transparency in gif or png format (for the browsers that support it), and so create drop shadows or any other type of border for your links or contents.
If the content changes or if the user changes the font size, the button will adapt !

There will probably be more possibilities to do such things with the coming of CSS3 and HTML5. Until then you can now have contents stylized to your liking, that will be nice to the visually impaired too. Enjoy it!

3 Comments to 'Variable size custom button with CSS'

  1. Nick said :

    ..Not working in Firefox 3.6

  2. Matt said :

    I am using Firefox 3.6 right now and the demo page works perfectly… What problem do you see ?

  3. http://three-gorges.tk said :

    your blog’s design is simple and clean….

    Mind if I use some of the information from this post if I provide a link back to your site?…

Leave a Comment

Top of page
Clicky Web Analytics