[javascript] Find html label associated with a given input

Let's say I have an html form. Each input/select/textarea will have a corresponding <label> with the for attribute set to the id of it's companion. In this case, I know that each input will only have a single label.

Given an input element in javascript — via an onkeyup event, for example — what's the best way to find it's associated label?

This question is related to javascript html label

The answer is


Use a JQuery selector:

$("label[for="+inputElement.id+"]")

If you're willing to use querySelector (and you can, even down to IE9 and sometimes IE8!), another method becomes viable.

If your form field has an ID, and you use the label's for attribute, this becomes pretty simple in modern JavaScript:

var form = document.querySelector('.sample-form');
var formFields = form.querySelectorAll('.form-field');

[].forEach.call(formFields, function (formField) {
    var inputId = formField.id;
    var label = form.querySelector('label[for=' + inputId + ']');
    console.log(label.textContent);
});

Some have noted about multiple labels; if they all use the same value for the for attribute, just use querySelectorAll instead of querySelector and loop through to get everything you need.


A really concise solution using ES6 features like destructuring and implicit returns to turn it into a handy one liner would be:

const getLabels = ({ labels, id }) => labels || document.querySelectorAll(`label[for=${id}]`)

Or to simply get one label, not a NodeList:

const getFirstLabel = ({ labels, id }) => labels && labels[0] || document.querySelector(`label[for=${id}]`)

If you are using jQuery you can do something like this

$('label[for="foo"]').hide ();

If you aren't using jQuery you'll have to search for the label. Here is a function that takes the element as an argument and returns the associated label

function findLableForControl(el) {
   var idVal = el.id;
   labels = document.getElementsByTagName('label');
   for( var i = 0; i < labels.length; i++ ) {
      if (labels[i].htmlFor == idVal)
           return labels[i];
   }
}

It is actually far easier to add an id to the label in the form itself, for example:

<label for="firstName" id="firstNameLabel">FirstName:</label>

<input type="text" id="firstName" name="firstName" class="input_Field" 
       pattern="^[a-zA-Z\s\-]{2,25}$" maxlength="25"
       title="Alphabetic, Space, Dash Only, 2-25 Characters Long" 
       autocomplete="on" required
/>

Then, you can simply use something like this:

if (myvariableforpagelang == 'es') {
   // set field label to spanish
   document.getElementById("firstNameLabel").innerHTML = "Primer Nombre:";
   // set field tooltip (title to spanish
   document.getElementById("firstName").title = "Alfabética, espacio, guión Sólo, 2-25 caracteres de longitud";
}

The javascript does have to be in a body onload function to work.

Just a thought, works beautifully for me.


The best answer works perfectly fine but in most cases, it is overkill and inefficient to loop through all the label elements.

Here is an efficent function to get the label that goes with the input element:

function getLabelForInput(id)
{
    var el = document.getElementById(id);
    if (!el)
        return null;
    var elPrev = el.previousElementSibling;
    var elNext = el.nextElementSibling;
    while (elPrev || elNext)
    {
        if (elPrev)
        {
            if (elPrev.htmlFor === id)
                return elPrev;
            elPrev = elPrev.previousElementSibling;
        }
        if (elNext)
        {
            if (elNext.htmlFor === id)
                return elNext;
            elNext = elNext.nextElementSibling;
        }
    }
    return null;
}

For me, this one line of code was sufficient:

el = document.getElementById(id).previousElementSibling;

In most cases, the label will be very close or next to the input, which means the loop in the above function only needs to iterate a very small number of times.


with jquery you could do something like

var nameOfLabel = someInput.attr('id');
var label = $("label[for='" + nameOfLabel + "']");

It is actually far easier to add an id to the label in the form itself, for example:

<label for="firstName" id="firstNameLabel">FirstName:</label>

<input type="text" id="firstName" name="firstName" class="input_Field" 
       pattern="^[a-zA-Z\s\-]{2,25}$" maxlength="25"
       title="Alphabetic, Space, Dash Only, 2-25 Characters Long" 
       autocomplete="on" required
