cf.completefrontendCode editorOpen lab
THE JAVASCRIPT FIELD GUIDE

Attributes & properties

Learn the difference between HTML attributes and DOM properties: getAttribute, setAttribute, reflection, dataset, input defaults, and boolean attributes.

By the end, you can
  • 01
    Read the right sideChoose attributes for markup/defaults and properties for live state.
  • 02
    Predict reflectionExplain id, className, href, style, value, and checked sync rules.
  • 03
    Use safe custom dataStore small strings with data-* and handle boolean attributes correctly.

Two places for information

An element can carry information in two closely related places. An attribute is the name/value text you write in HTML, such as id="save" or value="Ada". A property is a field on the live DOM object JavaScript receives, such as button.id or input.value.

The difference matters because the DOM is alive. Users type, click, scripts assign values, and the browser normalizes some properties. Attributes are usually string defaults and configuration. Properties are often the current state and can be booleans, numbers, objects, or resolved values.

Real-life analogyThe box label and the product in your hands

Imagine a toy box labelled “red car.” That label is useful, but once the child paints the car blue, the object in their hands is blue even if the box still says red. For an input, the value attribute is the label; the value property is what is in the field right now.

In real life: Label printed at the factory
In JavaScript: The HTML attribute you wrote, like value="Ada"
In real life: The product's current state after you open it
In JavaScript: The DOM property, like input.value after typing
In real life: A label saying default color
In JavaScript: defaultValue or defaultChecked
In real life: Changing the thing in your hands
In JavaScript: Assigning a property, such as input.value = "Grace"

Where the analogy stops: Many standard attributes and properties reflect each other, so the label and product can stay in sync. Inputs are the memorable exception: the current value can split away from the default.

This lesson builds on The browser environment, The DOM tree, Walking & searching the DOM, and Node properties & contents. Up next, Creating & changing elements uses these reads and writes while building new nodes.

getAttribute and setAttribute

INTERACTIVE

Attribute methods read and write the attribute map on an element. element.getAttribute(name) returns a string when the attribute exists and null when it does not. element.setAttribute(name, value) converts the value to a string before storing it. Attribute names on HTML elements in HTML documents are case-insensitive, so getAttribute("ID") and getAttribute("id") look at the same attribute.

Fun fact: attributes are objects too

element.attributes is a NamedNodeMap of Attr nodes. You usually use getAttribute, setAttribute, hasAttribute, and removeAttribute instead of editing those nodes directly.

Try the inspector. Type before pressing setAttribute value, then press write input.value. The first changes the label/default side. The second changes what the user sees now.

Attribute vs property inspector
What the inspector readsPop out in the code editor (opens in a new tab)JavaScript
const input = document.querySelector("input"); input.value;                 // property: current typed textinput.getAttribute("value"); // attribute: default from HTMLinput.defaultValue;          // property reflecting that default input.setAttribute("value", "Linus");input.value = "Grace";
Real DOM nodeslive
input.value
""
input.getAttribute("value")
null
input.defaultValue
""
checkbox.checked
false
checkbox.getAttribute("checked")
null
checkbox.defaultChecked
false
Try it yourself

Type in the input or tick the checkbox, then compare the live properties with the original attributes.

The controls manipulate real DOM nodes inside an empty ref container, so React never owns the input or checkbox being changed.

How attributes and properties sync

TABLE

Many standard HTML attributes reflect to DOM properties. Reflect means changing one side updates the other according to rules in the DOM and HTML specs. The rule is not always “same name, same type,” so read the API you need.

How attributes and properties sync
CaseAttribute readProperty readWhat to remember
idgetAttribute("id") is the written stringel.id is the same stringReflects both ways for normal IDs.
classclass attribute stringclassName string and classList token helperRenamed because class is special JavaScript syntax.
hrefAs written, such as /docsResolved absolute URLUse the attribute for source text; property for navigation target.
valueDefault valueCurrent typed valueUse defaultValue for the reflected default property.
checkedDefault checked when presentCurrent checked booleanUse defaultChecked for the default.
styleCSS text stringCSSStyleDeclaration objectel.style.color = ... edits one declaration.
forfor attribute on <label>htmlFor propertyRenamed because for is a keyword.
tabindexString or nullNumber from tabIndexSome properties are typed.
color on <div>Custom non-standard stringUsually undefinedNot every attribute gets a matching property.

The table is the map; the next replay is the movie. It uses a tiny pure model of an input so the server can record the steps without a DOM. The browser behavior was checked against real inputs for this lesson.

Pure model used in the replayPop out in the code editor (opens in a new tab)JavaScript
function makeInput(defaultValue) {  return {    attributes: { value: String(defaultValue) },    value: String(defaultValue),    defaultValue: String(defaultValue),    getAttribute(name) {      return Object.hasOwn(this.attributes, name) ? this.attributes[name] : null;    },    setAttribute(name, value) {      this.attributes[name] = String(value);      if (name === "value") this.defaultValue = String(value);    },    removeAttribute(name) {      delete this.attributes[name];      if (name === "value") this.defaultValue = "";    },  };} const input = makeInput("Ada");input.value = "Grace";input.setAttribute("value", "Linus");console.log(input.value);console.log(input.getAttribute("value"));console.log(input.defaultValue);

