Change label color on input focus

Hi,

Here’s a sample form:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Sample Form</title>
</head>
<body>
<form action="#">
<label for="fname">First name</label><input type="text" id="fname">
<br>
<label for="lname">Last name</label><input type="text" id="lname">
</form>
</body>
</html>

I wonder how I can change the label color when I focus/tab on its text filed? How can I do it through JavaScript if CSS doesn’t work here?

Thanks in advance!
Mike

It can be done with css using http://reference.sitepoint.com/css/pseudoclass-focus but not all versions of the browsers will support that. Try and do it with css if you can incase the end user has javascript disabled

According to your reference:

It can apply to a form control

But I’m going to style the label when its corresponding input gets focus.

Let’s go with your currently existing code.

We place the script at the end of the body, just before the </body> tag


    </form>
    ...
    <script src="script.js"></script>
</body>
</html>

When the script runs, you want to assign a CSS class to the label, to give it a background color:


.focused {
    background-color: #00FFFF;
}

The script adds an onclick event listener to each input field, so that the inputFocusHandler script can handle the label class name.


var form = document.getElementById('personalInfo'),
    i;
for (i = 0; i < form.elements.length; i += 1) {
    if (form.elements[i].nodeName === 'INPUT') {
        form.elements[i].onfocus = inputFocusHandler;
    }
}

How the labelFocusHandler function works is to check that an input field was clicked on, after which it passes that input field on to the setLabelFocusWithInput function.

The inputFocusHandler function gets the label field and adds the “focused” class name to it. Then when someone leaves the input field (that’s the blur event) the class name is removed from the label field.


function inputFocusHandler() {
    var label = searchUpForTagName(this, 'label');
    label.className = 'focused';
 
    this.onblur = function () {
        label.className = '';
    };
}

Notice how these functions are all nice and small, and each handle just one main concern.

That searchUpForTagName function is where things start to get a bit more complex. We could just search the previous siblings and be done with it, but a preferred style to use with form labels is with a nested label:


<label>
    First name
    <input type="text" name="fname">
</label>

So, we should go up the previous siblings of the input field looking for the label, and when we hit the top we should go to its parent, and then keep on looking up.
We can do that in two stages, where we check if any previous siblings match, and if not go to the parent and keep on checking. If we end up at the body element, what we were looking for isn’t there so we should just return without having found anything.


function searchUpForTagName(field, tagName) {
    tagName = tagName.toUpperCase();
    
    // first check the previous siblings
    field = searchPreviousSiblings(field, tagName);

    while (field && field.nodeName !== tagName) {
        if (field.parentNode.nodeName === 'BODY') {
            return;
        }
        // then check the parent and its previous siblings
        field = field.parentNode;
        if (field.nodeName !== tagName) {
            field = searchPreviousSiblings(field.parentNode, tagName);
        }
    }
    return field;
}

Checking the previousSiblings is relatively straight forward too. We just check if a previous sibling exists before checking if it’s what we want:


function searchPreviousSiblings(fromElement, tagName) {
    var prevElement = fromElement;
    tagName = tagName.toUpperCase();

    if (!prevElement.previousSibling) {
        return;
    }
    prevElement = fromElement.previousSibling;
    while (prevElement && prevElement.nodeName !== tagName) {
        if (!prevElement.previousSibling) {
            return prevElement;
        }
        prevElement = prevElement.previousSibling;
    }
    return prevElement;
}

And so, to change the label color on input focus, tends to need the following code for it to be done properly:


function searchPreviousSiblings(fromElement, tagName) {
    var prevElement = fromElement;
    tagName = tagName.toUpperCase();
 
    if (!prevElement.previousSibling) {
        return;
    }
    prevElement = fromElement.previousSibling;
    while (prevElement && prevElement.nodeName !== tagName) {
        if (!prevElement.previousSibling) {
            return prevElement;
        }
        prevElement = prevElement.previousSibling;
    }
    return prevElement;
}

function searchUpForTagName(field, tagName) {
    tagName = tagName.toUpperCase();
 
    // first check the previous siblings
    field = searchPreviousSiblings(field, tagName);
 
    while (field && field.nodeName !== tagName) {
        if (field.parentNode.nodeName === 'BODY') {
            return;
        }
        // then check the parent and its previous siblings
        field = field.parentNode;
        if (field.nodeName !== tagName) {
            field = searchPreviousSiblings(field.parentNode, tagName);
        }
    }
    return field;
}

function inputFocusHandler() {
    var label = searchUpForTagName(this, 'label');
    label.className = 'focused';
 
    this.onblur = function () {
        label.className = '';
    };
}

var form = document.getElementById('personalInfo'),
    i;
for (i = 0; i < form.elements.length; i += 1) {
    if (form.elements[i].nodeName === 'INPUT') {
        form.elements[i].onfocus = inputFocusHandler;
    }
}

Dear Paul,

I appreciate your time and educational notes. Thank you! :slight_smile: