jQuery / Compare width, innerWidth and outerWidth

In jQuery, .width() measures content, .innerWidth() includes horizontal padding, and .outerWidth() also includes horizontal borders. Use .outerWidth(true) to include horizontal margins. These getters return numeric pixel measurements, distinct from a CSS width string.

Choose the boundary to measure

The CSS box model places padding, border and margin around content. Choose the boundary your task needs; a larger number is not inherently a more accurate measurement.

Call Included content-box example border-box example
.width() Content 200 150
.innerWidth() Content + padding 240 190
.outerWidth() Content + padding + border 250 200
.outerWidth(true) Previous + margin 270 220
.css("width") Computed CSS string 200px 200px

These values assume CSS width 200px, padding 20px per side, border 5px per side and margin 10px per side. .width() still measures content under border-box; .innerWidth() and .outerWidth() add their respective boundaries.

With box-sizing content-box, the border extent is 200+40+10=250. With border-box, padding and border fit inside CSS 200, leaving content 150. The meaning of .width() stays constant; the meaning of the CSS assignment changes.

Complete comparison example

Save everything as UTF-8 width-demo.html and open it in a browser. Internet loads the official jQuery file 4.0.0. No server or installation is needed. Initial values, padding changes and restoration, and fractional width were executed in Windows Edge with 3.7.1 and 4.0.0.

The starting styles differ only in box-sizing. Each .case permits local horizontal scrolling on a narrow screen. The output labeled margin is the total .outerWidth(true), not the margin alone.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Compare jQuery width measurements</title>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
  <style>
    body { font: 16px/1.6 sans-serif; max-width: 760px; margin: 20px; }
    button { font: inherit; margin: 4px; }
    .case { overflow-x: auto; background: #f4f7f8; margin: 12px 0; }
    .box { width: 200px; padding: 20px; border: 5px solid teal; margin: 10px; background: #fff; }
    #content { box-sizing: content-box; }
    #border { box-sizing: border-box; }
    pre { white-space: pre-wrap; overflow-wrap: anywhere; }
  </style>
</head>
<body>
  <button type="button" id="padding">Toggle padding 20 / 40</button>
  <button type="button" id="fraction">Toggle width 200 / 200.5</button>
  <button type="button" id="reset">Reset</button>
  <div class="case"><div class="box" id="content">content-box</div></div>
  <div class="case"><div class="box" id="border">border-box</div></div>
  <pre id="result" aria-live="polite"></pre>
  <script>
    $(function () {
      let padding = 20, width = 200;
      function report() {
        const lines = [];
        $(".box").each(function () {
          const $box = $(this);
          lines.push(`${this.id}: css=${$box.css("width")}; width=${$box.width()}; inner=${$box.innerWidth()}; outer=${$box.outerWidth()}; margin=${$box.outerWidth(true)}`);
        });
        $("#result").text(lines.join("\n"));
      }
      $("#padding").on("click", function () {
        padding = padding === 20 ? 40 : 20;
        $(".box").css("padding", padding + "px"); report();
      });
      $("#fraction").on("click", function () {
        width = width === 200 ? 200.5 : 200;
        $(".box").css("width", width + "px"); report();
      });
      $("#reset").on("click", function () {
        padding = 20; width = 200;
        $(".box").css({ padding: "20px", width: "200px" }); report();
      });
      report();
    });
  </script>
</body>
</html>

Initial output: identical CSS widths produce different content and border measurements.

content: css=200px; width=200; inner=240; outer=250; margin=270
border: css=200px; width=150; inner=190; outer=200; margin=220
  1. Press Toggle padding 20 / 40. content-box keeps width=200 while inner=280, outer=290 and margin=310.
  2. border-box keeps its outer border at 200: width=110, inner=190, outer=200 and margin=220. Its content shrinks.
  3. Press again to restore padding 20 and the initial output.
  4. Toggle width 200 / 200.5 increases every width result by 0.5. Do not assume integer returns.
  5. Reset restores width and padding on both boxes without changing site-wide CSS.

Numeric values and multiple elements

A getter without arguments measures the first matched element. Use .each() or .map() for every element. After Reset, run this in developer tools:

console.log($("#content, #border").width());
console.log($(".box").map(function () { return $(this).width(); }).get().join(","));
console.log($(".missing").width(), $(".missing").innerWidth(), $(".missing").outerWidth());

The first line reads only content-box; the second measures both contents. An empty selection returns undefined in the tested jQuery 3.7.1 and 4.0.0.

200
200,150
undefined undefined undefined

Distinguish actual zero width from an empty collection. Check length and the result before arithmetic to avoid NaN from undefined. .css("width") includes units and can concatenate instead of adding numerically. Unconditionally truncating decimals with parseInt can accumulate errors across several elements.

This article covers getters. Passing a value, as in .width(200), changes the operation to a setter; omit arguments when only measuring.

Measurement timing and visible bounds

Avoid relying on dimensions of display:none elements or their descendants. Temporary show-and-hide measurement can be unreliable and expensive; measure after actual layout. visibility:hidden retains layout instead. Images, fonts and dynamic content can change dimensions after DOM readiness, so consider when those resources are applied.

For bounds after CSS transforms, consider getBoundingClientRect(). Applying scale(0.5) to the content-box in this example produced .outerWidth()=250 and native rectangle width=125. Rotation changes the meaning of the enclosing rectangle too; the APIs are not interchangeable.

Do not apply ordinary-element innerWidth or outerWidth to window or document; use their appropriate .width() measurements. A margin-inclusive sum does not explain every layout’s occupied parent width or sibling spacing.

Check real conditions for scrollbars, collapsed table borders, zoom, rounding and changing layouts. Alternating style writes and dimension reads in a loop can cause frequent layout work; consider grouping necessary reads and changes.