/>

Then, you can simply use something like this:

if (myvariableforpagelang == 'es') {
   // set field label to spanish
   document.getElementById("firstNameLabel").innerHTML = "Primer Nombre:";
   // set field tooltip (title to spanish
   document.getElementById("firstName").title = "Alfabética, espacio, guión Sólo, 2-25 caracteres de longitud";
}

The javascript does have to be in a body onload function to work.

Just a thought, works beautifully for me.


If you are using jQuery you can do something like this

$('label[for="foo"]').hide ();

If you aren't using jQuery you'll have to search for the label. Here is a function that takes the element as an argument and returns the associated label

function findLableForControl(el) {
   var idVal = el.id;
   labels = document.getElementsByTagName('label');
   for( var i = 0; i < labels.length; i++ ) {
      if (labels[i].htmlFor == idVal)
           return labels[i];
   }
}

I am bit surprised no one is suggesting to use the CSS relationship method?

in a style sheet you can reference a label from the element selector:

<style>

//for input element with class 'YYY'
input.YYY + label {}

</style>

if the checkbox has an id of 'XXX' then the label would be found through jQuery by:

$('#XXX + label');

You can also apply .find('+ label') to return the label from a jQuery checkbox element, ie useful when looping:

$('input[type=checkbox]').each( function(){
   $(this).find('+ label');
});

For future searchers... The following is a jQuery-ified version of FlySwat's accepted answer:

var labels = $("label");
for (var i = 0; i < labels.length; i++) {
    var fieldId = labels[i].htmlFor;
    if (fieldId != "") {
        var elem = $("#" + fieldId);
        if (elem.length != 0) {
            elem.data("label", $(labels[i]));   
        }
    }
}

Using:

$("#myFormElemId").data("label").css("border","3px solid red");

Answer from Gijs was most valuable for me, but unfortunately the extension does not work.

Here's a rewritten extension that works, it may help someone:

jQuery.fn.getLabels = function () {
    return this.map(function () {
        var parentLabels = $(this).parents('label').get();
        var associatedLabels = this.id ? associatedLabels = $("label[for='" + this.id + "']").get() : [];
        return parentLabels.concat(associatedLabels);
    });
};

I know this is old, but I had trouble with some solutions and pieced this together. I have tested this on Windows (Chrome, Firefox and MSIE) and OS X (Chrome and Safari) and believe this is the simplest solution. It works with these three style of attaching a label.

<label><input type="checkbox" class="c123" id="cb1" name="item1">item1</label>

<input type="checkbox" class="c123" id="cb2" name="item2">item2</input>

<input type="checkbox" class="c123" id="cb3" name="item3"><label for="cb3">item3</label>

Using jQuery:

$(".c123").click(function() {
    $cb = $(this);
    $lb = $(this).parent();
    alert( $cb.attr('id') + ' = ' + $lb.text() );
});

My JSFiddle: http://jsfiddle.net/pnosko/6PQCw/


Earlier...

var labels = document.getElementsByTagName("LABEL"),
    lookup = {},
    i, label;

for (i = 0; i < labels.length; i++) {
    label = labels[i];
    if (document.getElementById(label.htmlFor)) {
        lookup[label.htmlFor] = label;
    }
}

Later...

var myLabel = lookup[myInput.id];

Snarky comment: Yes, you can also do it with JQuery. :-)


All the other answers are extremely outdated!!

All you have to do is:

input.labels

HTML5 has been supported by all of the major browsers for many years already. There is absolutely no reason that you should have to make this from scratch on your own or polyfill it! Literally just use input.labels and it solves all of your problems.


I am a bit surprised that nobody seems to know that you're perfectly allowed to do:

<label>Put your stuff here: <input value="Stuff"></label>

Which won't get picked up by any of the suggested answers, but will label the input correctly.

