Himanshu SharmaSoftware engineer
Let’s talk

jQuery · Lesson 11 of 45

Attributes and properties: attr() and prop()

Read and change HTML attributes with jQuery .attr() and .removeAttr(), live element state with .prop(), and learn which to use for checked, disabled and href.

12 minReading and changing the pageUpdated 23 October 2026

By the end of this lessonChoose correctly between .attr() and .prop(), change links, images and form states, and avoid the classic checkbox bug.

Attributes and properties

Every HTML element is written with attributes:

html
<a id="docs" href="/learn/" title="Courses">Learn</a>
<input id="agree" type="checkbox" checked>

When the browser reads that HTML, it creates an element object in memory. That object has properties, many of which start out copied from the attributes. But they are not the same thing:

  • The attribute is the text in the HTML. It usually does not change unless code changes it.
  • The property is the live value. It changes as the user interacts: ticking a box changes the checked property, typing changes the value property.

jQuery gives you .attr() for attributes and .prop() for properties.

Reading and setting attributes

html
<a id="docs" href="/learn/" title="Courses">Learn</a>
<img id="logo" src="logo-small.png" alt="">

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  console.log("href:", $("#docs").attr("href"));
  console.log("missing:", $("#docs").attr("data-missing"));

  $("#docs").attr("href", "/learn/jquery/");
  $("#logo").attr({ src: "logo-large.png", alt: "Company logo", width: 200 });
  $("#docs").removeAttr("title");

  console.log("new href:", $("#docs").attr("href"));
  console.log("logo:", $("#logo").attr("src"), "|", $("#logo").attr("alt"), "|", $("#logo").attr("width"));
  console.log("title after removeAttr:", $("#docs").attr("title"));
</script>
result
href: /learn/
missing: undefined
new href: /learn/jquery/
logo: logo-large.png | Company logo | 200
title after removeAttr: undefined
  • .attr(name) reads an attribute; a missing attribute gives undefined.
  • .attr(name, value) sets it on every selected element.
  • .attr({ ... }) sets several at once.
  • .removeAttr(name) deletes it.

Use .attr() for things that really are attributes: href, src, alt, title, id, rel, target, aria-* and role.

The checkbox problem

Here is the bug that has confused many developers. The checkbox starts ticked in the HTML. Then the user (here, our code) unticks it:

html
<label><input id="agree" type="checkbox" checked> I agree</label>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $("#agree")[0].click();   // the user unticks it

  console.log("attr:", JSON.stringify($("#agree").attr("checked")));
  console.log("prop:", $("#agree").prop("checked"));
  console.log("is(':checked'):", $("#agree").is(":checked"));
</script>
result
attr: ""
prop: false
is(':checked'): false
  • .attr("checked") still reports the original HTML: the attribute is there (with an empty value), even though the box is no longer ticked.
  • .prop("checked") reports the live state: false.
  • .is(":checked") also checks the live state and reads nicely in if statements.

So to read whether a box is ticked, always use .prop("checked") or .is(":checked"). Older tutorials show .attr("checked"); that pattern is wrong and produces bugs as soon as the user changes the box.

Setting state with .prop()

The same rule applies when you change state. Use .prop() with true or false:

html
<label><input id="terms" type="checkbox"> I accept the terms</label>
<button id="send" disabled>Send</button>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $("#terms").on("change", function () {
    const accepted = $(this).prop("checked");
    $("#send").prop("disabled", !accepted);
    console.log("accepted:", accepted, "| button disabled:", $("#send").prop("disabled"));
  });
</script>
result
accepted: true | button disabled: false

The button starts disabled and becomes usable when the box is ticked. This "enable the button once the form is valid" pattern is everywhere.

The main boolean properties to manage with .prop() are checked, selected, disabled, readonly, required and multiple.

Properties that are not attributes

Some properties have no attribute at all, so only .prop() can read them:

html
<select id="size">
  <option>Small</option>
  <option selected>Medium</option>
  <option>Large</option>
</select>
<a id="rel" href="/learn/">Learn</a>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  console.log("selectedIndex:", $("#size").prop("selectedIndex"));
  console.log("tagName:", $("#size").prop("tagName"));
  console.log("href attr:", $("#rel").attr("href"));
  console.log("href prop ends with:", $("#rel").prop("href").endsWith("/learn/"));
</script>
result
selectedIndex: 1
tagName: SELECT
href attr: /learn/
href prop ends with: true

Notice the href difference: the attribute is exactly what you wrote (/learn/), while the property is the full resolved address including the page's origin. Use .attr("href") when you want what is written, and .prop("href") when you want the absolute URL.

A quick rule

You want to... Use
read or change href, src, alt, title, id, aria-*, data-* (as text) .attr()
read or change checked, selected, disabled, readonly .prop()
read or change a form field's current value .val() (next lesson)
remove an attribute entirely .removeAttr()

Common mistakes

  • Reading .attr("checked") to see if a box is ticked. Use .prop("checked").
  • Setting .attr("disabled", false). The attribute's presence is what disables the element, so this does not enable it. Use .prop("disabled", false) or .removeAttr("disabled").
  • Using .removeProp() on built-in properties such as checked. It cannot remove them; set them to false instead.
  • Using .attr() for data you want as numbers or objects. The .data() lesson shows a better tool.

Exercise

Make a Show password checkbox. When it is ticked, change the password field's type attribute to text; when unticked, back to password.

Show one possible answer
html
<input id="pw" type="password" value="secret123">
<label><input id="show" type="checkbox"> Show password</label>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $("#show").on("change", function () {
    $("#pw").attr("type", $(this).prop("checked") ? "text" : "password");
  });
</script>

The type is an attribute, so .attr() changes it; the checkbox state is a property, so .prop() reads it.

Key points

  • Attributes are what is written in the HTML; properties are the live values on the element object in the browser.
  • Use .attr() for attributes such as href, src, alt, title, id and aria-*; use .removeAttr() to delete one.
  • Use .prop() for live state: checked, selected, disabled and the current value.
  • .attr("checked") reports the original HTML, not whether the box is ticked now; .prop("checked") gives true or false.

Check yourself

1. How do you tell whether a checkbox is ticked right now?
2. Which method changes an image's src attribute?
3. How do you disable a button with jQuery?
4. What does .attr("data-missing") return when the attribute does not exist?