What’s the difference between .prop() and .attr() in jQuery?
In jQuery 1.6, a new .prop() method was introduced alongside the existing .attr() method. I’m trying to understand when to use each method and how they differ in behavior.
For example, when working with the style attribute:
$(selector).click(function() {
// Traditional approach:
var getAtt = this.getAttribute('style');
// Which jQuery method should I use?
var thisProp = $(this).prop('style');
var thisAttr = $(this).attr('style');
console.log(getAtt, thisProp, thisAttr);
});
The console shows that:
getAttribute('style')returns a string.attr('style')returns a string.prop('style')returns a CSSStyleDeclaration object
Questions:
- When should I use
.prop()versus.attr()in jQuery? - Will switching from
.attr()to.prop()in jQuery 1.6 break my existing code? - Why does
.prop('style')return a CSSStyleDeclaration while.attr('style')returns a string, and how does this affect my coding practices?
The fundamental difference between .prop() and .attr() in jQuery lies in what they manipulate: properties (DOM element properties) versus attributes (HTML attributes). .prop() was introduced in jQuery 1.6 to provide a clearer distinction and better handling of DOM element properties that may not have corresponding HTML attributes.
Contents
- Understanding Properties vs Attributes
- When to Use .prop()
- When to Use .attr()
- The Style Attribute Special Case
- Migration Considerations
- Practical Examples
- Best Practices
Understanding Properties vs Attributes
Properties are dynamic values that belong to DOM elements and can change over time. They represent the current state of an element, including values set by JavaScript or user interactions.
Attributes are static values defined in the HTML markup. They represent the initial state as specified in the HTML.
For example, consider a checkbox:
<input type="checkbox" checked id="myCheckbox">
Here, checked is an attribute, but the element also has a checked property that reflects the checkbox’s current state.
When to Use .prop()
Use .prop() when working with:
- Boolean properties like
checked,selected,disabled - Element properties like
tagName,nodeName,nodeType - Form values like
value,selectedIndex - Style properties (returns CSSStyleDeclaration object)
- Any property that doesn’t have a direct HTML attribute equivalent
// Check if checkbox is checked
if ($('#myCheckbox').prop('checked')) {
// Checkbox is checked
}
// Get element tag name
var tagName = $('div').prop('tagName');
When to Use .attr()
Use .attr() when working with:
- HTML attributes like
id,class,src,href - Custom data attributes like
data-* - Attributes that directly correspond to HTML markup
- String values that represent element characteristics
// Get element ID
var elementId = $('#myElement').attr('id');
// Set custom data attribute
$('#myElement').attr('data-custom', 'value');
// Get image source
var imageUrl = $('img').attr('src');
The Style Attribute Special Case
Your example perfectly illustrates the key difference:
$(selector).click(function() {
var getAtt = this.getAttribute('style'); // String
var thisProp = $(this).prop('style'); // CSSStyleDeclaration object
var thisAttr = $(this).attr('style'); // String
console.log(getAtt, thisProp, thisAttr);
});
.attr('style')returns the raw string value from the HTML attribute.prop('style')returns the actual CSSStyleDeclaration object, which gives you access to individual CSS properties
This affects your coding practices significantly:
// Using .attr() - string manipulation
var styleString = $('#element').attr('style');
var newStyle = styleString + 'color: red;';
$('#element').attr('style', newStyle);
// Using .prop() - object manipulation
var styleObject = $('#element').prop('style');
styleObject.color = 'red';
styleObject.backgroundColor = 'blue';
Migration Considerations
Will switching break existing code? It depends on what you’re doing:
- Safe to switch: For boolean attributes like
checked,disabled,selected - Potentially breaking: For other attributes where behavior changes
Migration guidelines from jQuery 1.6 documentation:
-
Use .prop() for:
checkedstatus of checkboxes and radio buttonsdisabledstatus of form elementsselectedstatus of option elements- Any property that doesn’t have a direct HTML attribute
-
Continue using .attr() for:
class(use.addClass(),.removeClass(),.toggleClass()instead)value(for input values, use.val())style(if you need string manipulation)src,href,id, etc.
Example migration:
// Before jQuery 1.6
if ($('#checkbox').attr('checked')) {
// This was unreliable - checked attribute might not exist
}
// After jQuery 1.6 (recommended)
if ($('#checkbox').prop('checked')) {
// This properly checks the actual checked state
}
Practical Examples
Form handling:
// Get form element values
var inputValue = $('#myInput').val(); // Always use .val() for form values
var isChecked = $('#myCheckbox').prop('checked'); // Use .prop() for boolean properties
var selectedIndex = $('#mySelect').prop('selectedIndex');
// Set form element values
$('#myInput').val('new value');
$('#myCheckbox').prop('checked', true);
$('#mySelect').prop('selectedIndex', 2);
Image handling:
// Get image dimensions
var img = $('#myImage');
var naturalWidth = img.prop('naturalWidth');
var naturalHeight = img.prop('naturalHeight');
// Get/set image source
var src = img.attr('src');
img.attr('src', 'new-image.jpg');
Custom data:
// Set custom data attribute
$('#element').attr('data-user-id', '12345');
// Get custom data attribute
var userId = $('#element').attr('data-user-id');
// Alternatively, use .data() method (jQuery 1.4.3+)
$('#element').data('userId', '12345');
var userId = $('#element').data('userId');
Best Practices
- Use .prop() for boolean states and DOM properties
- Use .attr() for HTML attributes and custom data
- Use .val() for form input values
- Use .data() for storing arbitrary data associated with elements
- Be consistent throughout your codebase
Decision flowchart:
Do you need to work with:
├─ Boolean state (checked, disabled, selected)? → Use .prop()
├─ HTML attribute (id, class, src, href, data-*)? → Use .attr()
├─ Form input value? → Use .val()
├─ Arbitrary data storage? → Use .data()
└─ Style manipulation? → Consider .prop('style') for object access or .attr('style') for string
Common pitfalls to avoid:
// Don't mix .attr() and .prop() for the same property
// Inconsistent:
$('#checkbox').attr('checked', true); // Sets attribute
if ($('#checkbox').prop('checked')) { // Checks property
// This might not work as expected
}
// Do this instead:
$('#checkbox').prop('checked', true); // Both set and check using .prop()
if ($('#checkbox').prop('checked')) {
// This works correctly
}
Conclusion
The introduction of .prop() in jQuery 1.6 provided a much-needed distinction between HTML attributes and DOM element properties. Here are the key takeaways:
- Use .prop() for boolean states, DOM properties, and when you need the current state of an element
- Use .attr() for HTML attributes and when working with markup-based values
- The style attribute behaves differently -
.prop('style')gives you a CSSStyleDeclaration object while.attr('style')gives you a string - Migration from
.attr()to.prop()for boolean properties is safe and recommended - Consistency is key - choose one method and stick with it for similar operations
Understanding this distinction will help you write more reliable and maintainable jQuery code that properly reflects the actual state of your DOM elements.