Here's some code that does take this case into account:

$.fn.getLabels = function() {
    return this.map(function() {
        var labels = $(this).parents('label');
        if (this.id) {
            labels.add('label[for="' + this.id + '"]');
        }
        return labels.get();
    });
};

Usage:

$('#myfancyinput').getLabels();

Some notes:

  • The code was written for clarity, not for performance. More performant alternatives may be available.
  • This code supports getting the labels of multiple items in one go. If that's not what you want, adapt as necessary.
  • This still doesn't take care of things like aria-labelledby if you were to use that (left as an exercise to the reader).
  • Using multiple labels is a tricky business when it comes to support in different user agents and assistive technologies, so test well and use at your own risk, etc. etc.
  • Yes, you could also implement this without using jQuery. :-)

Earlier...

var labels = document.getElementsByTagName("LABEL"),
    lookup = {},
    i, label;

for (i = 0; i < labels.length; i++) {
    label = labels[i];
    if (document.getElementById(label.htmlFor)) {
        lookup[label.htmlFor] = label;
    }
}

Later...

var myLabel = lookup[myInput.id];

Snarky comment: Yes, you can also do it with JQuery. :-)


with jquery you could do something like

var nameOfLabel = someInput.attr('id');
var label = $("label[for='" + nameOfLabel + "']");

I know this is old, but I had trouble with some solutions and pieced this together. I have tested this on Windows (Chrome, Firefox and MSIE) and OS X (Chrome and Safari) and believe this is the simplest solution. It works with these three style of attaching a label.

<label><input type="checkbox" class="c123" id="cb1" name="item1">item1</label>

<input type="checkbox" class="c123" id="cb2" name="item2">item2</input>

<input type="checkbox" class="c123" id="cb3" name="item3"><label for="cb3">item3</label>

Using jQuery:

$(".c123").click(function() {
    $cb = $(this);
    $lb = $(this).parent();
    alert( $cb.attr('id') + ' = ' + $lb.text() );
});

My JSFiddle: http://jsfiddle.net/pnosko/6PQCw/


have you tried using document.getElementbyID('id') where id is the id of the label or is the situation that you dont know which one you are looking for


If you are using jQuery you can do something like this

$('label[for="foo"]').hide ();

If you aren't using jQuery you'll have to search for the label. Here is a function that takes the element as an argument and returns the associated label

function findLableForControl(el) {
   var idVal = el.id;
   labels = document.getElementsByTagName('label');
   for( var i = 0; i < labels.length; i++ ) {
      if (labels[i].htmlFor == idVal)
           return labels[i];
   }
}

There is a labels property in the HTML5 standard which points to labels which are associated to an input element.

So you could use something like this (support for native labels property but with a fallback for retrieving labels in case the browser doesn't support it)...

var getLabelsForInputElement = function(element) {
    var labels = [];
    var id = element.id;

    if (element.labels) {
        return element.labels;
    }

    id && Array.prototype.push
        .apply(labels, document.querySelector("label[for='" + id + "']"));

    while (element = element.parentNode) {
        if (element.tagName.toLowerCase() == "label") {
            labels.push(element);
        }  
    }

    return labels;
};

// ES6
var getLabelsForInputElement = (element) => {
    let labels;
    let id = element.id;

    if (element.labels) {
        return element.labels;
    }

    if (id) {
        labels = Array.from(document.querySelector(`label[for='${id}']`)));
    }

    while (element = element.parentNode) {
        if (element.tagName.toLowerCase() == "label") {
            labels.push(element);
        }  
    }

    return labels;
};

Even easier if you're using jQuery...

var getLabelsForInputElement = function(element) {
    var labels = $();
    var id = element.id;

    if (element.labels) {
        return element.labels;
    }

    id && (labels = $("label[for='" + id  + "']")));

    labels = labels.add($(element).parents("label"));

    return labels;
};

have you tried using document.getElementbyID('id') where id is the id of the label or is the situation that you dont know which one you are looking for


