---
title: Bitovi Academy - Attributes and Properties
description: Learn about the attributes and properties on an element.
---

- ![AI implementation](https://www.bitovi.com/hubfs/AIConsultingIcon.svg)
  
  [AI implementation](https://www.bitovi.com/services/ai-consulting?hsLang=en-us)
- ![Systems engineering](https://www.bitovi.com/hubfs/icon%20-%20backend.svg)
  
  [Systems engineering](https://www.bitovi.com/services/systems-engineering-consulting?hsLang=en-us)
- ![Project management](https://www.bitovi.com/hubfs/icon%20-%20PM.svg)
  
  [Project management](https://www.bitovi.com/services/agile-project-management-consulting?hsLang=en-us)
- ![Product design](https://www.bitovi.com/hubfs/icon%20-%20design.svg)
  
  [Product design](https://www.bitovi.com/services/product-design-consulting?hsLang=en-us)
- ![Frontend development](https://www.bitovi.com/hubfs/icon%20-%20frontend.svg)
  
  [Frontend development](https://www.bitovi.com/services/frontend-development-consulting?hsLang=en-us)
- [View more
  
  →
  
  ](https://www.bitovi.com/digital-consulting-services?hsLang=en-us)

We're Experts in...

- [JavaScript](https://www.bitovi.com/services/frontend/javascript-consulting?hsLang=en-us)
- [AI training](https://www.bitovi.com/ai-training-for-software-engineers?hsLang=en-us)
- [Angular](https://www.bitovi.com/services/frontend/angular-consulting?hsLang=en-us)
- [Design Systems](https://www.bitovi.com/services/axure-figma-migration?hsLang=en-us)
- [React](https://www.bitovi.com/services/frontend/react-consulting?hsLang=en-us)
- [Temporal](https://www.bitovi.com/services/backend/temporal-consulting?hsLang=en-us)
- [React Native](https://www.bitovi.com/services/frontend/react-consulting/react-native?hsLang=en-us)
- [Node.js](https://www.bitovi.com/services/backend/nodejs-consulting-1?hsLang=en-us)

Showcase

![Yum! Brands](https://www.bitovi.com/hubfs/yum-showcase-link-1.png)

[View case study](https://www.bitovi.com/en/bitovi-yum-case-study?hsLang=en-us)

More Projects

- [![Levi's](https://www.bitovi.com/hubfs/levis.svg)](https://www.bitovi.com/web-application-consulting-work/levis-ecommerce-responsive-redesign?hsLang=en-us)
- [![Christie's International Real Estate](https://www.bitovi.com/hubfs/christies.svg)](https://design.bitovi.com/christies)
- [![BAFS](https://www.bitovi.com/hubfs/bafs.svg)](https://www.bitovi.com/ux-design-consulting/ux-case-studies/bafs-ppp?hsLang=en-us)
- [View more
  
  →
  
  ](https://www.bitovi.com/our-software-consulting-work?hsLang=en-us)

Open Source Tools

We build powerful tools and open source them to support the community.

[See what we've built →](https://www.bitovi.com/open-source?hsLang=en-us)

- [![Blog](https://www.bitovi.com/hubfs/icon%20-%20blog.svg)
  
  BlogWe post about perfecting software delivery
  
  ](https://bitovi.com/blog)
- [![Partnerships](https://www.bitovi.com/hubfs/Handshake-1.svg)
  
  PartnershipsLearn about Bitovi's technology partners
  
  ](https://www.bitovi.com/partnerships?hsLang=en-us)
- [![Academy](https://www.bitovi.com/hubfs/limbo/icons/icon-academy.svg)
  
  AcademyFree courses to build delivery skills
  
  ](https://www.bitovi.com/academy/?hsLang=en-us)
- [![Open source tools](https://www.bitovi.com/hubfs/icon%20-%20open%20source.svg)
  
  Open source toolsUse our tools or contribute to our open source mission.
  
  ](https://www.bitovi.com/open-source?hsLang=en-us)

Let's Connect

- [![Discord](https://www.bitovi.com/hubfs/DiscordLogo.svg)
  
  Discord
  
  ](https://discord.gg/J7ejFsZnJ4)
- [![LinkedIn](https://www.bitovi.com/hubfs/LinkedinLogo.svg)
  
  LinkedIn
  
  ](https://www.linkedin.com/company/bitovi/)
- [![GitHub](https://www.bitovi.com/hubfs/GithubLogo.svg)
  
  GitHub
  
  ](https://github.com/bitovi/)

![Eggbot](https://www.bitovi.com/hubfs/build_assets/bitovi-limbo-cms-react/338/js_client_assets/assets/eggbot-LTGhdSGL.png)

Name *

Work Email *

Phone

What's your project?

Send

### Contact Us

(312) 620-0386contact@bitovi.com

- [ Advanced JavaScript ](https://www.bitovi.com/academy/learn-advanced-javascript.html?hsLang=en-us)
- [ DOM and jQuery ](https://www.bitovi.com/academy/learn-dom-jquery.html?hsLang=en-us) 
    - [ Functional Utilities ](https://www.bitovi.com/academy/learn-dom-jquery/functional-utilities.html?hsLang=en-us)
    - [ Finding Elements ](https://www.bitovi.com/academy/learn-dom-jquery/finding-elements.html?hsLang=en-us)
    - [ Traversing Elements ](https://www.bitovi.com/academy/learn-dom-jquery/traversing-elements.html?hsLang=en-us)
    - [ Attributes and Properties ](https://www.bitovi.com/academy/learn-dom-jquery/attributes-and-properties.html?hsLang=en-us)
    - [ Layout ](https://www.bitovi.com/academy/learn-dom-jquery/layout.html?hsLang=en-us)
    - [ Events Part 1 ](https://www.bitovi.com/academy/learn-dom-jquery/events-part-1.html?hsLang=en-us)
    - [ Events Part 2 ](https://www.bitovi.com/academy/learn-dom-jquery/events-part-2.html?hsLang=en-us)
    - [ Fn Plugins ](https://www.bitovi.com/academy/learn-dom-jquery/fn-plugins.html?hsLang=en-us)
    - [ Tabs Widget ](https://www.bitovi.com/academy/learn-dom-jquery/tabs-widget.html?hsLang=en-us)
- [ Debug JavaScript ](https://www.bitovi.com/academy/learn-to-debug-javascript.html?hsLang=en-us)
- [ Learn TypeScript ](https://www.bitovi.com/academy/learn-typescript.html?hsLang=en-us)
- [ Learn React Native ](https://www.bitovi.com/academy/learn-react-native.html?hsLang=en-us)
- [ Learn Web Components ](https://www.bitovi.com/academy/learn-web-components.html?hsLang=en-us)
- [ Agile Program Management With Jira ](https://www.bitovi.com/academy/learn-agile-program-management-with-jira.html?hsLang=en-us)
- [ Learn RxJS ](https://www.bitovi.com/academy/learn-rxjs.html?hsLang=en-us)
- [ Giving a Training ](https://www.bitovi.com/academy/training.html?hsLang=en-us)
- [ Learn Technology Consulting ](https://www.bitovi.com/academy/learn-technology-consulting.html?hsLang=en-us)
- [ Learn React ](https://www.bitovi.com/academy/learn-react.html?hsLang=en-us)
- [ Learn NgRx ](https://www.bitovi.com/academy/learn-ngrx.html?hsLang=en-us)
- [ Learn Graphql ](https://www.bitovi.com/academy/learn-graphql.html?hsLang=en-us)
- [ Learn Docker ](https://www.bitovi.com/academy/learn-docker.html?hsLang=en-us)
- [ Learn CanJS ](https://www.bitovi.com/academy/learn-canjs.html?hsLang=en-us)
- [ Learn Angular ](https://www.bitovi.com/academy/learn-angular.html?hsLang=en-us)
- [ Advanced TypeScript ](https://www.bitovi.com/academy/advanced-typescript.html?hsLang=en-us)

[View More Courses](https://www.bitovi.com/academy/#courses) [ ]

# Attributes and Properties `page`

Learn about the attributes and properties on an element.

## Overview

We will learn about:

- The difference between attributes and properties
- How to set and read styles on an element

## Slides

## Setup

Run the following example in CodePen:

```
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<link rel="stylesheet" href="//code.jquery.com/qunit/qunit-1.12.0.css">
<script src="//code.jquery.com/qunit/qunit-1.12.0.js"></script>
<script src="//bitovi.github.io/academy/static/scripts/jquery-test.js"></script>
<link rel="stylesheet" href="//bitovi.github.io/academy/static/scripts/jquery-test.css">
<script type="module">
(function() {
  $ = function(selector) {
    if ( !(this instanceof $) ) {
      return new $(selector);
    }
    var elements;
    if (typeof selector === "string") {
      elements = document.querySelectorAll(selector);
    } else if ($.isArrayLike(selector)) {
      elements = selector;
    }
    [].push.apply(this, elements);
  };

  $.extend = function(target, object) {
    for (var prop in object) {
      if (object.hasOwnProperty(prop)) {
        target[prop] = object[prop];
      }
    }
    return target;
  };

  // Static methods
  $.extend($, {
    isArray: function(obj) {
      return Object.prototype.toString.call(obj) === "[object Array]";
    },
    isArrayLike: function(obj) {
      return obj &&
        typeof obj === "object" &&
        (   obj.length === 0 ||
            typeof obj.length === "number" &&
            obj.length > 0 &&
            obj.length - 1 in obj );

    },
    each: function(collection, cb) {
      if ($.isArrayLike(collection)) {
        for (var i = 0; i < collection.length; i++) {
          if (cb.call(this, i, collection[i]) === false) {
            break;
          }
        }
      } else {
        for (var prop in collection) {
          if (collection.hasOwnProperty(prop)) {
            if (cb.call(this, prop, collection[prop]) === false) {
              break;
            }
          }
        }
      }
      return collection;
    },
    makeArray: function(arr) {
      if ($.isArray(arr)) {
        return arr;
      }
      var array = [];
      $.each(arr, function(i, item) {
        array[i] = item;
      });
      return array;
    },
    proxy: function(fn, context) {
      return function() {
        return fn.apply(context, arguments);
      };
    }
  });

  function makeTraverser(traverser) {
    return function() {
      var elements = [], args = arguments;
      $.each(this, function(i, element) {
        var els = traverser.apply(element, args);
        if ($.isArrayLike(els)) {
          elements.push.apply(elements, els);
        } else if (els) {
          elements.push(els);
        }
      });
      return $(elements);
    };
  }

  $.extend($.prototype, {
      html: function(newHtml) {
        if(arguments.length) {
          return $.each(this, function(i, element) {
            element.innerHTML = newHtml;
          });
        } else {
          return this[0].innerHTML;
        }
      },
      val: function(newVal) {
        if(arguments.length) {
          return $.each(this, function(i, element) {
            element.value = newVal;
          });
        } else {
          return this[0].value;
        }
      },
      text: function(newText) {
        if (arguments.length) {
          return $.each(this, function(i, element) {
            element.textContent = newText;
          });
        } else {
          return this[0].textContent;
        }
      },
      find: makeTraverser(function(selector) {
        return this.querySelectorAll(selector);
      }),
      parent: makeTraverser(function() {
        return this.parentNode;
      }),
      next: makeTraverser(function() {
        return this.nextElementSibling;
      }),
      prev: makeTraverser(function() {
        return this.previousElementSibling;
      }),
      children: makeTraverser(function() {
        return this.children;
      }),
      attr: function(attrName, value) { },
      css: function(cssPropName, value) { },
      addClass: function(className) { },
      removeClass: function(className) { }
  });

})();
</script>

```

Each exercise builds on the previous exercise. There is a completed solution at the end of this page.

## Exercise: `collection.attr( attrName [,value] )`

### The problem

[collection.attr](http://api.jquery.com/attr/) either:

- Gets the value of an attribute for the first element in the set of matched elements, or
- sets one or more attributes for every matched element.

```
<a id="link-less">Bitovi</a>
<script type="module">
  import "https://unpkg.com/jquery@3/dist/jquery.js";

  $("a").attr("href", "https://bitovi.com");
</script>
```

Click to see test code

```
QUnit.test("$.fn.attr", function () {
  equal($("#qunit-fixture").attr("id"), "qunit-fixture", "can read id");

  $("#qunit-fixture").html("<span></span><span></span>");

  $("#qunit-fixture span").attr("foo", "bar");

  equal(
    $("#qunit-fixture span")[0].getAttribute("foo"),
    "bar",
    "attribute set successfully"
  );
  equal(
    $("#qunit-fixture span")[1].getAttribute("foo"),
    "bar",
    "attribute set successfully"
  );

  $("#qunit-fixture span")[0].setAttribute("foo", "BAR");

  equal(
    $("#qunit-fixture span").attr("foo"),
    "BAR",
    "read the first item in the collection’s attr"
  );
});
```

### What you need to know

- [getAttribute](https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute) reads an attribute value
- [setAttribute](https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute) sets an attribute value

### The solution

Click to see the solution

```
    attr: function(attrName, value) {
      if (arguments.length == 2) {
        return $.each(this, function(i, element) {
          element.setAttribute(attrName, value);
        });
      } else {
        return this[0] && this[0].getAttribute(attrName);
      }
    },

```

## Exercise: `collection.css( propertyName [,value] )`

### The problem

[collection.css](http://api.jquery.com/css/) either:

- Gets the value of a computed style property for the first element in the set of matched elements,
- or sets one or more CSS properties for every matched element.

```
<div>Foo Bar</div>
<script type="module">
  import "https://unpkg.com/jquery@3/dist/jquery.js";

  $("div").css("backgroundColor", "green");
</script>
```

Click to see test code

```
QUnit.test("$.fn.css", function () {
  $("#qunit-fixture").html("<span>Content</span><span>Second</span>");

  equal($("#qunit-fixture span").css("padding-left"), "20px");

  $("#qunit-fixture span").css("paddingLeft", "40px");

  equal(
    $("#qunit-fixture span").css("padding-left"),
    "40px",
    "first span set to 40px"
  );
  equal(
    $("#qunit-fixture span:nth-child(2)").css("padding-left"),
    "40px",
    "second span set to 40px"
  );
});
```

### What you need to know

- The [style](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style) property is used to set and get the inline style of an element.
  
  ```
  <div id="theDiv">theDiv</div>
  <script type="module">
    theDiv.style.color = "red";
  
    console.log(theDiv.outerHTML);
    // Logs "<div id="theDiv" style="color: red;">theDiv</div>"
  </script>
  ```

- The [window.getComputedStyle](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle) returns an object containing the values of all CSS properties of an element.
  
  ```
  <p id="theP">Hello</p>
  <style>
    p {
      color: green;
    }
  </style>
  <script type="module">
    let computedStyles = window.getComputedStyle(theP);
    console.log(computedStyles.getPropertyValue("color"));
    // logs "rgb(0, 128, 0)"
  </script>
  ```

### The solution

Click to see the solution

```
    css: function(cssPropName, value) {
      if (arguments.length == 2) {
        return $.each(this, function(i, element) {
          element.style[cssPropName] = value;
        });
      } else {
        return this[0] &&
          window.getComputedStyle(this[0])
            .getPropertyValue(cssPropName);
      }
    },
```

## Bonus Exercise: `collection.addClass(className)` and `collection.removeClass(className)`

### The problem

[collection.addClass](https://api.jquery.com/addclass/) adds a class to each element’s `className`. [collection.removeClass](https://api.jquery.com/removeclass/) removes a class to each element’s `className`.

The following changes the `<div>` from green to red after one second.

```
<style>
  .red {
    background-color: red;
  }
  .green {
    background-color: green;
  }
</style>
<div class="red" id="hi">Hello</div>
<script type="module">
  import "https://unpkg.com/jquery@3/dist/jquery.js";

  setTimeout(function () {
    $("#hi").addClass("green").removeClass("red");
  }, 1000);
</script>
```

Click to see test code

```
QUnit.test("$.fn.addClass and $.fn.removeClass", function () {
  var count = function (reg, str) {
    var c = 0;
    str.replace(reg, function () {
      c++;
    });
    return c;
  };

  var $divs = $("#qunit-fixture")
    .html('<div class="foo"></div><div class="foob"></div>')
    .children();

  $divs.addClass("foo");

  equal(1, count(/foo/, $divs[0].className), "only one foo");
  equal(1, count(/foo/, $divs[1].className), "only one foo");

  $divs.addClass("foob");

  equal(1, count(/foob/, $divs[0].className), "only one foo");
  equal(1, count(/foob/, $divs[1].className), "only one foo");

  $divs.removeClass("foob");
  equal(0, count(/foob/, $divs[0].className), "only one foo");
  equal(0, count(/foob/, $divs[1].className), "only one foo");

  $divs.removeClass("foo");
  equal(0, count(/foo/, $divs[0].className), "only one foo");
  equal(0, count(/foo/, $divs[1].className), "only one foo");
});
```

### What you need to know

- An element’s [classList](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList) lets you add and remove class names on it.
  
  ```
  <style>
    .red {
      background-color: red;
    }
    .green {
      background-color: green;
    }
  </style>
  <div class="red" id="hi">Hello</div>
  <script type="module">
    setTimeout(function () {
      hi.classList.add("green");
      hi.classList.remove("red");
    }, 1000);
  </script>
  ```

### The solution

Click to see the solution

```
      addClass: function(className) {
        return $.each(this, function(i, element) {
          element.classList.add(className);
        });
      },
      removeClass: function(className) {
        return $.each(this, function(i, element) {
          element.classList.remove(className);
        });
      }
```

## Complete Solution

Click to see completed solution

```
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<link rel="stylesheet" href="//code.jquery.com/qunit/qunit-1.12.0.css">
<script src="//code.jquery.com/qunit/qunit-1.12.0.js"></script>
<script src="//bitovi.github.io/academy/static/scripts/jquery-test.js"></script>
<link rel="stylesheet" href="//bitovi.github.io/academy/static/scripts/jquery-test.css">
<script type="module">
(function() {
  $ = function(selector) {
    if ( !(this instanceof $) ) {
      return new $(selector);
    }
    var elements;
    if (typeof selector === "string") {
      elements = document.querySelectorAll(selector);
    } else if ($.isArrayLike(selector)) {
      elements = selector;
    }
    [].push.apply(this, elements);
  };

  $.extend = function(target, object) {
    for (var prop in object) {
      if (object.hasOwnProperty(prop)) {
        target[prop] = object[prop];
      }
    }
    return target;
  };

  // Static methods
  $.extend($, {
    isArray: function(obj) {
      return Object.prototype.toString.call(obj) === "[object Array]";
    },
    isArrayLike: function(obj) {
      return obj &&
        typeof obj === "object" &&
        (   obj.length === 0 ||
            typeof obj.length === "number" &&
            obj.length > 0 &&
            obj.length - 1 in obj );

    },
    each: function(collection, cb) {
      if ($.isArrayLike(collection)) {
        for (var i = 0; i < collection.length; i++) {
          if (cb.call(this, i, collection[i]) === false) {
            break;
          }
        }
      } else {
        for (var prop in collection) {
          if (collection.hasOwnProperty(prop)) {
            if (cb.call(this, prop, collection[prop]) === false) {
              break;
            }
          }
        }
      }
      return collection;
    },
    makeArray: function(arr) {
      if ($.isArray(arr)) {
        return arr;
      }
      var array = [];
      $.each(arr, function(i, item) {
        array[i] = item;
      });
      return array;
    },
    proxy: function(fn, context) {
      return function() {
        return fn.apply(context, arguments);
      };
    }
  });

  function makeTraverser(traverser) {
    return function() {
      var elements = [], args = arguments;
      $.each(this, function(i, element) {
        var els = traverser.apply(element, args);
        if ($.isArrayLike(els)) {
          elements.push.apply(elements, els);
        } else if (els) {
          elements.push(els);
        }
      });
      return $(elements);
    };
  }

  $.extend($.prototype, {
      html: function(newHtml) {
        if(arguments.length) {
          return $.each(this, function(i, element) {
            element.innerHTML = newHtml;
          });
        } else {
          return this[0].innerHTML;
        }
      },
      val: function(newVal) {
        if(arguments.length) {
          return $.each(this, function(i, element) {
            element.value = newVal;
          });
        } else {
          return this[0].value;
        }
      },
      text: function(newText) {
        if (arguments.length) {
          return $.each(this, function(i, element) {
            element.textContent = newText;
          });
        } else {
          return this[0].textContent;
        }
      },
      find: makeTraverser(function(selector) {
        return this.querySelectorAll(selector);
      }),
      parent: makeTraverser(function() {
        return this.parentNode;
      }),
      next: makeTraverser(function() {
        return this.nextElementSibling;
      }),
      prev: makeTraverser(function() {
        return this.previousElementSibling;
      }),
      children: makeTraverser(function() {
        return this.children;
      }),
      attr: function(attrName, value) {
        if (arguments.length == 2) {
          return $.each(this, function(i, element) {
            element.setAttribute(attrName, value);
          });
        } else {
          return this[0] && this[0].getAttribute(attrName);
        }
      },
      css: function(cssPropName, value) {
        if (arguments.length == 2) {
          return $.each(this, function(i, element) {
            element.style[cssPropName] = value;
          });
        } else {
          return this[0] &&
            window.getComputedStyle(this[0])
              .getPropertyValue(cssPropName);
        }
      },
      addClass: function(className) {
        return $.each(this, function(i, element) {
          element.classList.add(className);
        });
      },
      removeClass: function(className) {
        return $.each(this, function(i, element) {
          element.classList.remove(className);
        });
      }
  });

})();
</script>

```

###### On this page...

###### Get help

If you need [help](https://discord.gg/J7ejFsZnJ4) with an exercise, please reach out to us on [Discord](https://discord.gg/J7ejFsZnJ4)

If you find a bug, please [create an issue](https://github.com/bitovi/academy/issues/new) or email [contact@bitovi.com](mailto:contact@bitovi.com?Subject=Training%20Suggestion)

## Join the Bitovi Newsletter

 Do you want to receive updates about new Bitovi Academy courses, Bitovi open source projects, and dev community news? If so, please provide your email. We won’t spam you or give it away for any reason!  
*By providing your email you agree to receive communications from Bitovi*

![](https://bitovi.github.io/academy/static/img/close.svg)

```json
{
  "@context" : "http://schema.org",
  "@type" : "Organization",
  "address" : {
    "@type" : "PostalAddress",
    "addressCountry" : "United States",
    "addressLocality" : "Libertyville",
    "addressRegion" : "IL",
    "postalCode" : "60048",
    "streetAddress" : "1134 Pine Tree Lane "
  },
  "alternateName" : "Bitovi",
  "areaServed" : {
    "@type" : "GeoCircle",
    "geoMidpoint" : {
      "@type" : "GeoCoordinates",
      "latitude" : "41.8781",
      "longitude" : "87.6298"
    },
    "geoRadius" : "5000 km"
  },
  "description" : "Bitovi is a UX, UI design and front-end JavaScript development consulting company",
  "email" : "contact@bitovi.com",
  "image" : "https://www.bitovi.com/hubfs/bitovi-logo-x2.png",
  "logo" : "https://www.bitovi.com/hubfs/bitovi-logo-23-1.svg",
  "mainEntityOfPage" : {
    "@id" : "https://www.bitovi.com/academy/learn-dom-jquery/attributes-and-properties.html",
    "@type" : "WebPage",
    "description" : "Learn about the attributes and properties on an element. "
  },
  "naics" : "541511",
  "name" : "Bitovi Web App Consulting",
  "sameAs" : [ "https://www.facebook.com/BitoviLLC/", "https://twitter.com/bitovi", "https://www.linkedin.com/company/bitovi" ],
  "telephone" : "312-620-0386",
  "url" : "http://bitovi.com"
}
```