JavaScript

When dealing with the width of DOM elements in JavaScript, properties like offsetWidth and clientWidth differ depending on whether they include padding and borders, and the actual displayed width can also vary based on box-sizing and the style.width setting, so it’s essential to understand each characteristic and choose the right method according to your needs.

width [property]

 要素の「幅(width)」を扱う場合、単に style.width に値を代入するだけでなく、実際に描画されている幅を取得したい場合など、いくつかの方法や概念があります。

幅の取得方法

 ブラウザ上でレンダリングされた要素の幅を取得するには、大きく分けて以下のプロパティがよく使用されます。

 これらは似たように見えますが、取得できる値や含まれる余白等が異なります。

offsetWidth

特徴
要素の幅に加えて、左右のパディング(padding) や境界線(border) の幅も含んだ値を取得できます(スクロールバーは含まない)。
主な用途
実際のボックスモデル(枠線やパディングを含む)全体の幅を知りたい場合に便利です。
サンプルコード

JavaScript

const element = document.getElementById("someElement");
console.log(element.offsetWidth);

もし CSS で以下のように指定している場合

CSS

#someElement {
	width: 100px;      /* コンテンツ領域 */
	padding: 10px;     /* 左右合計で20px */
	border: 2px solid black; /* 左右合計で4px */
}

offsetWidth はおおよそ「100 + 20 + 4 = 124px」となります(実際には整数値で返されます)。

clientWidth

特徴
要素のコンテンツ幅 + 左右のパディングを含むが、境界線(border) やスクロールバーは含まない値です。
主な用途
内側のコンテンツ領域(+ パディング)だけの幅を確認したいときに使用します。
サンプルコード

JavaScript

const element = document.getElementById("someElement");
console.log(element.clientWidth);

先ほどと同じ CSS

CSS

#someElement {
	width: 100px;
	padding: 10px;      /* 左右合計で20px */
	border: 2px solid black; /* 含まれない */
}

clientWidth はおおよそ「100 + 20 = 120px」となります。

scrollWidth

特徴
要素全体のスクロール可能な領域の幅を返します。要素にスクロールバーが必要なほど横にコンテンツがはみ出している場合、コンテンツ部分を含む実質的な全幅を取得できます。
主な用途
横スクロールが発生しているかどうか確認したり、スクロールで切れている部分まで含めた幅を取得したいときに使います。
サンプルコード

JavaScript

const element = document.getElementById("someElement");
console.log(element.scrollWidth);

例えば、スタイルが width: 100px; overflow: auto; で、中に200px分のテキストが入っている場合、実際に表示されるのは100px幅ですが、scrollWidth は 200px 相当の値が返ってきます。

getBoundingClientRect()

特徴
画面表示の都合(スクロール位置、拡大率など)を考慮しつつ、要素の位置情報や幅・高さなどの「ピクセル単位の絶対値」を含む情報を取得できます。
主な用途
要素の画面上での位置(左上座標など)や、ピクセルベースの実際の幅・高さを正確に取りたいときに使用します。width プロパティも返ってきます。
サンプルコード

JavaScript

const element = document.getElementById("someElement");
const rect = element.getBoundingClientRect();
console.log(rect.width);

rect.width は要素の描画上の幅(小数点を含む可能性あり)を返します。レスポンシブデザインなど、拡大率が変わる状況にも対応して正確な値を得られます。

幅の設定方法

element.style.width

 JavaScript から要素の幅を直接変更する方法として最もシンプルな手段は、インラインスタイルとして幅を指定することです。

JavaScript

const element = document.getElementById("someElement");
element.style.width = "200px";

クラス名を切り替える

 幅を変更するために、あらかじめ CSS クラスを定義しておき、JavaScript 側でクラスを切り替える方法です。

CSS

.large-width {
	width: 300px;
}
.small-width {
	width: 100px;
}

JavaScript

const element = document.getElementById("someElement");

// 幅を大きくする
element.classList.add("large-width"); 

// 幅を小さくする
element.classList.remove("large-width");
element.classList.add("small-width");

 この方法は、コード上の見通しがよく、変更点を CSS にまとめやすいという利点があります。

幅を扱ううえでの注意点

CSS の Box Sizing

 CSS の box-sizing プロパティが content-box(初期値) か border-box かによって、width が示す範囲が変わります。

content-box(初期値)
width は コンテンツ領域の幅を指す。
border-box
width は パディングやボーダーを含めた全体の幅を指す。

CSS

/* 例: border-box を適用した場合 */
#someElement {
	box-sizing: border-box;
	width: 100px; 
	padding: 10px;  /* この場合、実際の要素の全幅は 100px のまま */
}

 box-sizing を利用する場合、先ほど紹介した offsetWidth や clientWidth がどの範囲を含むか、結果の値が変わってくるので注意してください。

レイアウトの再計算 (Reflow)

 offsetWidth や clientWidth など、要素のレイアウト情報を参照するプロパティを呼び出すと、ブラウザは場合によってはレイアウトの再計算(reflow) を行います。

ブラウザ依存

 基本的にはどのモダンブラウザでも offsetWidth / clientWidth / scrollWidth は同様に動作します。しかし、旧式ブラウザや一部ブラウザでの振る舞いが微妙に異なるケースもあります。レガシーブラウザ対応が必要な場合は注意が必要です。