So jQuery 1.6 has the new function prop().

$(selector).click(function(){
    //instead of:
    this.getAttribute('style');
    //do i use:
    $(this).prop('style');
    //or:
    $(this).attr('style');
})

or in this case do they do the same thing?

And if I do have to switch to using prop(), all the old attr() calls will break if i switch to 1.6?

UPDATE

selector = '#id'

$(selector).click(function() {
    //instead of:
    var getAtt = this.getAttribute('style');
    //do i use:
    var thisProp = $(this).prop('style');
    //or:
    var thisAttr = $(this).attr('style');

    console.log(getAtt, thisProp, thisAttr);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<div id='id' style="color: red;background: orange;">test</div>

(see also this fiddle: http://jsfiddle.net/maniator/JpUF2/)

The console logs the getAttribute as a string, and the attr as a string, but the prop as a CSSStyleDeclaration, Why? And how does that affect my coding in the future?

14 upvote
  flag
This will be of definite interest: books.google.ca/… – user1385191
21 upvote
  flag
@Neal, it's because this change transcends jQuery. The difference between HTML attributes and DOM properties is massive. – user1385191
upvote
  flag
@Matt but what was attr returning before 1.6? wasnt it always returning a string? – Neal
upvote
  flag
.attr() has changed dramatically in jQuery 1.6. Here the problem is explained: edgarinvillegas.wordpress.com/2011/05/10/… – Edgar Villegas Alvarado
upvote
  flag
@Edgar, alot of the problems were fixed in jQuery 1.6.1 – Neal
6 upvote
  flag
It makes me sad to see jQuery's reverted the changes. They're heading in the wrong direction. – user1385191
upvote
  flag
@Matt, did you see jResig's latest blog post? – Neal
3 upvote
  flag
@Neal. Yes, and it just complicates the problem further instead of separating the two methods. – user1385191
upvote
  flag
Depricated attr in 1.9.0+ removed. – Mark Schultheiss
1 upvote
  flag
@MarkSchultheiss I am not sure what you are talking about.... – Neal
2 upvote
  flag
AFAIK as of 1.9 attr() won't do "magic" for properties anymore. So .attr('checked', false) will not do what one might expect. – ThiefMaster
upvote
  flag
@ThiefMaster where is the source for this? – Neal
upvote
  flag
@Neal - the access to properties via attr() has been removed for some things starting with 1.9.0 jQuery jquery.com/upgrade-guide/1.9 scroll down and read .attr() versus .prop() boolean attributes such as checked and disabled on a checkbox are affected by this change – Mark Schultheiss
upvote
  flag
see this fiddle jsfiddle.net/h682v/4, change it to 1.9.1 version, and see the properties for disabled are not changed using attr - check/uncheck of those two at the bottom are still accessible until you change the attr() stuff to prop() - one instance of the change. – Mark Schultheiss
1 upvote
  flag
Your collective knowledge of jQuery is impressive. However when someone says x vs y they just want a simple comparison, when to use one and not the other. They're not after a deep dive. That's why they're here not reading the documentation. All terrible answers – BritishDeveloper
5 upvote
  flag
@BritishDeveloper the answer is more complicated than simply stating always use x or y because it depends on what you intend to get. Do you want the attribute, or do you want the property? they are two very different things. – Kevin B
upvote
  flag
upvote
  flag
@Bergi that looks like a duplicate to this question – Neal
upvote
  flag
@Neal Dunno, it doesn't focus as much on jQuery as this question here, so it might often be better dupe target. – Bergi
upvote
  flag
@Bergi the answers here actually do not even reference jquery that much and is basically the canonical point for don properties vs attributes – Neal

16 Answers 11

All is in the doc :

The difference between attributes and properties can be important in specific situations. Before jQuery 1.6, the .attr() method sometimes took property values into account when retrieving some attributes, which could cause inconsistent behavior. As of jQuery 1.6, the .prop() method provides a way to explicitly retrieve property values, while .attr() only retrieves attributes.

So use prop !

2 upvote
  flag
So that mean when i switch to 1.6, alot of things will break?? – Neal
3 upvote
  flag
+1 for RTFM. A quick note about attributes versus properties would be a good addition though. – Jason McCreary
upvote
  flag
No, it's just an inconsistent behavior, if it works before, it will always works with jQuery 1.6, it's just that prop is safer ;) – Arnaud F.
6 upvote
  flag
I seem to recall .$.attr() retrieving properties most of the time I worked with it, not "sometimes". The confusion caused by it is still resonant today. Sadly, I'm having a lot of trouble finding a definitive read on HTML attributes vs. DOM properties, so I might write an answer here in a bit. – user1385191
3 upvote
  flag
@Arnaud-f Not true. All code previous to 1.6 that uses attr('checked') to check checkboxes will now be broken. – CaptSaltyJack
upvote
  flag
@Neal I'm in the same boat as you. If I were you, I'd stick with 1.5 for a while. If you absolutely want to upgrade to 1.6, and you've got live web sites you're dealing with, I would pull all your files into a test environment with 1.6 and make sure all the code works, search for all instances of .attr() and see if it makes sense the way you're using it. If not, replace with .prop(). Test, test, test. – CaptSaltyJack
upvote
  flag
@CaptSaltyJack that is rly rly annoying.... – Neal
3 upvote
  flag
@Matt McDonald: What kind of "...trouble finding a definitive read on HTML attributes vs. DOM properties..." do you mean? Properties (reflected and otherwise) are described in the DOM2 HTML specification; you may also need to refer to the DOM2 and DOM3 specs. – T.J. Crowder

This change has been a long time coming for jQuery. For years, they've been content with a function named attr() that mostly retrieved DOM properties, not the result you'd expect from the name. The segregation of attr() and prop() should help alleviate some of the confusion between HTML attributes and DOM properties. $.fn.prop() grabs the specified DOM property, while $.fn.attr() grabs the specified HTML attribute.

To fully understand how they work, here's an extended explanation on the difference between HTML attributes and DOM properties.:

HTML Attributes

Syntax:

<body onload="foo()">

Purpose: Allows markup to have data associated with it for events, rendering, and other purposes.

Visualization: HTML Attributes The class attribute is shown here on the body. It's accessible through the following code:

var attr;
attr = document.body.getAttribute("class");
//IE 8 Quirks and below
attr = document.body.getAttribute("className");

Attributes are returned in string form and can be inconsistent from browser to browser. However, they can be vital in some situations. As exemplified above, IE 8 Quirks Mode (and below) expects the name of a DOM property in get/set/removeAttribute instead of the attribute name. This is one of many reasons why it's important to know the difference.

DOM Properties

Syntax:

document.body.onload = foo;

Purpose: Gives access to properties that belong to element nodes. These properties are similar to attributes, but are only accessible through JavaScript. This is an important difference that helps clarify the role of DOM properties. Please note that attributes are completely different from properties, as this event handler assignment is useless and won't receive the event (body doesn't have an onload event, only an onload attribute).

Visualization: DOM Properties

Here, you'll notice a list of properties under the "DOM" tab in Firebug. These are DOM properties. You'll immediately notice quite a few of them, as you'll have used them before without knowing it. Their values are what you'll be receiving through JavaScript.

Documentation

Example

HTML: <textarea id="test" value="foo"></textarea>

JavaScript: alert($('#test').attr('value'));

In earlier versions of jQuery, this returns an empty string. In 1.6, it returns the proper value, foo.

Without having glanced at the new code for either function, I can say with confidence that the confusion has more to do with the difference between HTML attributes and DOM properties, than with the code itself. Hopefully, this cleared some things up for you.

-Matt

2 upvote
  flag
@Matt this explains nothing about prop() in jQuery.... – Neal
7 upvote
  flag
$.prop() gets DOM properties, $.attr() gets HTML attributes. I'm trying to bridge the gap psychologically so you can understand the difference between the two. – user1385191
upvote
  flag
@Matt, you did not state that in your answer... Can you explain what prop() does please? – Neal
7 upvote
  flag
Boy, I am confused now too. So $('#test').prop('value') does not return anything? Nor does .attr('checked') for a checkbox? But it used to? Now you'd have to change it to prop('checked')? I don't understand the need for this distinction - why is it important to differentiate between HTML attributes and DOM properties? What is the common use-case that made this change "a long time coming"? What is wrong with abstracting the distinction between the two away, since it seems like their use-cases mostly overlap? – BlueRaja - Danny Pflughoeft
upvote
  flag
In your example at the end, I think attr in alert($('#test').attr('value')); is meant to be prop. – Amy B
3 upvote
  flag
@BlueRaja: because there is a serious underlying difference between the two concepts which, if you brush it under the carpet like jQuery used to, results in unexpected failures. value is one of the most obvious cases, since the value property will give you the current value of a field, but the value attribute will give you the original value that was declared in the value="..." attribute, which is actually the defaultValue property. (Though this particular case gets confused again by bugs in IE<9.) – bobince
upvote
  flag
@bobince: So what happens if you set .attr('value', 'something')? Is the value of the current field changed, or is only the "original value" changed? If the latter, that seems like a huge mistake that I can see causing a lot more problems than it fixed... (and if the former, I think it's confusing that changing the attribute changes the property, but not vice-versa) – BlueRaja - Danny Pflughoeft
upvote
  flag
@BlueRaja: The former. In most cases, attr() pre-1.6 maps to the property. – Tim Down
4 upvote
  flag
@BlueRaja: The answer to that is even more complicated. :-) Setting attr('value', ...) in jQuery <1.6 sets the property, so the current value changes and the default value doesn't. In 1.6 it sets the attribute, so in theory the default value changes and the current value doesn't. However, there are (more) browser inconsistencies over what exactly setting the value attribute does. In IE it sets the current value as well; in some browsers it only sets the current value if the current value has not already been set before. [cries] – bobince
upvote
  flag
@Matt your image seems to have disappeared... – Neal
upvote
  flag
Just like @Quentin said, "Attributes are defined by HTML. Properties are defined by DOM." The simplest version I have read. – Alan Dong
upvote
  flag
minus1 Weak example: <textarea/> doesn’t use a value attribute to set its initial content. – ᴠɪɴᴄᴇɴᴛ
up vote 1670 down vote accepted

Update 1 November 2012

My original answer applies specifically to jQuery 1.6. My advice remains the same but jQuery 1.6.1 changed things slightly: in the face of the predicted pile of broken websites, the jQuery team reverted attr() to something close to (but not exactly the same as) its old behaviour for Boolean attributes. John Resig also blogged about it. I can see the difficulty they were in but still disagree with the recommendation to prefer attr().

Original answer

If you've only ever used jQuery and not the DOM directly, this could be a confusing change, although it is definitely an improvement conceptually. Not so good for the bazillions of sites using jQuery that will break as a result of this change though.

I'll summarize the main issues:

  • You usually want prop() rather than attr().
  • In the majority of cases, prop() does what attr() used to do. Replacing calls to attr() with prop() in your code will generally work.
  • Properties are generally simpler to deal with than attributes. An attribute value may only be a string whereas a property can be of any type. For example, the checked property is a Boolean, the style property is an object with individual properties for each style, the size property is a number.
  • Where both a property and an attribute with the same name exists, usually updating one will update the other, but this is not the case for certain attributes of inputs, such as value and checked: for these attributes, the property always represents the current state while the attribute (except in old versions of IE) corresponds to the default value/checkedness of the input (reflected in the defaultValue / defaultChecked property).
  • This change removes some of the layer of magic jQuery stuck in front of attributes and properties, meaning jQuery developers will have to learn a bit about the difference between properties and attributes. This is a good thing.

If you're a jQuery developer and are confused by this whole business about properties and attributes, you need to take a step back and learn a little about it, since jQuery is no longer trying so hard to shield you from this stuff. For the authoritative but somewhat dry word on the subject, there's the specs: DOM4, HTML DOM, DOM Level 2, DOM Level 3. Mozilla's DOM documentation is valid for most modern browsers and is easier to read than the specs, so you may find their DOM reference helpful. There's a section on element properties.

As an example of how properties are simpler to deal with than attributes, consider a checkbox that is initially checked. Here are two possible pieces of valid HTML to do this:

<input id="cb" type="checkbox" checked>
<input id="cb" type="checkbox" checked="checked">

So, how do you find out if the checkbox is checked with jQuery? Look on Stack Overflow and you'll commonly find the following suggestions:

  • if ( $("#cb").attr("checked") === true ) {...}
  • if ( $("#cb").attr("checked") == "checked" ) {...}
  • if ( $("#cb").is(":checked") ) {...}

This is actually the simplest thing in the world to do with the checked Boolean property, which has existed and worked flawlessly in every major scriptable browser since 1995:

if (document.getElementById("cb").checked) {...}

The property also makes checking or unchecking the checkbox trivial:

document.getElementById("cb").checked = false

In jQuery 1.6, this unambiguously becomes

$("#cb").prop("checked", false)

The idea of using the checked attribute for scripting a checkbox is unhelpful and unnecessary. The property is what you need.

  • It's not obvious what the correct way to check or uncheck the checkbox is using the checked attribute
  • The attribute value reflects the default rather than the current visible state (except in some older versions of IE, thus making things still harder). The attribute tells you nothing about the whether the checkbox on the page is checked. See http://jsfiddle.net/VktA6/49/.
upvote
  flag
So if i want to upgrade i have to go back and change all references of attr to prop? – Neal
upvote
  flag
@Neal: Yes, I suspect that will work in most cases, although not having studied every single part of the jQuery attr() and prop() code I can't guarantee it will work in every single case. – Tim Down
upvote
  flag
@TimDown, so now it will be easier to put an input element back to its initial state? – Neal
upvote
  flag
@Neal: "So if i want to upgrade i have to go back and change all references of attr to prop?" Not all, no. Many, probably most, but probably not all. – T.J. Crowder
2 upvote
  flag
@T.J.Crowder, then which ones? – Neal
8 upvote
  flag
@Neal: If you want to know what properties DOM elements have and how attributes may seed their values, keep these links to hand: The DOM2 HTML specification, the DOM2 spec, and DOM3 spec. The indexes in each case are excellent and link you straight to a thorough description of the property, where its value comes from, etc. – T.J. Crowder
upvote
  flag
@T.J.Crowder but if i do upgrade, wasn't attr always a string? so it should not matter if i change it or not? prop is not a string i get that now, its a DOM element – Neal
upvote
  flag
@Neal: (We cross-commented.) Actually, the only real example I'm coming up with is your own data-xyz attributes, which you'd get with attr unless you want to use jQuery's data, which I avoided initially but may start using as of recent improvements to it. Another advantage of knowing your properties is that you can make your code more efficient. If you've ever written var link = $(this).attr("href") to get the href of an anchor in an event handler, once you know your reflected properties, you'll feel confident writing var link = this.href instead. – T.J. Crowder
upvote
  flag
@T.J.Crowder so this.href or will i be doing $(this).prop('href')? – Neal
1 upvote
  flag
@Neal: No, look at the docs: prop returns a string. It's a string it gets from a property on the underlying DOM element (such as element.href), rather than from an attribute on the underlying DOM element (such as element.getAttribute("href")). attr usually did that as well. In most cases (the vast majority), just change prop to attr and all is well. Only when you know you really, really want the actual attribute value would you use attr. This is going to be rare. – T.J. Crowder
upvote
  flag
@T.J.Crowder it doesnt return a string! look at my fiddle... – Neal
upvote
  flag
@Neal: "so this.href or will i be doing $(this).prop('href')" Whichever you prefer, they'll have the same result. The latter is more verbose and involves several unnecessary function calls, but has the advantage that you don't have to worry about some special cases that jQuery handles for you. – T.J. Crowder
upvote
  flag
@T.J.Crowder i think our comments are getting crossed... – Neal
upvote
  flag
@Neal: Re your fiddle. You happened to pick a tricky one ("style"). (I'm surprised the docs say it returns a string, they should account for compound properties like style.) The style property references an object with style information. It's one of very, very few properties like that, the vast majority are either strings or numbers. (What did attr used to return for "style"?) – T.J. Crowder
upvote
  flag
@T.J.Crowder i guess i picked an interesting one out of the hat. but if usually it returns a string, what makes it different from attr in those cases? – Neal
3 upvote
  flag
@Neal: Re what makes it different: The source and nature of the information. Look at Tim's value example, for instance. A function called attr that retrieves the property value rather than the attribute "value" doesn't make much sense (and they can be different). Going forward, attr doing attributes and prop doing properties will be clearer, though the transition will be painful for some. Don't take this the wrong way, there's nothing like stepping back and reading the specs to get an idea of what properties are. – T.J. Crowder
1 upvote
  flag
@T.J.Crowder So what your saying is that attr is the hardcoded values and prop is the dynamic, changing values throughout the DOM? – Neal
upvote
  flag
@Neal: Gah, sorry, value is a bad example, forget I mentioned it. – T.J. Crowder
upvote
  flag
@T.J.Crowder so can you give an answer that explains it better? right now i think @TimDown's answer is good, but not the best – Neal
upvote
  flag
@Neal: "So what your saying is that attr is the hardcoded values and prop is the dynamic, changing values throughout the DOM?" Well, attributes can be changed too (via attr or the underlying DOM setAttribute function, or -- confusingly -- because certain properties, when changed, change the underlying attribute). (cont'd) – T.J. Crowder
upvote
  flag
@Neal: T.J. is making some excellent points. I would suggest you go off and experiment with manipulating the DOM directly using properties, with the specs and maybe a jQuery-free book or tutorial for company. It's not actually as hard as you may think. – Tim Down
2 upvote
  flag
@T.J.Crowder can you please give a full answer as opposed to these broken up comments? it might be more easy to read for future users – Neal
40 upvote
  flag
@Neal: A DOM element is an object. Properties are properties of that object, just like any other programming object. Some of those props get their initial values from the attributes in the markup, which are also stored on the DOM object in a separate map of attributes. In most cases, writing to a prop only changes the prop, although sadly there are some props that write any changes through to the underlying attr (value for instance), but let's try to mostly ignore that. 99% of the time, you want to work with props. If you need to work with an actual attribute, you'll probably know that. – T.J. Crowder
upvote
  flag
@T.J. Changing the value property of an input doesn't change its value attribute in modern browsers. – Tim Down
3 upvote
  flag
@Tim: "Changing the value property of an input doesn't change its value attribute in modern browsers" I didn't think it did, which is why I started to use it as an example, but when I started coding up the example, darned if it didn't get updated on Chrome, Firefox, Opera, IE... - jsbin.com/ahire4 Turns out that's because I was using an input[type="button"] for my experiment. It doesn't update the attribute on a input[type="text"] - jsbin.com/ahire4/2 Talk about convoluted!! Not just the element, but the type of it... – T.J. Crowder
upvote
  flag
@T.J. Ah yes, I admit I was thinking only of text inputs. – Tim Down
upvote
  flag
@T.J.Crowder That is because a input[type="button"]'s dirty value flag cannot be true. – Esailija
upvote
  flag
Some performance testing related to this answer can be found here. jsperf.com/prop-vs-ischecked/5 – Blowsie
upvote
  flag
for jQuery 1.9.1 a selector such as $('#chk').checked returns undefined - worked prior to 1.9.0, filed bug as it seems it should work, .prop("checked") works as expected. – Mark Schultheiss
5 upvote
  flag
$('#chk').checked never worked... That is not proper jQuery at all... – Neal
upvote
  flag
this fiddle using 1.4.2 says it did work with the form $(selector)[0].checked jsfiddle.net/h682v/4 – Mark Schultheiss
1 upvote
  flag
I stand corrected :) $('#chk')[0].checked is the proper form – Mark Schultheiss
upvote
  flag
I updated the jsfiddle to include a comparison between the native Javascript and jQuery's prop, attr, and is(":checked"). jsfiddle.net/6EE7k/2 – Luke
upvote
  flag
So, years later, and well out of scope: attr does not return the original value of the disabled attribute! Neither does getAttribute(). Anybody happen to know how to do so? – Charles Wood
1 upvote
  flag
@CharlesWood: The disabled attribute is kept in sync with the disabled property. The original value is not accessible after the disabledness has been changed. – Tim Down
upvote
  flag
So many Thanks, This link may useful too specially JSFiddle test: jq4you.blogspot.com/2013/04/jquery-attr-vs-prop-difference.h‌​tml – QMaster

I think Tim said it quite well, but let's step back:

A DOM element is an object, a thing in memory. Like most objects in OOP, it has properties. It also, separately, has a map of the attributes defined on the element (usually coming from the markup that the browser read to create the element). Some of the element's properties get their initial values from attributes with the same or similar names (value gets its initial value from the "value" attribute; href gets its initial value from the "href" attribute, but it's not exactly the same value; className from the "class" attribute). Other properties get their initial values in other ways: For instance, the parentNode property gets its value based on what its parent element is; an element always has a style property, whether it has a "style" attribute or not.

Let's consider this anchor in a page at http://example.com/testing.html:

<a href='foo.html' class='test one' name='fooAnchor' id='fooAnchor'>Hi</a>

Some gratuitous ASCII art (and leaving out a lot of stuff):

+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
|             HTMLAnchorElement             |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
| href:       "http://example.com/foo.html" |
| name:       "fooAnchor"                   |
| id:         "fooAnchor"                   |
| className:  "test one"                    |
| attributes:                               |
|    href:  "foo.html"                      |
|    name:  "fooAnchor"                     |
|    id:    "fooAnchor"                     |
|    class: "test one"                      |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+

Note that the properties and attributes are distinct.

Now, although they are distinct, because all of this evolved rather than being designed from the ground up, a number of properties write back to the attribute they derived from if you set them. But not all do, and as you can see from href above, the mapping is not always a straight "pass the value on", sometimes there's interpretation involved.

When I talk about properties being properties of an object, I'm not speaking in the abstract. Here's some non-jQuery code:

var link = document.getElementById('fooAnchor');
alert(link.href);                 // alerts "http://example.com/foo.html"
alert(link.getAttribute("href")); // alerts "foo.html"

(Those values are as per most browsers; there's some variation.)

The link object is a real thing, and you can see there's a real distinction between accessing a property on it, and accessing an attribute.

As Tim said, the vast majority of the time, we want to be working with properties. Partially that's because their values (even their names) tend to be more consistent across browsers. We mostly only want to work with attributes when there is no property related to it (custom attributes), or when we know that for that particular attribute, the attribute and the property are not 1:1 (as with href and "href" above).

The standard properties are laid out in the various DOM specs:

These specs have excellent indexes and I recommend keeping links to them handy; I use them all the time.

Custom attributes would include, for instance, any data-xyz attributes you might put on elements to provide meta-data to your code (now that that's valid as of HTML5, as long as you stick to the data- prefix). (Recent versions of jQuery give you access to data-xyz elements via the data function, but that function is not just an accessor for data-xyz attributes [it does both more and less than that]; unless you actually need its features, I'd use the attr function to interact with data-xyz attribute.)

The attr function used to have some convoluted logic around getting what they thought you wanted, rather than literally getting the attribute. It conflated the concepts. Moving to prop and attr was meant to de-conflate them. Briefly in v1.6.0 jQuery went too far in that regard, but functionality was quickly added back to attr to handle the common situations where people use attr when technically they should use prop.

30 upvote
  flag
+1, well explained. I didn't quite have the patience to step back and explain all that for an SO answer. Maybe time for a blog post... – Tim Down
9 upvote
  flag
Both you and Tim did a great job on elaborating on the intricacies of attributes/properties. I'll definitely be reading a lot more specs from now on. – user1385191
upvote
  flag
Wow. that new 1.6.1 update really nullifies this question a bit.. (but not much) but that link basically answers it now – Neal
upvote
  flag
It didn't nullify it for me, I just fixed a bug using jquery1.7 where I was setting .attr('class', 'bla') and it wasn't working where .prop('className', 'bla') worked – PandaWood
upvote
  flag
@PandaWood: .attr('class', 'bla') works as expected for me in 1.7.0, 1.7.1, and 1.7.2 on Chrome 17, Firefox 11, Opera 11, IE6, IE8, IE9, and Safari 5. – T.J. Crowder
upvote
  flag
Thanks, there must be something specific in my case, let me check this & come back with a test case. But changing the code as we have it right now, to simply "prop/className", instead of "attr" fixes a massive bug for us that hit when we moved from jquery1.4 to 1.7 - on all browsers – PandaWood
upvote
  flag
@T.J.Crowder why then does .attr('value') return on for radio buttons when the value attribute is not specified in the markup? – Flash
upvote
  flag
@Andrew: Because very quickly after splitting attr and prop, they had to backpedal markedly and make attr do a lot of prop stuff. See the last paragraph of the answer. – T.J. Crowder
upvote
  flag
@T.J.Crowder So what is the safest, cross browser way to check a value attribute (or any other attribute)? .attr doesn't work nor does .val. Are element.hasAttribute/element.getAttribute implemented properly in all browsers? – Flash
upvote
  flag
@Andrew: The value attribute is a special case, because IE8 and earlier (and IE9 in "compatibility mode") just plain get it wrong. If you want to find out what the value of the attribute was when the markup was loaded (as opposed to any updated value you or the user may have set since), even getAttribute and the attributes NamedNodeMap will be the current value on those (other browsers understand the distinction). The good news is you can get there, via the defaultValue property of the element. I'm curious, why do you want the value of the attribute rather than the current value? – T.J. Crowder
upvote
  flag
@T.J.Crowder thanks - I am working on some code as part of a framework to set value attributes for certain form elements if they have not been specified in the markup - for example <option>foo</option> --> <option value='foo'>foo</option>. //allinonescript.com/questions/11427239/… – Flash
upvote
  flag
@Andrew: I see. Well, good luck, IE7 and earlier don't even have hasAttribute, and getAttribute('value') returns "" if there's no value attribute (rather than null, which is what it should return, and does for other ones). You might find this fun to play with: jsbin.com/aneyap/6 IE has other getAttribute issues as well, such as the fact that getAttribute('class') is always null (you have to use 'className', which doesn't make any sense in getAttribute although of course that's what the reflected property is called). – T.J. Crowder
2 upvote
  flag
@T.J.Crowder re: .data - it'll read the default value of the attribute, if present, but if you write to it, it'll change a hidden property of the element, and not update the attribute. – Alnitak
upvote
  flag
@Alnitak: Right, it's asymmetrical. The first time you use it on an element, it seeds itself from the data-* attributes, but there's never any write-back nor does it keep things in sync. (I never use it for data-* attributes for exactly this reason.) – T.J. Crowder
upvote
  flag
@T.J.Crowder Thanks for the great answer. Very helpful. However, it did leave me with one question. In your answer above you said: a number of properties write back to the attribute they derived from if you set them. But not all do, ... so that got me thinking, then what happens when you set an attribute that may not have a corresponding DOM counterpart? Does it then just set/create a new one? or does it just leave it as an attribute since it would need to be in the specified list of defined properties (if there is one) to get written as a property? – johntrepreneur
upvote
  flag
@T.J.Crowder For instance, there is a jquery bug regarding an error that is encountered in IE7 mode when attempting to use .attr in conjuction with certain attributes (aria-autocomplete). After reading how attr and prop are somewhat interchangable I tried using .prop as a workaround to set the aria attributes .prop('aria-autocomplete', 'list') and it seems to work although I'm not 100% certain of all cases and side effects. Is this a valid use of .prop? – johntrepreneur

It's just the distinction between HTML attributes and DOM objects that causes a confusion. For those that are comfortable acting on the DOM elements native properties such a this.src this.value this.checked etc, .prop is a very warm welcome to the family. For others, it's just an added layer of confusion. Let's clear that up.

The easiest way to see the difference between .attr and .prop is the following example:

<input blah="hello">
  1. $('input').attr('blah'): returns 'hello' as expected. No suprises here.
  2. $('input').prop('blah'): returns undefined -- because it's trying to do [HTMLInputElement].blah -- and no such property on that DOM object exists. It only exists in the scope as an attribute of that element i.e. [HTMLInputElement].getAttribute('blah')

Now we change a few things like so:

$('input').attr('blah', 'apple');
$('input').prop('blah', 'pear');
  1. $('input').attr('blah'): returns 'apple' eh? Why not "pear" as this was set last on that element. Because the property was changed on the input attribute, not the DOM input element itself -- they basically almost work independently of each other.
  2. $('input').prop('blah'): returns 'pear'

The thing you really need to be careful with is just do not mix the usage of these for the same property throughout your application for the above reason.

See a fiddle demonstrating the difference: http://jsfiddle.net/garreh/uLQXc/


.attr vs .prop:

Round 1: style

<input style="font:arial;"/>
  • .attr('style') -- returns inline styles for the matched element i.e. "font:arial;"
  • .prop('style') -- returns an style declaration object i.e. CSSStyleDeclaration

Round 2: value

<input value="hello" type="text"/>   

$('input').prop('value', 'i changed the value');
  • .attr('value') -- returns 'hello' *
  • .prop('value') -- returns 'i changed the value'

* Note: jQuery for this reason has a .val() method, which internally is equivalent to .prop('value')

upvote
  flag
@Neal becaue it gives reference to the structure of the jquery functions better. "$('input').prop('blah'): returns undefined -- because it's trying to do [HTMLInputElement].blah -- and no such property on that DOM object exists. It only exists in the scope as an attribute of that element i.e. [HTMLInputElement].getAttribute('blah')" – Uğur Gümüşhan
2 upvote
  flag
Seems different from the doc, api.jquery.com/prop: "The .prop() method should be used to set disabled and checked instead of the .attr() method. The .val() method should be used for getting and setting value." – swan
upvote
  flag
I do not understand why when class or style property is changed attribute is changed as well jsfiddle.net/featon/Jbw6m/3 ? – Damian

A property is in the DOM; an attribute is in the HTML that is parsed into the DOM.

Further detail

If you change an attribute, the change will be reflected in the DOM (sometimes with a different name).

Example: Changing the class attribute of a tag will change the className property of that tag in the DOM. If you have no attribute on a tag, you still have the corresponding DOM property with an empty or a default value.

Example: While your tag has no class attribute, the DOM property className does exist with a empty string value.

edit

If you change the one, the other will be changed by a controller, and vice versa. This controller is not in jQuery, but in the browser's native code.

13 upvote
  flag
@yunzen it is a clear, concise, and simple correct answer. You definitely deserve it :-) – Neal
upvote
  flag
So does this mean it is better to update the attribute because then you're ensuring that the attribute and property both get updated and are in alignment? – Luke
1 upvote
  flag
@Luke the DOM is the inner technical representation, the model. The HTML attributes are an outer representation, a view. If you change the one, the other will be changed by a controller, and vice versa. – HerrSerker
1 upvote
  flag
@Luke Look at this: jsfiddle.net/Pms3W – HerrSerker
upvote
  flag
@HerrSerker So they're both kept in sync via a controller? I assume this is just within jQuery's attr and prop methods? Here's a modification of your fiddle where I explore this more - jsfiddle.net/v8wRy - and so far they seem to be equivalent. – Luke
upvote
  flag
thanks.good answer.but can u explain when to use .prop() and .attr() – PSR
upvote
  flag
@PSR Read the Attributes vs Properties section on jquery.prop() – HerrSerker
upvote
  flag
Upvoted. Quoted and linked to your answer (HTML vs. DOM), hope you don't mind. – basic6
3 upvote
  flag
"If you change the one, the other will be changed by a controller, and vice versa. This controller is not in jQuery, but in the browsers' native code." This is not true for most attributes/properties. For the majority it’s only a one-way translation where an attribute determines the initial value of the corresponding property. The top two answers explain this in detail. – ᴠɪɴᴄᴇɴᴛ
upvote
  flag
@Vincent. I don't see, where the top two answers say something contrary to my answer. Of course most attributes are the initial values of the corresponding DOM properties. But they are mutually dependent. Try something like jQuery('p').prop('className', 'foo'); in Chrome console and you will see, how every paragraph get's thg class attribute of 'foo'. Of course not in the source code, which comes from the server. That is a constant. – HerrSerker
1 upvote
  flag
This is real correct answer. Nothing complicated. I don't need a master's thesis or care how it's coded in the background. Just what is the difference, int a nutshell, and this answer explains that. – user3621633

Usually you'll want to use properties. Use attributes only for:

  1. Getting a custom HTML attribute (since it's not synced with a DOM property).
  2. Getting a HTML attribute that doesn't sync with a DOM property, e.g. get the "original value" of a standard HTML attribute, like <input value="abc">.

dirty checkedness is an example where the difference is observable.

To see it, run the following snippet and:

  • click the button. Both checkboxes got checked.
  • uncheck both checkboxes.
  • click the button again. Only the prop checkbox got checked. BANG!

$('button').on('click', function() {
  $('#attr').attr('checked', 'checked')
  $('#prop').prop('checked', true)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>attr <input id="attr" type="checkbox"></label>
<label>prop <input id="prop" type="checkbox"></label>
<button type="button">Set checked attr and prop.</button>

For some attributes like disabled on button, adding or removing the content attribute disabled="disabled" always toggles the property (called IDL attribute in HTML5) because http://www.w3.org/TR/html5/forms.html#attr-fe-disabled says:

The disabled IDL attribute must reflect the disabled content attribute.

so you might get away with it, although it is ugly since it modifies HTML without need.

For other attributes like checked="checked" on input type="checkbox", things break, because once you click on it, it becomes dirty, and then adding or removing the checked="checked" content attribute does not toggle checkedness anymore.

This is why you should use mostly .prop, as it affects the effective property directly, instead of relying on complex side-effects.

upvote
  flag
For completeness also try these variations: 1) Before clicking the button check and then uncheck the first checkbox 2) (For this one you will need to change the snippet) Give the first input a checked attribute: checked="checked" – ᴠɪɴᴄᴇɴᴛ

TL;DR

Use prop() over attr() in the majority of cases.

A property is the current state of the input element. An attribute is the default value.

A property can contain things of different types. An attribute can only contain strings

1 upvote
  flag
if possible to come with few easy sample of what u r saying and also show when to use prop() and when to go for attr(). waiting for answer :) – Mou

attributes -> HTML

properties -> DOM

8 upvote
  flag
I know what you want to say, but HTML is a markup language, and the DOM a representation created out of the HTML. A DOMElement has both attributes and properties. – t.niese
upvote
  flag
@t.niese, attirbutes also one of the property of DOM – NkS
upvote
  flag
The short answer is simple. – Nabi K.A.Z.

attributes are in your HTML text document/file (== imagine this is the result of your html markup parsed), whereas
properties are in HTML DOM tree (== basically an actual property of some object in JS sense).

Importantly, many of them are synced (if you update class property, class attribute in html will also be updated; and otherwise). But some attributes may be synced to unexpected properties - eg, attribute checked corresponds to property defaultChecked, so that

  • manually checking a checkbox will change .prop('checked') value, but will not change .attr('checked') and .prop('defaultChecked') values
  • setting $('#input').prop('defaultChecked', true) will also change .attr('checked'), but this will not be visible on an element.

Rule of thumb is: .prop() method should be used for boolean attributes/properties and for properties which do not exist in html (such as window.location). All other attributes (ones you can see in the html) can and should continue to be manipulated with the .attr() method. (http://blog.jquery.com/2011/05/10/jquery-1-6-1-rc-1-released/)

And here is a table that shows where .prop() is preferred (even though .attr() can still be used).

table with preferred usage


Why would you sometimes want to use .prop() instead of .attr() where latter is officially adviced?

  1. .prop() can return any type - string, integer, boolean; while .attr() always returns a string.
  2. .prop() is said to be about 2.5 times faster than .attr().
upvote
  flag
something has been changed, like these: $('#myImageId').prop('src', 'http://example.com/img.png'), var class = $('.myDivClass').prop('class'), or $('#myTextBox').prop('type', 'button'). And so on... – user4090029
upvote
  flag
@Mr.Wolf, sorry? – lakesare
upvote
  flag
@Mr.Wolf, sorry, I stil don't get what you mean. what has 'changed'? syntax has always been like like that. – lakesare
upvote
  flag
I think the table in your answer is unnecessary. Because .prop() works fine with all of the properties. You don't wanna mark all properties in .prop() column, do you? – user4090029
upvote
  flag
@Mr.Wolf, I think it is necessary, because, as already stated, it 'shows where .prop() is preferred (even though .attr() can still be used)' – lakesare
upvote
  flag
I usually use .attr() for defining an event what .prop() cannot. Like this: $('.myDiv').attr('onclick', 'alert("Hello world!")'). If you change .attr() to .prop(), it won't work. Totally, I think there is no reason to use .attr() to set or get value of id/class/href/checked/src...... Notice that I don't say you're wrong. – user4090029

Gary Hole answer is very relevant to solve the problem if the code is written in such way

obj.prop("style","border:1px red solid;")

Since the prop function return CSSStyleDeclaration object, above code will not working properly in some browser(tested with IE8 with Chrome Frame Plugin in my case).

Thus changing it into following code

obj.prop("style").cssText = "border:1px red solid;"

solved the problem.

Gently reminder about using prop(), example:

if ($("#checkbox1").prop('checked')) {
    isDelete = 1;
} else {
    isDelete = 0;
}

Function above is used to check if checkbox1 is checked or not, if checked: return 1; if not: return 0. Function prop() used here as a GET function.

if ($("#checkbox1").prop('checked', true)) {
    isDelete = 1;
} else {
    isDelete = 0;
}

Function above is used to set checkbox1 to be checked and ALWAYS return 1. Now function prop() used as a SET function.

Don't mess up.

P/S: When I'm checking Image src property. If the src is empty, prop return the current url of the page (wrong), and attr return empty string (right).

upvote
  flag
You're wrong in this example: <img src="smiley.gif" alt="Smiley face" width="42" height="42" onclick="alert($(this).prop('src'))">. It should work and return the image location. – user4090029
upvote
  flag
If the src is EMPTY – user2657778

Before jQuery 1.6 , the attr() method sometimes took property values into account when retrieving attributes, this caused rather inconsistent behavior.

The introduction of the prop() method provides a way to explicitly retrieve property values, while .attr() retrieves attributes.

The Docs:

jQuery.attr() Get the value of an attribute for the first element in the set of matched elements.

jQuery.prop() Get the value of a property for the first element in the set of matched elements.

.attr():

  • Get the value of an attribute for the first element in the set of matched elements.
  • Gives you the value of element as it was defines in the html on page load

.prop():

  • Get the value of a property for the first element in the set of matched elements.
  • Gives the updated values of elements which is modified via javascript/jquery

1) A property is in the DOM; an attribute is in the HTML that is parsed into the DOM.

2) $( elem ).attr( "checked" ) (1.6.1+) "checked" (String) Will change with checkbox state

3) $( elem ).attr( "checked" ) (pre-1.6) true (Boolean) Changed with checkbox state

  • Mostly we want to use for DOM object rather then custom attribute like data-img, data-xyz.

  • Also some of difference when accessing checkbox value and href with attr() and prop() as thing change with DOM output with prop() as full link from origin and Boolean value for checkbox (pre-1.6)

  • We can only access DOM elements with prop other then it gives undefined

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>prop demo</title>
  <style>
    p {
      margin: 20px 0 0;
    }
    b {
      color: blue;
    }
  </style>

</head>

<body>

  <input id="check1" type="checkbox" checked="checked">
  <label for="check1">Check me</label>
  <p></p>

  <script>
    $("input").change(function() {
      var $input = $(this);
      $("p").html(
        ".attr( \"checked\" ): <b>" + $input.attr("checked") + "</b><br>" +
        ".prop( \"checked\" ): <b>" + $input.prop("checked") + "</b><br>" +
        ".is( \":checked\" ): <b>" + $input.is(":checked")) + "</b>";
    }).change();
  </script>

</body>

</html>

Not the answer you're looking for? Browse other questions tagged or ask your own question.