JavaScript DOM Attributes: getAttribute, setAttribute and More
Learn to read, change, remove and check HTML attributes with getAttribute, setAttribute, removeAttribute and hasAttribute, plus data attributes and properties.
What you will learn
HTML elements are not only tags. They carry extra information called attributes: the href of a link, the src of an image, the disabled state of a button, and so on. In this lesson you will learn how to read, change, remove and check attributes with getAttribute, setAttribute, removeAttribute and hasAttribute. You will also learn the difference between an attribute and a property, how boolean attributes work, and how to store your own data in data-* attributes.
What is an attribute?
An attribute is a name="value" pair written inside the opening tag:
<a href="/about" target="_blank" title="Read more">About us</a>
Here href, target and title are attributes. Think of an element as a person and attributes as the details on their ID card: name, age, address. JavaScript can read the card, correct a detail, add a new one, or tear a detail off.
You have already learned attributes in HTML (see the HTML Attributes in Depth lesson). Now we control them from JavaScript.
The sample page
All examples use this page. It is also loaded in Practice in Editor.
<h1 id="title">Attributes Practice</h1>
<a id="link" href="/about" target="_blank">About us</a>
<p>
<img id="logo" src="logo.png" alt="Company logo" width="120">
</p>
<form>
<input id="email" type="email" placeholder="Your email" required>
<input id="password" type="password" placeholder="Password">
<button id="save" type="submit" disabled>Save</button>
</form>
<div id="product" data-id="42" data-price="499" data-in-stock="true">Wireless Mouse</div>
Start your code with these variables:
const link = document.getElementById("link");
const email = document.getElementById("email");
const save = document.getElementById("save");
const product = document.getElementById("product");
The four main methods
| Method | What it does | Returns |
|---|---|---|
getAttribute(name) |
Reads the value | A string, or null if the attribute does not exist |
setAttribute(name, value) |
Adds the attribute, or changes it if it exists | Nothing (undefined) |
removeAttribute(name) |
Deletes the attribute | Nothing (undefined) |
hasAttribute(name) |
Checks if the attribute exists | true or false |
getAttribute
console.log(link.getAttribute("href")); // "/about"
console.log(link.getAttribute("target")); // "_blank"
console.log(link.getAttribute("rel")); // null (there is no rel attribute)
The result is always a string, or null. Even a number such as width="120" comes back as the text "120":
const logo = document.getElementById("logo");
console.log(logo.getAttribute("width")); // "120" (a string)
console.log(typeof logo.getAttribute("width")); // "string"
console.log(Number(logo.getAttribute("width")) + 30); // 150
setAttribute
The first argument is the name, the second is the value. If the attribute already exists, its value is replaced. If not, it is created.
link.setAttribute("href", "https://mycodenest.in"); // change
link.setAttribute("title", "Visit MyCodeNest"); // add new
link.setAttribute("rel", "noopener noreferrer"); // add new
console.log(link.getAttribute("href")); // "https://mycodenest.in"
Open the Elements panel in DevTools and watch the <a> tag change live.
removeAttribute
link.removeAttribute("target");
console.log(link.getAttribute("target")); // null
Removing an attribute that does not exist is safe. Nothing happens and there is no error.
hasAttribute
console.log(link.hasAttribute("href")); // true
console.log(link.hasAttribute("download")); // false
Use it when you only care whether something is present, not what its value is.
More attribute helpers
| Member | What it does |
|---|---|
toggleAttribute(name) |
Adds the attribute if missing, removes it if present. Returns true if it is now present |
toggleAttribute(name, force) |
force = true always adds it, force = false always removes it |
getAttributeNames() |
An array of all attribute names of the element |
attributes |
A list of all attributes; each has a name and a value |
console.log(link.getAttributeNames()); // ["id", "href", "title", "rel"]
for (const attr of product.attributes) {
console.log(attr.name + " = " + attr.value);
}
Output:
id = product
data-id = 42
data-price = 499
data-in-stock = true
Boolean attributes: disabled, required, checked, hidden
Some attributes do not need a value. If they are present, they are ON. If they are absent, they are OFF.
<button id="save" disabled>Save</button> <!-- disabled: ON -->
<button id="save">Save</button> <!-- disabled: OFF -->
So to turn them on and off, add and remove the attribute:
save.removeAttribute("disabled"); // enable the button
save.setAttribute("disabled", ""); // disable it again (the value text does not matter)
save.toggleAttribute("disabled"); // flip it
save.toggleAttribute("disabled", false); // make sure it is enabled
The most common beginner bug is this:
save.setAttribute("disabled", "false"); // The button is STILL disabled!
The attribute is present, so it is ON. The text "false" does not matter. Remove the attribute instead.
Common boolean attributes: disabled, required, checked, selected, readonly, hidden, autofocus, multiple.
Attribute vs property
This is the idea that confuses most beginners, so let us go slowly.
- An attribute is what is written in the HTML (the starting value).
- A property is what lives on the DOM object (the current value).
Many attributes have a matching property, and for simple cases they stay in sync:
console.log(link.id); // "link" (property)
console.log(link.title); // "Visit MyCodeNest"
link.title = "New title"; // changes the attribute too
console.log(link.getAttribute("title")); // "New title"
But for some attributes they are different:
email.value = "riya@example.com"; // like the user typing
console.log(email.getAttribute("value")); // null (HTML never had a value attribute)
console.log(email.value); // "riya@example.com" (current value)
The same happens with checkboxes. The checked attribute is only the starting state. The checked property changes when the user clicks.
// <input type="checkbox" id="agree" checked>
// After the user unchecks the box:
// agree.hasAttribute("checked") -> true (still in the HTML)
// agree.checked -> false (current state)
Links show a third difference. The attribute is exactly what you wrote. The property is the full address:
console.log(link.getAttribute("href")); // "/about" (as written)
console.log(link.href); // the complete URL, like "https://mycodenest.in/about"
| Use | When |
|---|---|
Property (el.value, el.checked, el.disabled, el.src) |
You want the current state of the element. This is the best choice for most standard things |
Attribute (getAttribute) |
You want the exact text written in the HTML, or the attribute has no property (like data-* or aria-*, or a custom one) |
Two names are different in properties because class and for are reserved words in JavaScript:
| HTML attribute | Property |
|---|---|
class |
className (or better, classList, which is the next lesson) |
for (on <label>) |
htmlFor |
tabindex |
tabIndex |
readonly |
readOnly |
Custom data: data-* attributes
HTML lets you invent your own attributes if the name starts with data-. They are perfect for hiding small pieces of information inside an element, like a product id.
<div id="product" data-id="42" data-price="499" data-in-stock="true">Wireless Mouse</div>
You can use getAttribute("data-id"), but there is an easier way: the dataset property.
console.log(product.dataset.id); // "42"
console.log(product.dataset.price); // "499"
console.log(product.dataset.inStock); // "true"
Rules for dataset:
- The name after
data-is used without the prefix. - A name with dashes becomes camelCase:
data-in-stockbecomesdataset.inStock. - Values are always strings.
"true"is not the booleantrue, and"499"is not a number. - Change, add and delete work like a normal object.
product.dataset.discount = "10"; // adds data-discount="10"
console.log(product.getAttribute("data-discount")); // "10"
console.log("price" in product.dataset); // true (check if it exists)
delete product.dataset.id; // removes data-id
const price = Number(product.dataset.price);
const inStock = product.dataset.inStock === "true";
console.log(price + 100, inStock); // 599 true
Tip:
data-*attributes also work in CSS:[data-in-stock="false"] { opacity: 0.4; }. And never put secret data (like passwords) in them, because everyone can see the HTML.
Real use cases
1. Show and hide a password
The type attribute decides if the text is dots or visible. One click flips it.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Show Password</title>
<style>
body { font-family: sans-serif; padding: 20px; }
input { padding: 8px; font-size: 16px; }
button { padding: 8px 12px; font-size: 16px; cursor: pointer; }
</style>
</head>
<body>
<label for="pw">Password</label><br>
<input id="pw" type="password" placeholder="Enter password">
<button id="toggle" type="button">Show</button>
<script>
const pw = document.getElementById("pw");
const toggle = document.getElementById("toggle");
toggle.addEventListener("click", function () {
const isHidden = pw.getAttribute("type") === "password";
pw.setAttribute("type", isHidden ? "text" : "password");
toggle.textContent = isHidden ? "Hide" : "Show";
});
</script>
</body>
</html>
(addEventListener means “when the button is clicked, run this function”. You will learn it fully in the events lessons.)
2. Enable the submit button only when the form is ready
Real sites keep “Create account” disabled until the user agrees to the terms. Here the disabled attribute is added and removed as the checkbox changes.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Terms</title>
<style>
body { font-family: sans-serif; padding: 20px; }
button { padding: 10px 16px; font-size: 16px; }
button:disabled { opacity: 0.5; cursor: not-allowed; }
</style>
</head>
<body>
<label>
<input type="checkbox" id="agree"> I agree to the terms and conditions
</label>
<p><button id="create" disabled>Create account</button></p>
<script>
const agree = document.getElementById("agree");
const create = document.getElementById("create");
agree.addEventListener("change", function () {
create.toggleAttribute("disabled", !agree.checked);
});
</script>
</body>
</html>
toggleAttribute("disabled", !agree.checked) means: disabled is ON when the box is NOT checked. Notice that we read the property agree.checked (the current state) and write the attribute disabled.
3. Product gallery with a data attribute
Each thumbnail carries the big image name in a data-full attribute, and we also keep alt text updated for accessibility.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Gallery</title>
<style>
body { font-family: sans-serif; padding: 20px; }
.thumb { padding: 8px 12px; margin-right: 6px; cursor: pointer; }
#big { margin-top: 12px; padding: 40px; border: 2px dashed #999; font-size: 18px; }
</style>
</head>
<body>
<button class="thumb" data-full="red-shoe.jpg" data-alt="Red running shoe">Red</button>
<button class="thumb" data-full="blue-shoe.jpg" data-alt="Blue running shoe">Blue</button>
<button class="thumb" data-full="green-shoe.jpg" data-alt="Green running shoe">Green</button>
<div id="big">Click a colour</div>
<script>
const big = document.getElementById("big");
document.querySelectorAll(".thumb").forEach(function (thumb) {
thumb.addEventListener("click", function () {
const file = thumb.dataset.full;
const alt = thumb.dataset.alt;
// In a real page, big would be an <img> and you would write:
// big.setAttribute("src", "images/" + file);
// big.setAttribute("alt", alt);
big.textContent = "Showing images/" + file + " (alt: " + alt + ")";
});
});
</script>
</body>
</html>
The page has no hard-coded list inside the script. To add a fourth colour, you only add one more button in the HTML.
4. Make external links safe
Links that open in a new tab should have rel="noopener noreferrer". This script finds every link that goes to another site and fixes it.
document.querySelectorAll("a[href^='http']").forEach(function (a) {
if (a.hostname !== location.hostname) {
a.setAttribute("target", "_blank");
a.setAttribute("rel", "noopener noreferrer");
}
});
5. Accessibility: keep ARIA in sync
When a button opens a menu, screen readers need to know the state. Update aria-expanded along with what the user sees.
const menuButton = document.getElementById("menu-btn");
menuButton.addEventListener("click", function () {
const open = menuButton.getAttribute("aria-expanded") === "true";
menuButton.setAttribute("aria-expanded", String(!open));
});
aria-* attributes have no property, and values must be the strings "true" or "false". That is why String(!open) is used.
Common mistakes
setAttribute("disabled", "false"). The button stays disabled. UseremoveAttribute("disabled")ortoggleAttribute("disabled", false).- Expecting a number or boolean back.
getAttribute("width")anddataset.priceare strings. Convert withNumber(), or compare with=== "true". - Forgetting that a missing attribute is
null.link.getAttribute("rel").toLowerCase()crashes if there is norel. Check withhasAttribute, or use?.. - Using
getAttribute("value")to read what the user typed. It gives the starting value only. Useinput.value. - Using
getAttribute("checked")for a checkbox state. Usecheckbox.checked. - Writing
getAttribute("class")to add classes. It replaces the whole class string and is easy to break. UseclassList(next lesson). - Typing
dataset.data-id. That reads asdataset.dataminusid. Usedataset.id, anddataset.inStockfordata-in-stock. - Setting an attribute from untrusted user input. A link built from user text can start with
javascript:. Check that URLs start withhttps://before you use them. - Wrong capital letters. It is
setAttribute, notsetattributeorSetAttribute.
Practice
- Print the
hrefandtargetof the link withgetAttribute. Then printgetAttribute("rel")and explain why you getnull. - Change the link to go to
https://mycodenest.inand add atitle. Check the result in the Elements panel. - Remove
targetfrom the link and usehasAttributeto confirm it is gone. - Enable the Save button by removing
disabled. Then disable it again withsetAttribute. - Try
save.setAttribute("disabled", "false")on an enabled button. Is it disabled or enabled? Why? - Set
email.valuefrom JavaScript. Printemail.getAttribute("value")andemail.value. Explain the difference. - Print the
hrefof the link withgetAttribute("href")and withlink.href. What is different? - Loop over
product.attributesand print every name and value. - Read
data-pricefrom the product, convert it to a number, and print the price with 10% discount. - Challenge: build a “Show / Hide” toggle for the
#passwordfield usingsetAttribute("type", ...), and also update the button’saria-labelbetween"Show password"and"Hide password".
Recap
- Attributes are the
name="value"details inside a tag. JavaScript can manage them with four main methods. getAttribute(name)reads (a string, ornull),setAttribute(name, value)adds or changes,removeAttribute(name)deletes, andhasAttribute(name)checks.toggleAttribute(name, force)is a handy shortcut for adding and removing in one call.getAttributeNames()andattributeslist everything.- Boolean attributes (
disabled,required,checked,hidden) are ON when present and OFF when absent, whatever the value text is. - An attribute is the starting value in the HTML. A property is the current value on the object. For live state, like
value,checkedanddisabled, prefer the property. classisclassName(orclassList) andforishtmlForas properties.- Use
data-*attributes withdatasetto attach your own information. Names become camelCase and values are always strings. - Always handle
nullfor missing attributes, and convert strings to numbers or booleans when needed. - Next you will learn how to change what an element shows:
textContent,innerText,innerHTMLandstyle.