CSS, Classes & Dimensions
Making things look different is one of the most common reasons to touch the DOM: highlight a selected row, switch to a dark theme, show an error border on a form field. jQuery offers class methods, a .css() method for inline styles, and a set of methods for measuring sizes and positions.
In this lesson you will learn all three groups, the important change in jQuery 4 about units, and the plain JavaScript equivalents: classList, style, getComputedStyle() and getBoundingClientRect().
Classes first
The cleanest way to change how something looks is to define the look in CSS and switch a class from JavaScript. Your styles stay in the stylesheet, and your script only decides which state applies.
| jQuery | Plain JavaScript |
|---|---|
$el.addClass("active") | el.classList.add("active") |
$el.addClass("a b") | el.classList.add("a", "b") |
$el.removeClass("active") | el.classList.remove("active") |
$el.toggleClass("open") | el.classList.toggle("open") |
$el.toggleClass("error", isWrong) | el.classList.toggle("error", isWrong) |
$el.hasClass("open") | el.classList.contains("open") |
The jQuery versions work on every element in the set; the plain versions work on one element, so use forEach for many.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Theme switch</title>
<style>
body { font-family: system-ui, sans-serif; transition: background 0.3s, color 0.3s; }
body.dark { background: #16202a; color: #e8eef4; }
.seat { inline-size: 2.4rem; margin: 0.2rem; padding: 0.3rem 0; background: transparent; color: inherit; border: 1px solid currentColor; border-radius: 4px; cursor: pointer; }
.seat.booked { background: #0769ad; color: #fff; }
</style>
</head>
<body>
<button id="theme">Toggle dark theme</button>
<h2>Choose seats: Jaipur Express, coach B2</h2>
<div id="seats">
<button class="seat">1</button><button class="seat">2</button><button class="seat">3</button>
<button class="seat">4</button><button class="seat">5</button><button class="seat">6</button>
</div>
<p id="summary">No seats chosen.</p>
<script src="https://cdn.jsdelivr.net/npm/jquery@4.0.0/dist/jquery.min.js"></script>
<script>
// Plain JavaScript for the theme
document.querySelector("#theme").addEventListener("click", () => {
document.body.classList.toggle("dark");
});
// jQuery for the seats
$(".seat").on("click", function () {
$(this).toggleClass("booked");
const count = $(".seat.booked").length;
$("#summary").text(count ? count + " seat(s) chosen, ₹" + count * 655 : "No seats chosen.");
});
</script>
</body>
</html>Inline styles with css()
.css() reads or writes inline styles directly. Use it for values you calculate while the page runs, such as a progress bar width.
$("#bar").css("width"); // read the computed width, e.g. "120px"
$("#bar").css("width", "75%"); // write one property
$("#bar").css({ width: "75%", "background-color": "#2e7d32" }); // write several
$(":root").css("--brand", "#0769ad"); // CSS custom properties work too
// Plain JavaScript
const bar = document.querySelector("#bar");
getComputedStyle(bar).width; // read the computed value
bar.style.width = "75%"; // write (camelCase names: backgroundColor)
document.documentElement.style.setProperty("--brand", "#0769ad");As a getter, .css() returns the computed value of the first element (what the browser actually uses after all stylesheets), always as a string such as "16px". Use parseFloat() to get the number.
Units matter in jQuery 4. Older versions added px to almost any plain number you passed. jQuery 4 adds it only for a short list of size properties such as width, height, margin, padding, top and border-width. For anything else, such as font-size, gap or letter-spacing, a plain number is ignored. Run this to see it:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Units in jQuery 4</title>
</head>
<body>
<p id="a">Text A</p>
<p id="b">Text B</p>
<button id="grow">Make both bigger</button>
<pre id="out"></pre>
<script src="https://cdn.jsdelivr.net/npm/jquery@4.0.0/dist/jquery.min.js"></script>
<script>
$("#grow").on("click", function () {
const current = parseFloat($("#a").css("font-size")); // "16px" -> 16
$("#a").css("font-size", current + 4); // number: ignored for font-size in jQuery 4
$("#b").css("font-size", current + 4 + "px"); // string with a unit: works
$("#out").text(
"A: " + $("#a").css("font-size") + "\n" +
"B: " + $("#b").css("font-size")
);
});
</script>
</body>
</html>Text A never grows; text B grows each time. The safe habit for both jQuery and plain JavaScript is simple: always pass a string with its unit.
Measuring sizes and positions
jQuery has methods that measure an element's box. The CSS box has content, then padding, then border, then margin:
| jQuery | Measures | Plain JavaScript |
|---|---|---|
.width() | content only (a number) | parseFloat(getComputedStyle(el).width) (with box-sizing: content-box) |
.innerWidth() | content + padding | el.clientWidth |
.outerWidth() | content + padding + border | el.offsetWidth or el.getBoundingClientRect().width |
.outerWidth(true) | ... + margin | add the margins from getComputedStyle |
.offset() | position relative to the document: { top, left } | rect.top + window.scrollY, rect.left + window.scrollX |
.position() | position relative to the positioned parent | el.offsetTop, el.offsetLeft |
$(window).scrollTop() | how far the page is scrolled | window.scrollY |
.height() and its friends work the same way vertically. One difference: getBoundingClientRect() includes CSS transforms such as scale(), while offsetWidth and jQuery's methods measure the layout size.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Measuring a box</title>
<style>
#card { width: 200px; padding: 10px; border: 5px solid #0769ad; margin: 20px; }
</style>
</head>
<body>
<div id="card">Library card: Kabir</div>
<pre id="out"></pre>
<script src="https://cdn.jsdelivr.net/npm/jquery@4.0.0/dist/jquery.min.js"></script>
<script>
const $card = $("#card");
const card = document.querySelector("#card");
$("#out").text(
"jQuery width(): " + $card.width() + "\n" +
"jQuery innerWidth(): " + $card.innerWidth() + "\n" +
"jQuery outerWidth(): " + $card.outerWidth() + "\n" +
"jQuery outerWidth(true): " + $card.outerWidth(true) + "\n" +
"Plain clientWidth: " + card.clientWidth + "\n" +
"Plain offsetWidth: " + card.offsetWidth + "\n" +
"Plain rect.width: " + card.getBoundingClientRect().width
);
</script>
</body>
</html>You should see 200, 220, 230 and 270 from jQuery, and 220, 230 and 230 from the plain properties.
Common mistakes
- Setting many styles with
.css()instead of a class. Styles scattered through JavaScript are hard to find and override. Put the look in CSS and toggle a class. - Passing plain numbers to
.css()in jQuery 4. Only some size properties getpxadded. Write"18px","1.2rem"and so on. - Overwriting all classes.
.attr("class", "active")orel.className = "active"removes every other class. UseaddClassorclassList.add. - Measuring hidden elements. A
display: noneelement has no layout box, so its sizes are 0. - Expecting
.css("width")to return a number. It returns a string with a unit;.width()returns a number.
Key points
- Switch looks with classes:
addClass,removeClass,toggleClass(name, state)andhasClass, orclassListin plain JavaScript. .css()reads computed values and writes inline styles; plain JavaScript usesgetComputedStyle()andel.style.- jQuery 4 adds
pxonly to certain size properties, so always pass units as strings. .width(),.innerWidth(),.outerWidth()and.outerWidth(true)measure content, padding, border and margin..offset()is relative to the document;getBoundingClientRect()is relative to the viewport, so addscrollYto compare.
Exercise
Build a "marks" bar: a grey track <div> with a coloured bar inside, and an input for marks out of 100. When the input changes, use jQuery to set the bar's width to that percentage with .css() (remember the unit), and use .toggleClass("fail", marks < 33) to turn the bar red for failing marks. Show the bar's measured width in pixels with .outerWidth().
Show solution
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Marks bar</title>
<style>
#track { width: 300px; height: 16px; background: #eee; border-radius: 8px; }
#bar { height: 100%; width: 0; background: #2e7d32; border-radius: 8px; }
#bar.fail { background: #c62828; }
</style>
</head>
<body>
<label>Marks <input id="marks" type="number" min="0" max="100" value="45"></label>
<div id="track"><div id="bar"></div></div>
<p id="px"></p>
<script src="https://cdn.jsdelivr.net/npm/jquery@4.0.0/dist/jquery.min.js"></script>
<script>
function update() {
const marks = Math.min(100, Math.max(0, Number($("#marks").val())));
$("#bar").css("width", marks + "%").toggleClass("fail", marks < 33);
$("#px").text("Bar width: " + $("#bar").outerWidth() + "px");
}
$("#marks").on("input", update);
update();
</script>
</body>
</html>The width is a percentage string, so jQuery 4 applies it correctly, and toggleClass with a condition adds or removes fail in one call.
Quick Quiz
1. What is the plain JavaScript equivalent of $el.toggleClass("open", isOpen)?
classList.toggle with a second argument adds the class when true and removes it when false.
2. In jQuery 4, what happens with $("p").css("font-size", 20)?
jQuery 4 only adds px automatically for a limited set of size properties; write "20px".
3. Which jQuery method includes margin in its result?
Passing true adds the margins to the content, padding and border.
4. What does $("#box").css("width") return?
The getter returns the computed value as a CSS string; .width() returns a number.
Learn jQuery with a mentor
Free lessons get you started. Our Full Stack Web Development training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