As it has been already mentionned, the (currently) top-rated answer does not take into account the possibility to embed an input inside a label.

Since nobody has posted a JQuery-free answer, here is mine :

var labels = form.getElementsByTagName ('label');
var input_label = {};
for (var i = 0 ; i != labels.length ; i++)
{
    var label = labels[i];
    var input = label.htmlFor
              ? document.getElementById(label.htmlFor)
              : label.getElementsByTagName('input')[0];
    input_label[input.outerHTML] = 
        (label.innerText || label.textContent); // innerText for IE8-
}

In this example, for the sake of simplicity, the lookup table is directly indexed by the input HTML elements. This is hardly efficient and you can adapt it however you like.

You can use a form as base element, or the whole document if you want to get labels for multiple forms at once.

No checks are made for incorrect HTML (multiple or missing inputs inside labels, missing input with corresponding htmlFor id, etc), but feel free to add them.

You might want to trim the label texts, since trailing spaces are often present when the input is embedded in the label.


All the other answers are extremely outdated!!

All you have to do is:

input.labels

HTML5 has been supported by all of the major browsers for many years already. There is absolutely no reason that you should have to make this from scratch on your own or polyfill it! Literally just use input.labels and it solves all of your problems.


$("label[for='inputId']").text()

This helped me to get the label of an input element using its ID.


have you tried using document.getElementbyID('id') where id is the id of the label or is the situation that you dont know which one you are looking for


A really concise solution using ES6 features like destructuring and implicit returns to turn it into a handy one liner would be:

const getLabels = ({ labels, id }) => labels || document.querySelectorAll(`label[for=${id}]`)

Or to simply get one label, not a NodeList:

const getFirstLabel = ({ labels, id }) => labels && labels[0] || document.querySelector(`label[for=${id}]`)

Use a JQuery selector:

$("label[for="+inputElement.id+"]")

If you're willing to use querySelector (and you can, even down to IE9 and sometimes IE8!), another method becomes viable.

If your form field has an ID, and you use the label's for attribute, this becomes pretty simple in modern JavaScript:

var form = document.querySelector('.sample-form');
var formFields = form.querySelectorAll('.form-field');

[].forEach.call(formFields, function (formField) {
    var inputId = formField.id;
    var label = form.querySelector('label[for=' + inputId + ']');
    console.log(label.textContent);
});

Some have noted about multiple labels; if they all use the same value for the for attribute, just use querySelectorAll instead of querySelector and loop through to get everything you need.


Earlier...

var labels = document.getElementsByTagName("LABEL"),
    lookup = {},
    i, label;

for (i = 0; i < labels.length; i++) {
    label = labels[i];
    if (document.getElementById(label.htmlFor)) {
        lookup[label.htmlFor] = label;
    }
}

Later...

var myLabel = lookup[myInput.id];

Snarky comment: Yes, you can also do it with JQuery. :-)


For future searchers... The following is a jQuery-ified version of FlySwat's accepted answer:

var labels = $("label");
for (var i = 0; i < labels.length; i++) {
    var fieldId = labels[i].htmlFor;
    if (fieldId != "") {
        var elem = $("#" + fieldId);
        if (elem.length != 0) {
            elem.data("label", $(labels[i]));   
        }
    }
}

Using:

$("#myFormElemId").data("label").css("border","3px solid red");

I am a bit surprised that nobody seems to know that you're perfectly allowed to do:

<label>Put your stuff here: <input value="Stuff"></label>

Which won't get picked up by any of the suggested answers, but will label the input correctly.

Here's some code that does take this case into account:

$.fn.getLabels = function() {
    return this.map(function() {
        var labels = $(this).parents('label');
        if (this.id) {
            labels.add('label[for="' + this.id + '"]');
        }
        return labels.get();
    });
};

Usage:

$('#myfancyinput').getLabels();