Inputs, checks, and defaults

STEP THROUGH

Form controls are where learners most often trip. input.value is the current text. input.getAttribute("value") is the default attribute. input.defaultValue is the property that reflects that default. Checkboxes mirror the same idea: checked is current, while the checked attribute and defaultChecked are the default.

Step through attributes vs properties
Step 0 of 6Ready
Your turn: follow the blue line

This is a pure model of the input value/default-value split. It mirrors the browser behavior verified for this lesson.

Running in
  1. script
Next: line 20
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
function makeInput(defaultValue) {  return {    attributes: { value: String(defaultValue) },    value: String(defaultValue),    defaultValue: String(defaultValue),    getAttribute(name) {      return Object.hasOwn(this.attributes, name) ? this.attributes[name] : null;    },    setAttribute(name, value) {      this.attributes[name] = String(value);      if (name === "value") this.defaultValue = String(value);    },    removeAttribute(name) {      delete this.attributes[name];      if (name === "value") this.defaultValue = "";    },  };} input.value = "Grace";input.setAttribute("value", "Linus");console.log(input.value);console.log(input.getAttribute("value"));console.log(input.defaultValue);
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.
Attribute or property?
  • Text typed in an input right now
  • The value written in the original HTML
  • A link URL resolved against the page
  • The exact href="/docs" text as written
  • data-user-id read as userId
  • Whether a checkbox is checked after a click
  • Whether the checkbox started checked in HTML
  • dataset.lastSeen = 7 creating data-last-seen
  • Can the button be clicked right now?
Try it yourself
0 of 9 correct

Sort each read by the side of the DOM it belongs to.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

data-* and dataset

INTERACTIVE

data-* attributes are the safe place for small custom strings that belong to an element. JavaScript exposes them through element.dataset. A dash followed by a lowercase letter becomes an uppercase letter: data-user-id becomes dataset.userId. Setting dataset.someValue creates data-some-value.

Real-life analogydata-* attributes are sticky notes

You attach a small note to the element so your code can find it later without inventing non-standard attributes like userId="42".

In real life: Sticky note: customer #42
In JavaScript: data-user-id="42"
In real life: Reading the note later
In JavaScript: element.dataset.userId
In real life: Adding a new note
In JavaScript: element.dataset.lastSeen = "today"

Where the analogy stops: Sticky notes are visible to anyone looking at the page source or DevTools. Do not store secrets in data-*. Values are always strings, not rich objects.

dataset explorer
data-* conversionPop out in the code editor (opens in a new tab)JavaScript
const card = document.querySelector("[data-user-id]"); card.dataset.userId;       // "42"card.dataset.role;         // "admin"card.dataset.lastSeen = 7; // creates data-last-seen="7"delete card.dataset.role;  // removes data-role
Element attributesstrings
dataset.userId
undefined
dataset.role
undefined
dataset.lastSeen
undefined
data-* attributes
{}
Try it yourself

Read the sticky notes: data-user-id becomes dataset.userId, and data-role becomes dataset.role.

Dataset is for small strings your own code wants to attach to elements. It is not private storage.

Boolean attributes

INTERACTIVE

Boolean attributes are controlled by presence. If disabled, checked, hidden, required, or a similar boolean attribute exists at all, it is on. The strings "false" and "0" do not turn it off. To turn it off, remove the attribute or assign the reflected property to false.

Real-life analogyA light switch is on when it exists

For boolean attributes, the browser asks one question: “is the switch there?” If yes, the feature is on.

In real life: A switch installed on the wall
In JavaScript: A boolean attribute present on the element
In real life: A label on the switch saying false
In JavaScript: disabled="false" still means disabled
In real life: Removing the switch
In JavaScript: removeAttribute("disabled")

Where the analogy stops: Real switches have an up/down position. Boolean HTML attributes use presence only; the property gives you the convenient true/false value.

Boolean attributes playground
Boolean attribute readsPop out in the code editor (opens in a new tab)JavaScript
const button = document.querySelector("button"); button.setAttribute("disabled", "false");button.hasAttribute("disabled"); // truebutton.disabled;                 // truebutton.removeAttribute("disabled");button.disabled = false;button.toggleAttribute("disabled", true);
Button stateenabled
hasAttribute("disabled")
false
getAttribute("disabled")
null
button.disabled
false
Try it yourself

A boolean attribute is on when the attribute exists at all.

Presence is the switch. The text inside a boolean attribute is not parsed as true or false.

Where you will use this

