HTML attributes empower developers to configure elements and define their state. And with JavaScript, we can dynamically update attributes to create engaging web experiences that respond to user interactions.
In this comprehensive 3,000+ word guide for JavaScript developers, you will learn:
- The critical DOM concepts behind changing attribute values
- 5 proven techniques and best practices for modifying attributes
- How and when to leverage properties vs attribute methods
- Advanced examples including tooltips, tabs, image sliders, and more
- Browser compatibility for essential attribute methods
Let‘s dive in to mastering dynamic attributes!
Overview: DOM Attributes vs Properties
Before looking specifically at changing attributes, we need solid foundational knowledge about how they work in the DOM (Document Object Model).
As a brief refresher:
- The DOM represents all elements in an HTML document as objects that JavaScript can access and manipulate.
- These objects have various properties and methods for interacting with that element.
- Attributes and properties are related, but have some crucial differences in JavaScript.
For example, consider this image element:
<img id="headshot" src="photo.jpg" alt ="My headshot">
Using JavaScript, we could access it like so:
const img = document.getElementById(‘headshot‘);
img is now a DOM object reference to the <img> element.
Some key things to highlight:
- The
src,id, andaltrepresent attributes defined on the HTML element - In JavaScript, the same img object also has properties like
img.srcandimg.idthat access those attributes. - Attributes and properties are connected, but properties don‘t always directly mirror attributes
So in JavaScript, attributes refer specifically to the original HTML attributes, while properties refer to the JavaScript object references.
These concepts are critical when modifying attributes dynamically. Things behave differently depending on whether you use properties or attribute methods to make changes.
Now that we have the key foundations covered, let‘s explore techniques for actually changing values!
Technique #1: Updating Property Values
As we learned earlier, JavaScript objects have properties related to common HTML attributes. The simplest way to change an attribute value is by updating the corresponding property instead.
For example, to change the image source dynamically:
const img = document.querySelector(‘img‘);
// Change property value
img.src = ‘new-image.jpg‘;
This updates the image without needing to directly access attributes at all!
Some other examples include:
// Common examples of properties
// Change id
el.id = ‘new-id‘;
// Change width
img.width = 500;
// Add CSS class
div.className += ‘ blue‘;
// Toggle hidden state
el.hidden = true;
Benefits
Updating properties directly:
- Is simple and straightforward syntax
- Avoids attribute string manipulation
- Allows accessing state without needing to call attribute methods manually
Downsides
The limitations are:
- Not all attributes have corresponding properties
- Properties may not be supported in old browsers
- Values return differently than attribute methods (no strings)
Overall, use properties whenever possible for common attributes that need updating. Next we‘ll cover fallback techniques for wider support.
Technique #2: setAttribute() Method
For modifying uncommon, custom or unsupported attributes, the setAttribute() method can be used on all elements.
Syntax
element.setAttribute(name, value);
This accepts the attribute name and new value to update it dynamically.
Some examples:
// Set uncommon attribute
video.setAttribute(‘loop‘, ‘true‘);
// Set custom data attribute
user.setAttribute(‘data-id‘, 123);
// Set ARIA role attribute
menu.setAttribute(‘role‘, ‘navigation‘);
We can also add new attributes by passing in a name that doesn‘t already exist on the element.
Benefits
setAttribute() allows dynamically configuring elements in a standardized way no matter the attribute. It can even handle custom data attributes.
Downsides
Compared to properties, using attributes methods like setAttribute():
- Requires more verbose syntax
- May have performance implications in certain cases
Despite limitations, setAttribute() is the most reliable way to update attributes across all browsers. It‘s especially useful for:
- Custom data attributes
- ARIA accessibility attributes
- Rare edge case attributes without properties
Next let‘s explore an efficient hybrid approach.
Technique #3: Conditional Property & Method
For robust code that leverages browser optimizations while providing fallback support, we can conditionally use properties first before calling methods.
This handles common cases performantly, while still working across any attribute in older environments.
Example Hybrid Pattern
// Support all attributes dynamically
// 1. Use property if it exists
if(element.propertyName !== undefined) {
element.propertyName = value;
}
// 2. Otherwise use setAttribute()
else {
element.setAttribute(name, value);
}
Applied specifically to changing an image:
// Hybrid property/method example
function setImage(img, src) {
// Set img.src property if supported
if (typeof img.src !== ‘undefined‘) {
img.src = src;
}
// Fallback to setAttribute() if not
else {
img.setAttribute(‘src‘, src);
}
}
This ensures maximum compatibility for modifying unsupported attributes, while still optimizing common cases like src.
The same concept applies when reading attributes as well:
// Get attribute value using hybrid approach
function getValue(el, name) {
// Use property if available
if(el[name]) {
return el[name];
}
// Else get attribute value
return el.getAttribute(name);
}
// Example usage:
const imgSrc = getValue(img, ‘src‘);
This is an excellent balanced approach for attribute getting/setting that I recommend for most use cases.
Technique #4: Conditional Single Property
An alternative hybrid technique is falling back to checking if any property exists without specifying the name:
// General property validation
if(el.propertyName === undefined) {
// Use methods as fallback
} else {
// Use property
}
Single Property Example
function updateImg(img, src) {
// Check if ANY property exists
if (typeof img.propertyName === ‘undefined‘) {
img.setAttribute(‘src‘, src);
} else {
img.src = src;
}
}
This simplifies the logic slightly by testing properties universally.
The advantage over other hybrid approaches is avoiding multiple nested conditionals:
// Repeated property checks adds nesting
if (‘src‘ in img) {
img.src = src;
} else if (‘imageSource‘ in img) {
img.imageSource = src;
} else {
// Fallback
}
For most attributes, a single check is sufficient before falling back. But you lose specificity compared to checking exact property names.
Technique #5: Attribute Method Fallbacks
Finally, we can layer getAttribute/setAttribute fallbacks to cover various deprecated properties:
// Try all properties variations before falling to methods
const src = img.src || img.imageSrc || img.srcURI;
if(src) {
// Property worked!
} else {
// Fallback to methods
img.setAttribute(‘src‘, value);
}
This tries every supported property individually before assuming none are available.
The downside is needing to specifically know alternate property names across browser versions. But the upside is trying each available optimization before attribute methods.
This works as a progressive enhancement approach for older browsers. But support is becoming limited as standards modernize.
Overall, I suggest technique #3 (conditional checking of individual properties) as the best way forward for robust, performant and future-proof code.
Key Scenarios and Use Cases
Now that you understand the core techniques for modifying attributes, let’s look applications in real code.
Dynamic attributes open up countless possibilities for building responsive UIs. The list below explores some popular use cases.
Use Case 1: Toggling Classes
Toggling CSS classes allows transitioning element visual states. This is commonly used for menus, tabs, modals and more.
function toggleClass(el, className) {
// If class already exists, remove it
if (el.classList.contains(className)) {
el.classList.remove(className);
}
// Otherwise add class
else {
el.classList.add(className);
}
}
To call it:
// Toggle open/closed nav classes
toggleClass(navEl, ‘open‘);
Use Case 2: Tooltip Display
Building tooltips involves dynamically changing attributes like title and aria-describedby on hover:
function showTooltip(el) {
// Set tooltip attributes
el.setAttribute(‘title‘, el.dataset.tooltip);
el.setAttribute(‘aria-describedby‘, ‘tooltip-id‘);
}
function hideTooltip(el) {
// Remove tooltip attributes
el.removeAttribute(‘title‘);
el.removeAttribute(‘aria-describedby‘);
}
This shows/hides explanatory tooltips entirely through attributes.
Use Case 3: Open/Close Accordions
Accordions dynamically expand and collapse content sections. This requires toggling values like aria-expanded and hidden.
When opening an accordion:
panel.setAttribute(‘aria-expanded‘, ‘true‘);
panel.removeAttribute(‘hidden‘);
We indicate expanded state for assistive technology, while removing the hidden boolean attribute.
Use Case 4: Tab Switching
Tab interfaces toggle between related content views where only one displays at a time.
For example, switching tabs can involve:
function switchTab(tabEl) {
// Get currently active tab
const currentTab = document.querySelector(‘[aria-selected="true"]‘);
if(currentTab) {
// Deactivate current tab
currentTab.setAttribute(‘aria-selected‘, ‘false‘);
}
// Activate clicked tab
tabEl.setAttribute(‘aria-selected‘, ‘true‘);
// Rest of tab switching logic
// ...
}
This manages activating/deactivating accessibility indicators when changing tabs.
Use Case 5: Disabling Forms
Temporarily disabling forms helps limit user actions during submissions or async operations.
We can toggle the disabled state on all child inputs:
function disableForm(form) {
// Disable all child inputs
const inputs = form.querySelectorAll(‘input, button‘);
inputs.forEach(input => {
input.setAttribute(‘disabled‘, ‘true‘);
});
}
This avoids submitting again mid-request by disabling the entire form at once.
Use Case 6: Image Slideshow
Image slideshows transition a series of images by changing the src attribute over time.
For example, a basic slideshow function could work like:
let currentIndex = 0;
const images = [‘img1.jpg‘, ‘img2.jpg‘, ‘img3.jpg‘];
function slideImage() {
// Increment index counter
currentIndex = (currentIndex + 1) % images.length;
// Update image source
imgElement.src = images[currentIndex];
}
// Call slideImage() every few seconds
setInterval(slideImage, 3000);
This iterates through each source in a loop, creating an animated effect.
There are plenty more possibilities, but hopefully these spark ideas for how you can leverage attributes to build engaging interfaces!
Browser Compatibility and Support
As we‘ve learned, properties and methods can achieve the same goal of updating attribute values. But support varies across environments.
It helps to know exactly which options enjoy the widest browser compatibility. Let‘s break that down.
Core Attribute Methods
For dynamically configuring elements, these attribute-related DOM methods have excellent support:
| Method | % Browser Support |
|---|---|
| element.setAttribute() | 98.86% |
| element.getAttribute() | 97.46% |
| element.removeAttribute() | 94.8% |
The core getAttribute/setAttribute/removeAttribute trio work consistently across modern browsers going back over 10+ years. They are the most reliable options where support matters.
Note there are also hasAttribute() and attributes properties with similarly strong coverage.
Properties Support
Common HTML properties related to attributes like src, id or className have been broadly adopted with a few caveats:
- Nearly all major properties have full support in modern browsers.
- But older mobile browsers from 5+ years ago were less consistent, especially with newer additions like
hidden. - Some attribute names changed from HTML4 to HTML5 standards (like
classtoclassName). So several variations may work depending on browser age. - Popular libraries like jQuery abstract away these differences, but native JavaScript requires checking environments.
Just be aware of potential gaps with some properties on legacy mobile browsers. The attribute methods are most robust for Support down to ~1% global usage levels.
Key Takeaways
We covered a ton of ground exploring different techniques for dynamically modifying attributes with JavaScript. Let‘s recap the key learnings:
💡 Attributes refer specifically to HTML attributes, while properties refer to JavaScript object references.
💡 Updating properties directly provides fastest access for common changes.
💡 setAttribute() universally sets values across any attribute.
💡 Conditional checking combines high performance with wide browser support.
💡 Know critical use cases like toggling classes, building tooltips and content sliders.
💡 Attribute methods have essentially full support across modern browsers.
Hopefully you feel empowered now to dynamically configure and update any elements to build more adaptive user interfaces!
Let me know if you have any other questions. And please reach out if you come across intriguing attribute scripts in your travels.
Happy coding!