Some notes:

  • The code was written for clarity, not for performance. More performant alternatives may be available.
  • This code supports getting the labels of multiple items in one go. If that's not what you want, adapt as necessary.
  • This still doesn't take care of things like aria-labelledby if you were to use that (left as an exercise to the reader).
  • Using multiple labels is a tricky business when it comes to support in different user agents and assistive technologies, so test well and use at your own risk, etc. etc.
  • Yes, you could also implement this without using jQuery. :-)

document.querySelector("label[for=" + vHtmlInputElement.id + "]");

This answers the question in the simplest and leanest manner. This uses vanilla javascript and works on all main-stream proper browsers.


As it has been already mentionned, the (currently) top-rated answer does not take into account the possibility to embed an input inside a label.

Since nobody has posted a JQuery-free answer, here is mine :

var labels = form.getElementsByTagName ('label');
var input_label = {};
for (var i = 0 ; i != labels.length ; i++)
{
    var label = labels[i];
    var input = label.htmlFor
              ? document.getElementById(label.htmlFor)
              : label.getElementsByTagName('input')[0];
    input_label[input.outerHTML] = 
        (label.innerText || label.textContent); // innerText for IE8-
}

In this example, for the sake of simplicity, the lookup table is directly indexed by the input HTML elements. This is hardly efficient and you can adapt it however you like.

You can use a form as base element, or the whole document if you want to get labels for multiple forms at once.

No checks are made for incorrect HTML (multiple or missing inputs inside labels, missing input with corresponding htmlFor id, etc), but feel free to add them.

You might want to trim the label texts, since trailing spaces are often present when the input is embedded in the label.


have you tried using document.getElementbyID('id') where id is the id of the label or is the situation that you dont know which one you are looking for


I have made for my own need, can be useful for somebody: JSFIDDLE

$("input").each(function () {
    if ($.trim($(this).prev('label').text()) != "") {
        console.log("\nprev>children:");
        console.log($.trim($(this).prev('label').text()));
    } else {
        if ($.trim($(this).parent('label').text()) != "") {
            console.log("\nparent>children:");
            console.log($.trim($(this).parent('label').text()));
        } else {
            if ($.trim($(this).parent().prev('label').text()) != "") {
                console.log("\nparent>prev>children:");
                console.log($.trim($(this).parent().prev('label').text()));
            } else {
                console.log("NOTFOUND! So set your own condition now");
            }
        }
    }
});

There is a labels property in the HTML5 standard which points to labels which are associated to an input element.

So you could use something like this (support for native labels property but with a fallback for retrieving labels in case the browser doesn't support it)...

var getLabelsForInputElement = function(element) {
    var labels = [];
    var id = element.id;

    if (element.labels) {
        return element.labels;
    }

    id && Array.prototype.push
        .apply(labels, document.querySelector("label[for='" + id + "']"));

    while (element = element.parentNode) {
        if (element.tagName.toLowerCase() == "label") {
            labels.push(element);
        }  
    }

    return labels;
};

// ES6
var getLabelsForInputElement = (element) => {
    let labels;
    let id = element.id;

    if (element.labels) {
        return element.labels;
    }

    if (id) {
        labels = Array.from(document.querySelector(`label[for='${id}']`)));
    }

    while (element = element.parentNode) {
        if (element.tagName.toLowerCase() == "label") {
            labels.push(element);
        }  
    }

    return labels;
};

Even easier if you're using jQuery...

var getLabelsForInputElement = function(element) {
    var labels = $();
    var id = element.id;

    if (element.labels) {
        return element.labels;
    }

    id && (labels = $("label[for='" + id  + "']")));

    labels = labels.add($(element).parents("label"));

    return labels;
};

Earlier...

var labels = document.getElementsByTagName("LABEL"),
    lookup = {},
    i, label;

for (i = 0; i < labels.length; i++) {
    label = labels[i];
    if (document.getElementById(label.htmlFor)) {
        lookup[label.htmlFor] = label;
    }
}

Later...