Use attributes for markup-facing configuration, accessibility states, selectors, and defaults. Use properties for current state and browser-normalized values. Real components often mix both: a tab might read a data-panel attribute, set an ARIA attribute, write a boolean property, and reveal a panel through the reflected hidden property.

A practical mixPop out in the code editor (opens in a new tab)JavaScript
const tab = document.querySelector("[data-panel]");const panelId = tab.dataset.panel;const panel = document.getElementById(panelId); tab.setAttribute("aria-selected", "true");tab.disabled = true;panel.hidden = false;
  • dataset.panel reads your code’s sticky note.
  • setAttribute("aria-selected", "true") writes an accessibility state that assistive technology can read.
  • tab.disabled = true writes the live boolean property and reflects to the attribute.
  • panel.hidden = false changes the current DOM object state.

Common misconceptions

  • “Attributes and properties are the same thing.” They are connected for many standards, but attributes are string/default markup and properties are live object fields.
  • “setAttribute("value") always changes the visible input.” Once the input’s current value is dirty, set the value property instead.
  • “disabled="false" means enabled.” Boolean attributes are on when present.
  • “Dataset stores numbers and objects.” Dataset values are always strings; parse JSON yourself if you choose to store JSON text.
  • “Every attribute has a same-named property.” Some are renamed, typed, object-shaped, or not reflected at all.
  • “getAttribute returns undefined when missing.” It returns null.

Practice exercises

5 EXERCISES
Exercise 1 · Warm-upMissing attribute

Predict the value returned for an attribute that was never written.

Starter codePop out in the code editor (opens in a new tab)JavaScript
document.createElement("p").getAttribute("title");

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · Warm-upDataset values are strings

    Run the program mentally. What type is stored after a number goes through dataset?

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    const dataset = {};
    dataset.count = String(5);
    console.log(typeof dataset.count);
    console.log(dataset.count);

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeFind the boolean bug

      The developer expected an enabled button. Predict the value and name the bug.

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      button.setAttribute("disabled", "false");
      console.log(button.disabled);

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticePredict the timeline

        Use the replay idea to predict the three console lines.

        Starter codePop out in the code editor (opens in a new tab)JavaScript
        function makeInput(defaultValue) {
          return {
            attributes: { value: String(defaultValue) },
            value: String(defaultValue),
            defaultValue: String(defaultValue),
            getAttribute(name) {
              return Object.hasOwn(this.attributes, name) ? this.attributes[name] : null;
            },
            setAttribute(name, value) {
              this.attributes[name] = String(value);
              if (name === "value") this.defaultValue = String(value);
            },
            removeAttribute(name) {
              delete this.attributes[name];
              if (name === "value") this.defaultValue = "";
            },
          };
        }
        
        const input = makeInput("Ada");
        input.value = "Grace";
        input.setAttribute("value", "Linus");
        console.log(input.value);
        console.log(input.getAttribute("value"));
        console.log(input.defaultValue);

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeChoose the right API

          Fill in the three comments with the API that best matches each job.

          Starter codePop out in the code editor (opens in a new tab)JavaScript
          const item = document.querySelector("[data-price]");
          // 1. Read the price note.
          // 2. Disable the buy button.
          // 3. Store a selected default in markup.

            Quiz

            7 QUESTIONS
            Attributes & properties quiz · 7 questionsScore: first tries count
            1. Question 1 of 7Which statement best describes an HTML attribute?

              Choose an answer to see the explanation.

            2. Question 2 of 7What does this print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              console.log(String(7));
              console.log(null);

              Choose an answer to see the explanation.

            3. Question 3 of 7For <a href="/docs">, which read gives the resolved absolute URL?

              Choose an answer to see the explanation.

            4. Question 4 of 7What does this dataset-style program print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const dataset = {};
              dataset.count = String(5);
              console.log(typeof dataset.count);
              console.log(dataset.count);

              Choose an answer to see the explanation.

            5. Question 5 of 7What is true of disabled="false" in HTML?

              Choose an answer to see the explanation.

            6. Question 6 of 7Which property name reflects the for attribute on a <label>?

              Choose an answer to see the explanation.

            7. Question 7 of 7After a user edits an input, what does setAttribute("value", "new") update?

              Choose an answer to see the explanation.

            Key takeaways

            • Attributes are markup-side strings; properties are fields on live DOM objects.
            • getAttribute returns a string or null; setAttribute stringifies values.
            • Reflection rules vary: names can change, values can be typed, and URLs/styles can be normalized objects.
            • For inputs and checkboxes, value/checked are current; attributes and defaultValue/defaultChecked are defaults.
            • data-* maps to dataset camelCase properties, always as strings.
            • Boolean attributes are true when present; remove them or set the property to false to turn them off.
            Final definition

            An attribute is an element’s string/default information from markup; a property is the live JavaScript field on the DOM object.

            Up next: Creating & changing elements.

            CompleteFrontend Clear concepts. Working examples.