Friday 19 August 2016

Web Tutorial: Schooling You in Rollovers!

As I write this, Singapore is still celebrating the Olympic spirit. In particular, our first Olympic Gold medal ever. Won by a young sprightly lad by the name of Joseph Isaac Schooling, who pipped Michael Phelps to the coveted title in the 100m Butterfly.

Do I have cause to feel proud? Rationally, no. I didn't pitch a cent towards Schooling's endeavor, nor have I been rooting for him since day one. Hell, his name barely registered on my radar (and neither did the Rio Games, for that matter) until he won the race and my Facebook feed positively erupted with the news.

But do I feel proud, nonetheless? Strangely, even though I probably have little right to, yes. This is a momentous occasion for Singapore, the island I was born on, lived on, and will in most likelihood, die on.

Joseph Schooling, like a boss.

Congratulations, Schooling. Well done, young man.

I'll mark this occasion by dedicating the planned web tutorial for this month, to Singapore's first Olympic Gold victory. It's about rollover buttons, and it's been stewing for a little while.

Ahem, so...

One of the most common things on the net is rollover buttons. They've been in effect ever since the first JavaScript snippet. Today, we're going to examine some of the ways they are implemented.

Hold on - some of the ways?

Yes. You didn't think for a moment there was only one way, did you? Hell, no! As technology evolves, so do once-accepted ways of doing things.

For the rest of this tutorial, I will be using some very ubiquitous buttons as examples, ie. Facebook, Twitter and LinkedIn. In particular, we'll use them to link to Joseph Schooling's accounts.

These images should be saved in the "img" directory of your root folder.

rollover_fb0.jpg
rollover_tw0.jpg
rollover_li0.jpg

So, what does a rollover button do?

You move your mouse cursor over the button, and the button changes, showing you that it can be clicked.

Like this - see?

Without further ado, we're going to jump right in!

Using JavaScript and Img tags

For this, we need three more images. These are the images that will be changed to. In animation terminology, both original and new images are known as "sprites". (That's just FYI in case you have a presentation or something and need to sound like you know your shit. Don't worry about it.)

Again, these images should be saved in the "img" directory of your root folder.

rollover_fb1.jpg
rollover_tw1.jpg
rollover_li1.jpg