var myLabel = lookup[myInput.id];

Snarky comment: Yes, you can also do it with JQuery. :-)


with jquery you could do something like

var nameOfLabel = someInput.attr('id');
var label = $("label[for='" + nameOfLabel + "']");

If you are using jQuery you can do something like this

$('label[for="foo"]').hide ();

If you aren't using jQuery you'll have to search for the label. Here is a function that takes the element as an argument and returns the associated label

function findLableForControl(el) {
   var idVal = el.id;
   labels = document.getElementsByTagName('label');
   for( var i = 0; i < labels.length; i++ ) {
      if (labels[i].htmlFor == idVal)
           return labels[i];
   }
}

The best answer works perfectly fine but in most cases, it is overkill and inefficient to loop through all the label elements.

Here is an efficent function to get the label that goes with the input element:

function getLabelForInput(id)
{
    var el = document.getElementById(id);
    if (!el)
        return null;
    var elPrev = el.previousElementSibling;
    var elNext = el.nextElementSibling;
    while (elPrev || elNext)
    {
        if (elPrev)
        {
            if (elPrev.htmlFor === id)
                return elPrev;
            elPrev = elPrev.previousElementSibling;
        }
        if (elNext)
        {
            if (elNext.htmlFor === id)
                return elNext;
            elNext = elNext.nextElementSibling;
        }
    }
    return null;
}

For me, this one line of code was sufficient:

el = document.getElementById(id).previousElementSibling;

In most cases, the label will be very close or next to the input, which means the loop in the above function only needs to iterate a very small number of times.


Answer from Gijs was most valuable for me, but unfortunately the extension does not work.

Here's a rewritten extension that works, it may help someone:

jQuery.fn.getLabels = function () {
    return this.map(function () {
        var parentLabels = $(this).parents('label').get();
        var associatedLabels = this.id ? associatedLabels = $("label[for='" + this.id + "']").get() : [];
        return parentLabels.concat(associatedLabels);
    });
};

$("label[for='inputId']").text()

This helped me to get the label of an input element using its ID.


document.querySelector("label[for=" + vHtmlInputElement.id + "]");

This answers the question in the simplest and leanest manner. This uses vanilla javascript and works on all main-stream proper browsers.


I have made for my own need, can be useful for somebody: JSFIDDLE

$("input").each(function () {
    if ($.trim($(this).prev('label').text()) != "") {
        console.log("\nprev>children:");
        console.log($.trim($(this).prev('label').text()));
    } else {
        if ($.trim($(this).parent('label').text()) != "") {
            console.log("\nparent>children:");
            console.log($.trim($(this).parent('label').text()));
        } else {
            if ($.trim($(this).parent().prev('label').text()) != "") {
                console.log("\nparent>prev>children:");
                console.log($.trim($(this).parent().prev('label').text()));
            } else {
                console.log("NOTFOUND! So set your own condition now");
            }
        }
    }
});

I am bit surprised no one is suggesting to use the CSS relationship method?

in a style sheet you can reference a label from the element selector:

<style>

//for input element with class 'YYY'
input.YYY + label {}

</style>

if the checkbox has an id of 'XXX' then the label would be found through jQuery by:

$('#XXX + label');

You can also apply .find('+ label') to return the label from a jQuery checkbox element, ie useful when looping:

$('input[type=checkbox]').each( function(){
   $(this).find('+ label');
});

with jquery you could do something like

var nameOfLabel = someInput.attr('id');
var label = $("label[for='" + nameOfLabel + "']");

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to label

How to set label size in Bootstrap How do I change the text size in a label widget, python tkinter Change grid interval and specify tick labels in Matplotlib Editing legend (text) labels in ggplot How to change Label Value using javascript React ignores 'for' attribute of the label element How to dynamically update labels captions in VBA form? why I can't get value of label with jquery and javascript? What does "for" attribute do in HTML <label> tag? Get Application Name/ Label via ADB Shell or Terminal