Script by Jon Ippolito, v1.0
One of the easiest ways to make a Web page more responsive is to change the appearance of an element--a link, an image, or a div (rectangle)--when your user hovers over it with a mouse or trackpad.
You should know how to prepare your computer for Web projects and have a basic understanding of the anatomy of a Web page, including HTML, CSS, and JavaScript.
This particular screencast will use platformTK and softwareTK.
1. Change the style using just CSS
If you know enough CSS to identify an element by id (#) or class (.), you can add the :hover selector to make the changes only appear when the user has moused over an element.
/* The rectangle is normally blue. */
div#kitten {
background-color: blue ;
}
/* If the user mouses over the rectangle, it turns red. */
div#kitten:hover {
background-color: red ;
}
You can also change the style on hover with JavaScript. Let's start by doing this a brute-force way, namely inside the HTML tag itself.
<div onmouseover = "this.style.backgroundColor='red';" onmouseout = "this.style.backgroundColor='blue';">...
The JavaScript code must be attached inside quotes to an HTML tag using event handlers like onmouseover and onmouseout, which replace the CSS selector :hover. Inside those quotes, translating CSS to JavaScript requires the following conversions:
Note that you have to use single quotes ('') inside of double quotes ("") if you don't want the browser to get confused.
The disadvantage of this method is that you need to add new JavaScript lines for each stylistic attribute (color, border, width) that you want to change. Let's fix that.
An easier way to change a lot of styles at once is to associate them with a CSS class in your stylesheet, then use JavaScript to change the class.
<style>
.highlight-off {
background-color: blue ;
border: none ;
}
.highlight-on {
background-color: red ;
border: red dotted ;
}
</style>
...
<div onmouseover = "this.className='highlight-on';" onmouseout = "this.className='highlight-off';">...
Two details that can trip you up:
Adding JavaScript inside HTML tags ("inline") is inflexible, time-consuming, and just plain klunky. Fortunately, you can change styles or classes of HTML elements in JavaScript at the top of your page or in a separate file like highlight.js.
We'll use the fact that the JavaScript method document.getElementById("kitten") is the equivalent of the CSS selector #kitten. Note the camelCase capitalization of Id--short for Identity. If you write getElementByID by accident, JavaScript will throw an error.
<script>
document.getElementById( "kitten" ).onmouseover = this.className='highlight-on' ;
document.getElementById( "kitten" ).onmouseout = this.className='highlight-off' ;
</script>
...
<div id="kitten">...
This is almost right, but unfortunately the browser will just execute this.className = 'highlight-on' and this.className='highlight-off' one after another, and we'll never get any highlighting :(
When you want the browser to wait to execute code until a user mouses over an element--or to wait for any action, in fact--wrap that code in a function. In this case, we'll use "anonymous functions"--that is, functions defined right in place, without names--because they won't fire prematurely and will understand that this is the element the user rolled over.
<script>
document.getElementById( "kitten" ).onmouseover = function() {
this.className = 'highlight-on' ;
}
document.getElementById( "kitten" ).onmouseout = function() {
this.className = 'highlight-off' ;
}
</script>
...
<div id="kitten">...
We're almost there, but there's one small problem. If you load the page like this, your browser will tell you that document.getElementById("kitten") is undefined, despite the fact that you can see the div right in the HTML. The reason for this error is that the browser reads the code from top to bottom, and it encounters the code inside the script tags before it knows there's a div at the bottom named "kitten".
The solution is to wait till all of the divs in the body have loaded before adding the hover behavior. As usual, we'll delay the JavaScript by wrapping it in a function--in this case setHover()--and only trigger this function once the page has loaded.
<script>
setHover = function() {
document.getElementById( "kitten" ).onmouseover = function() {
this.className = 'highlight-on' ;
}
document.getElementById( "kitten" ).onmouseout = function() {
this.className = 'highlight-off' ;
}
}
</script>
...
<body onload="setHover()">
<div id="kitten">...
This is much better JavaScript.
That said, so far it's not an improvement on the CSS :hover selector, which is shorter and doesn't require adding onmouseover and onmouseout to each div. Fortunately, we can get JavaScript to add all these behaviors automatically.
When you want to automate something in JavaScript, try a for loop. We can use document.getElementsByTagName( "div" ) to grab all the divs in a page and make them all highlightable.
<script>
setHover = function() {
// Get all the divs on the page.
divs = document.getElementsByTagName( "div" ) ;
for ( divCounter = 0 ; divCounter < divs.length ; divCounter++ ) {
// Add onmouseover and onmouseout behaviors to each div.
divs[ divCounter ].onmouseover = function() {
this.className = 'highlight-on' ;
}
divs[ divCounter ].onmouseout = function() {
this.className = 'highlight-off' ;
}
}
}
</script>
...
<body onload="setHover()">
<div>...
Yes, we could have given all the divs hover behavior with CSS. But JavaScript lets you do much more: rolling over a div could pop up an alert, trigger a function that loads new content, or add the current item to a shopping cart.
divs[ divCounter ].onmouseover = function() {
this.className = 'highlight-on' ;
alert("You chose wisely!") ;
loadContentInto( this ) ;
addToShoppingCart( this ) ;
}
And while CSS only responds to hover behavior, JavaScript can respond to onmouseover, onclick, onfocus, and more:
divs[ divCounter ].onclick = function() {
alert("You asked for it--I'm taking you to another page!") ;
window.location = "another_page.html" ;
}
Maybe you only want divs in the navigation menu to respond with a certain behavior via onclick or onmouseover. No worries: give them the same class in the HTML, and then include an if statement in your JavaScript to filter for the divs you want.
<script>
setHover = function() {
divs = document.getElementsByTagName( "div" ) ;
// Get all the divs on the page.
divs = document.getElementsByTagName( "div" ) ;
for ( divCounter = 0 ; divCounter < divs.length ; divCounter++ ) {
// Only add the behaviors if the div is highlightable.
if ( divs[ divCounter ].className === "highlight-off" )
divs[ divCounter ].onmouseover = function() {
this.className = 'highlight-on' ;
}
divs[ divCounter ].onmouseout = function() {
this.className = 'highlight-off' ;
}
}
}
}
</script>
...
<body onload="setHover()">
<div class="regular">...
<div class="highlight-off">...
Congratulations! You now know how to use CSS to change the look of HTML elements when the user mouses over them, and how to use JavaScript to enable much more advanced user interaction.