So we have the original images in HTML, encased in anchor tags. The CSS styling is meant to disable the fugly border thicknesses that sometimes show up on older browsers. (Yes IE, I'm looking at you.)
<html>
    <head>
        <title>Rollover</title>
        <style>
            a img
            {
                border-width:0px;
            }
        </style>
    </head>
    <body>
        <a href="https://www.facebook.com/joseph.i.schooling"><img src="img/rollover_fb0.jpg"></a>
        <a href="https://www.linkedin.com/in/joseph-schooling-1750a9a2"><img src="img/rollover_li0.jpg"></a>
        <a href="https://twitter.com/joschooling"><img src="img/rollover_tw0.jpg"></a>
    </body>
</html>


Now we add this! Run your code. When you move your cursor over the icons, they should change to a lighter shade.
<html>
    <head>
        <title>Rollover</title>
        <style>
            a img
            {
                border-width:0px;
            }
        </style>
    </head>
    <body>
        <a href="https://www.facebook.com/joseph.i.schooling"><img src="img/rollover_fb0.jpg" onmouseover="this.src='img/rollover_fb1.jpg'" onmouseout="this.src='img/rollover_fb0.jpg'"></a>
        <a href="https://www.linkedin.com/in/joseph-schooling-1750a9a2"><img src="img/rollover_li0.jpg" onmouseover="this.src='img/2016/rollover_li1.jpg'" onmouseout="this.src='img/rollover_li0.jpg'"></a>
        <a href="https://twitter.com/joschooling"><img src="img/rollover_tw0.jpg" onmouseover="this.src='img/rollover_tw1.jpg'" onmouseout="this.src='img/rollover_tw0.jpg'"></a>
    </body>
</html>


When we invoke the mouseover and mouseout events in the HTML tags, the URLs of the images are changed accordingly. Not my favorite method. Don't get me wrong, it works. But this is Jurassic-era HTML. There are better ways of doing things now.

Using JavaScript and CSS


Here are the buttons, and some CSS. Note that the buttons aren't images. They're actual buttons. The CSS basically styles these buttons to use the original images as background images.
<html>
    <head>
        <title>Rollover</title>
        <style>
            button
            {
                width:64px;
                height:64px;
                border-width:0px;
                background-repeat:no-repeat;
                background-position:left top;
                cursor:pointer;
            }

            .btn_fb_off
            {
                background:url(img/rollover_fb0.jpg);
            }

            .btn_li_off
            {
                background:url(img/rollover_li0.jpg);
            }

            .btn_tw_off
            {
                background:url(img/rollover_tw0.jpg);
            }

            .btn_fb_on
            {
                background:url(img/rollover_fb1.jpg);
            }

            .btn_li_on
            {
                background:url(img/rollover_li1.jpg);
            }

            .btn_tw_on
            {
                background:url(img/rollover_tw1.jpg);
            }               
        </style>
    </head>
    <body>
        <button onclick="window.location='https://www.facebook.com/joseph.i.schooling'" class="btn_fb_off"></button>
        <button onclick="window.location='https://www.linkedin.com/in/joseph-schooling-1750a9a2'" class="btn_li_off"></button>
        <button onclick="window.location='https://twitter.com/joschooling'" class="btn_tw_off"></button>
    </body>
</html>


So if we add this to the HTML, the mouseover and mouseout events trigger a CSS change, which in effect changes the background image of the buttons.
<html>
    <head>
        <title>Rollover</title>
        <style>
            button
            {
                width:64px;
                height:64px;
                border-width:0px;
                background-repeat:no-repeat;
                background-position:left top;
                cursor:pointer;
            }

            .btn_fb_off
            {
                background:url(img/rollover_fb0.jpg);
            }

            .btn_li_off
            {
                background:url(img/rollover_li0.jpg);
            }

            .btn_tw_off
            {
                background:url(img/rollover_tw0.jpg);
            }

            .btn_fb_on
            {
                background:url(img/rollover_fb1.jpg);
            }

            .btn_li_on
            {
                background:url(img/rollover_li1.jpg);
            }

            .btn_tw_on
            {
                background:url(img/rollover_tw1.jpg);
            }               
        </style>
    </head>
    <body>
        <button onclick="window.location='https://www.facebook.com/joseph.i.schooling'" onmouseover="this.className='btn_fb_on'" onmouseout="this.className='btn_fb_off'" class="btn_fb_off"></button>
        <button onclick="window.location='https://www.linkedin.com/in/joseph-schooling-1750a9a2'" onmouseover="this.className='btn_li_on'" onmouseout="this.className='btn_li_off'" class="btn_li_off"></button>
        <button onclick="window.location='https://twitter.com/joschooling'" onmouseover="this.className='btn_tw_on'" onmouseout="this.className='btn_tw_off'" class="btn_tw_off"></button>
    </body>
</html>


Not my favorite method either. I'll explain why in a bit.

What's wrong with the above two methods?

Firstly, they use JavaScript, which is always a bad idea if you're paranoid about users turning JavaScript off.

Secondly, that's a shitload of HTML code to write for a few crummy rollover buttons. I prefer to reserve HTML for other things.

Thirdly, they involve loading new images. The first time any of these images are loaded, there's always a certain amount of delay. Subsequent times, the images have been cached, so no more delays occur. You can get around this problem by pre-loading images.

Or you could do this!

Using mostly CSS

This method does not use JavaScript, and does not use separate images for the sprites. These are the images we'll be using.

Did I mention that these images should be saved in the "img" directory of your root folder?



rollover_fb2.jpg
rollover_tw2.jpg
rollover_li2.jpg


Note that these images are joined. Here's the HTML and CSS.
<html>
    <head>
        <title>Rollover</title>
        <style>
            button
            {
                width:64px;
                height:64px;
                border-width:0px;
                background-position:0% 0%;
                cursor:pointer;
            }   

            #btn_fb
            {
                background-image:url(img/rollover_fb2.jpg);
            }

            #btn_li
            {
                background-image:url(img/rollover_li2.jpg);
            }

            #btn_tw
            {
                background-image:url(img/rollover_tw2.jpg);
            }
        </style>
    </head>
    <body>
        <button onclick="window.location='https://www.facebook.com/joseph.i.schooling'" id="btn_fb"></button>
        <button onclick="window.location='https://www.linkedin.com/in/joseph-schooling-1750a9a2'" id="btn_li"></button>
        <button onclick="window.location='https://twitter.com/joschooling'" id="btn_tw"></button>
    </body>
</html>


Again, these are actual buttons. Nothing much has changed from the previous method so far, except that a new CSS property has been added - background-position. This may seem utterly unnecessary now given that this is the default setting anyway. But... you guessed it, we're going to change this!
<html>
    <head>
        <title>Rollover</title>
        <style>
            button
            {
                width:64px;
                height:64px;
                border-width:0px;
                background-position:0% 0%;
                cursor:pointer;
            }

            button:hover
            {
                background-position:0% 100%;
            }   

            #btn_fb
            {
                background-image:url(img/rollover_fb2.jpg);
            }

            #btn_li
            {
                background-image:url(img/rollover_li2.jpg);
            }

            #btn_tw
            {
                background-image:url(img/rollover_tw2.jpg);
            }
        </style>
    </head>
    <body>
        <button onclick="window.location='https://www.facebook.com/joseph.i.schooling'" id="btn_fb"></button>
        <button onclick="window.location='https://www.linkedin.com/in/joseph-schooling-1750a9a2'" id="btn_li"></button>
        <button onclick="window.location='https://twitter.com/joschooling'" id="btn_tw"></button>
    </body>
</html>


See what we did there? Each element styled with the CSS class rollover has a new specification - the hover. When you move your cursor over the element, the background-position property of the element changes, giving you the new image, or at least appearing to do so. In reality, it's the same image. It's just that the background position has been offset! When you move your cursor off the element, the original settings kick in.

What's so good about this?

Well, for each button, only one image is used. This saves you the trouble of making different CSS classes for them. Right now you have only three buttons. What if you have fifty? Extensibility FTW!

Also, when the page is loaded, the images are loaded too. Different images don't have to be loaded upon your cursor interacting with the buttons.

Since you're not using JavaScript, you don't have to worry about someone disabling it.

Last, but not least, look at the simplicity of the HTML. All the work is being done by the CSS.

Water way to make buttons, eh?
T___T

No comments:

Post a Comment