jQuery入門道場TOP

3章 属性、CSS操作

この章で登場するメソッド一覧です。

属性、CSS操作

属性とは、そのタグの中に書かれている部分で、例えば、<a href="xxx" target="_blank"> の場合、href="xxx" とtarget="_blank" が該当します。hrefやtargetが名前(キー)で、xxxや _blankが値です。属性を設定・取得・削除する構文を見ていきます。

.attr()

jQueryでは、.attr()というメソッドを使って、属性を設定又は取得しています。.attr()には、4つの構文があります。 他のメソッドと同じく、引数の数や引数のタイプによって、これらの構文を区別します。

.attr(name)

マッチした要素の内の1番最初の要素の属性の値を取得します。

<a href="http://www.yahoo.co.jp/" id="mylink">Yahoo</a>
<a href="http://www.google.co.jp/">Google</a>
var url = $("#mylink").attr("href");
// これで、urlには "http://www.yahoo.co.jp/" と格納されます。
 
var url = $("a").attr("href");
// こちらも同上

1つ目は、IDで指定していますので、マッチ(選択)される要素は、1つのはずです。その要素のhref属性の値を返します(取得します)。(ここではYahooのURL)
2つ目は、クラス名で指定していますので、複数の要素がマッチする可能性はありますが、たとえ複数マッチしても、マッチした要素の最初の要素のhref属性の値を返します。(つまり、こちらもYahooのURL)
(1つの要素にもマッチしない場合やマッチした要素に該当の属性名が無い場合は、undefinedが返ります)

また、HTML5では、頭にdata- を付けることによりカスタム属性を使うことができますが、それも取得することができます。
例えば、以下になります。

<span id="taro" data-myid="101">太郎</span>
var id = $("#taro").attr("data-myid");
// idは、"101"が格納される

.attr(name, value)

属性名(name)に値(value)を設定します。

<img id="myphoto" src="skytree.jpg" />
$('#myphoto').attr('alt', 'スカイツリー');

これで、img要素(#myphoto)にalt「スカイツリー」を付与しています。
また、img要素であれば、src属性を変更して、画像を切り替えることもできます。

$('#myphoto').attr('src', 'skytree2.jpg');

.attr(map)

{name: value, name: value} のオブジェクト形式で、複数同時に属性を設定することもできます。

$('#myphoto').attr({alt: 'スカイツリー', title: '東京の新名所'});

.attr(name, function (index, attr))中級

マッチした要素の全てに第2引数の関数を実行し、その関数から返された値を属性値に設定します。

関数には引数が2つ渡され、1つ目は、マッチした要素のインデックス番号(0スタート)で、2つ目は、マッチした要素の変更前の属性値です。関数内のthisは、処理中の要素を指します。具体例を見てみましょう。

<img src="taro.gif" alt="太郎" title="15歳" />
<img src="jiro.gif" alt="次郎"  title="10歳" />
<img src="saburo.gif" alt="三郎" title="8歳" />
$('img').attr("title", function (index, attr) {
  return "[" + index + "]" + attr + this.alt;
});

上記を実行すると、img要素は次のように書き換えられます。 title属性が書き換えられている所に注目して下さい。

<img src="taro.gif" alt="太郎" title="[0]15歳太郎" />
<img src="jiro.gif" alt="次郎"  title="[1]10歳次郎" />
<img src="saburo.gif" alt="三郎" title="[2]8歳三郎" />

また、もし関数が何も返さない場合やundefinedを返した場合は、その要素の属性値は変更されません。

実は、属性やCSSを設定するjQueryのメソッドのほぼ全てで、上記のような関数を指定する形で設定を行うことができますが(jQueryの最新版であれば)、本書は入門者対象ということもあり、以後、この形は省略していきます。

.removeAttr(name)

指定した属性を削除します。

// title属性を削除します。
$('img').removeAttr("title");

Ver.1.7以上では、半角スペース区切りで複数指定することもできます。

クラス操作

先程見た.attr()を使ってクラス属性を操作することも可能ではありますが、特にクラスは、1つの要素にカンマ区切りで複数割り当てられます。そうすると、とあるクラスだけ足したり消したりするのを.attr() で操作するのは、なかなか大変なことです。1つ足そうと思ったら、既に存在するクラスを上書きして消してしまいかねません。そこで以下のクラス操作専用のメソッドが用意されています。

.addClass(name)

指定されたクラス名をマッチした要素全てに付け足します。半角スペースで繋いで、複数のクラス名を指定することもできます。 例えば、

<style type="text/css">
.woman {
  background-color: pink;
}
</style>
 
<ul>
  <li>太郎</li>
  <li>次郎</li>
  <li id="hanako">花子</li>
</ul>
$("#hanako").addClass("woman");

このようにすると、次の結果になります。

.removeClass([name])

指定されたクラス名をマッチした要素全てから削除します。クラス名を省略した場合は、全てのクラスが削除されます。

$("#hanako").removeClass("woman");

.toggleClass()

.toggleClass(name)

既に該当のクラス名があれば削除し、無ければ追加します。マッチした全ての要素に対して個々に行われます。
以下の例は、クリックする度ごとに太字になったり、元に戻ったりします。(イベントについては、後の章で詳しく見ます)

<style type="text/css">
.boldme {
  font-weight: bold;
}
</style>
 
<span id="clickme">【ここをクリックしてみて!】</span>
$("#clickme").on("click", function () {
  // ↓クリックする度に、ここの処理が呼ばれます
  $("#clickme").toggleClass("boldme");
});

実際のサンプル

クラス名は、半角スペースで区切って複数指定することもできます。

.toggleClass(name, switch)

switchが、true, falseのどちらに評価されるかにより、クラス名を追加するか又は削除するかを決定します。
(trueの場合は追加、falseの場合は削除)

.hasClass(name)

マッチした要素が指定したクラス名を持っている場合は、true、そうでない場合は、falseを返します。
例を見てみましょう。

<ul>
  <li>太郎</li>
  <li>次郎</li>
  <li id="hanako" class="woman">花子</li>
</ul>
// retには、trueが格納されます
var ret = $("#hanako").hasClass("woman");

もし複数の要素がマッチする場合は、その複数の要素の中から1つでも一致するクラスを持つ要素があれば、trueになります。

CSS操作

先程見たクラス操作関数を使ってスタイルを変更することはできます。デザイナと連携が密にできる場合は、その方がいいでしょう。 ただ、個別の要素にインライン方式でCSSを設定することもできます。それが、こちらの.css()になります。 また、既に適用されているCSSの値を取得することもできます。

.css()

.css(name)

マッチした要素の最初の要素から指定したCSSの値を文字列で取得します。 値は計算済みの値が取得されます。
具体例を見てみましょう。

<style>
#outside {
  font-size: 10px;
}
#inside {
  font-size: 2em;
}
</style>
 
<div id="outside">
  <div id="inside">
  </div>
</div>
var ret1 = $("#outside").css("font-size");
var ret2 = $("#inside").css("font-size");
var ret3 = $("#outside").css("width");  // おまけ
 
// 値を出力します。(Firebugなどで動作します)
console.log(ret1);
console.log(ret2);
console.log(ret3);

このようにすると、次の結果になります。

ret1は、ある意味そのままの10pxが取得されています。一方、ret2は、どうでしょうか?CSSで定義済みの2emではなく、20pxが取得されています。これは、2emのような(あまり役に立たない)データではなく、2emを現在の要素に適用した後の計算済みのデータが返ってきます。ret3のwidthは、どうでしょうか?#outsideには、特にwidthの指定はしていませんが、ブラウザで計算済みの値が返ってきました。ここでは、1134pxとなっていますが、ブラウザの横幅を変えればこの値も変わってきます。

なお、単位(px)付きでデータが取得されていることにも留意しておいて下さい。 後に見る .width().height()では、単位が付きません。

.css(name, value)

CSS名(name)に値(value)を設定します。

<div id="zansho">残暑が厳しいざんしょ。</div>
$('#zansho').css('background-color', 'pink');

次の結果になります。

本来ブラウザごとに異なるopacityの設定も、opacityに0.0~1.0(1.0が全部表示)の値を設定するだけで済みます。(-moz-opacityやfilter: alphaは、不要)

また、Ver. 1.6より、相対値を指定することもできます。以下で、現在のpadding-leftの値に、更に15プラスします。

$('#name').css("padding-left", "+=15");

.css(map)

attr(map)の場合と同じく、まとめて設定することができます。

<div id="night">今宵も暑い夏の夜</div>
$('#night').css({
  'background-color': 'pink',
  'font-weight': 'bold',
  color: 'blue'
});

次の結果になります。

'background-color'のようにCSSの名前にハイフンがあるため、''で括っていますが、camel caseと呼ばれる形式で書けば、''を省略できます。ハイフン(-)を取って、その後のワードを大文字にします。 上記を書き換えると、次のようになります。

$('#night').css({
  backgroundColor: 'pink',
  fontWeight: 'bold',
  color: 'blue'
});

どちらの記述でも大丈夫です。

幅、高さ操作

直前で見た.css()を使っても幅や高さを取得することは可能ですが、より便利な.width()と.height()が用意されています。

.width()

.width()

マッチした要素の最初の要素の幅を整数値(単位はpx)で取得します。値は計算済みの値が取得されますので、例えば、50%などが要素に指定されていた場合は、それをpx単位で計算した値が返されます。
.css("width")との違いは、.css("width")は、単位付きの文字列を返すのに対し、.width()は、単位を除いた整数値で返します。その為、計算ですぐに使うことができます。
具体例を見てみましょう。

<style>
#outside {
  width: 100px;
}
#inside {
  width: 50%;
}
</style>
 
<div id="outside">
  <div id="inside">
  </div>
</div>
 
<div id="alone">
</div>
var ret1 = $("#outside").width();
var ret2 = $("#inside").width();
var ret3 = $("#alone").width();
 
// 値を出力します。(Firebugなどで動作します)
console.log(ret1);
console.log(ret2);
console.log(ret3);

このようにすると、次の結果になります。

ret3は、特にCSSでは幅を指定していませんが、その都度計算された値を返しています。(ここではたまたま、1115になっています)

width()は、CSS3 box-sizingの値に関わらず、content width(paddingよりも更に内側の表示領域)の値を返します。 また、次のような使い方もできます。

$(window).width();   // ブラウザの横幅
$(document).width(); // HTMLドキュメントの横幅
 
$(window).height();// ブラウザの高さ

横にスクロールバーが出る状態の時は、HTMLドキュメントの方が、ブラウザの横幅よりも大きくなりますね。

少し余談ですが、この.width()メソッドがもし無かった場合、数値で横幅を得たい場合はどうすれば良いでしょうか? その場合は、.css("width")で取得した値をJavaScript関数の.parseInt()に掛ければOKです。

// 実際には、.width() があるので、このような処理は不要
var w = $("#div1").css("width");
var width = parseInt(w, 10);

parseIntには、トラブル防止の為、第2引数に10(10進数)を指定するのが良い習慣です。

.width(value)

幅をvalueに設定します。valueを150などのように単位を省略した場合は、pxが自動で設定されます。'50%'などのように単位付きの文字列で指定することもできます。
例)

$("#outside").width(500);

少し込み入った話ですが、今時の近代的ブラウザでは、CSSのwidthは、デフォルトでは、padding、border、marginを含みません(content-box) 。しかし、CSS3の{box-sizing: border-box;}とすることで、paddingとborderを含むようにすることができます。jQueryでは、{box-sizing: border-box;}の時は、content widthの幅ではなく、outerWidthの幅を設定(変更)します。

.height()

width()の縦バージョンです。width()を参照して下さい。

.innerWidth()、.innerHeight()

上記の .width()は、borderやpadding幅も含まないのに対して、.innerWidth()は、paddingの幅は含みます。(borderは含みません)
.innerHeight()も同様です。

.outerWidth()、.outerHeight()

.outerWidth([includeMargin])、.outerHeight([includeMargin])

もし引数が省略されているかfalseの場合は、borderとpadding幅も含んだ横幅を返します。引数にtrueを指定した場合は、更にmargin幅も含みます。
.outerHeight()も同様です。

スクロール操作

.scrollTop()

.scrollTop()

マッチした最初の要素のスクロールバーの縦位置(整数値)を取得します。スクロールバーが表示されない状態の時は、0になります。ブラウザの一番右にあるバーだけがスクロールバーとは限らず、例えばDIV要素でoverflowした場合でも、スクロールバーが出ることはあります。

// スクロールバーの位置を取得します。
var top = $(window).scrollTop();
var top = $("#info_box").scrollTop();

.scrollTop(value)

マッチした要素全てに対し、valueで指定した値にスクロールバーの縦位置を移動します。

// スクロールバーの位置を指定します。
$(window).scrollTop(50);

.scrollLeft()

マッチした要素の最初の要素のスクロールバーの横(水平)位置を取得します。(左側から起算) 他は、.scrollTop()と同様です。

座標位置

.offset()と.position()を見てみます。.offset()は、簡単です。.position()は、少し曲者です。しかし、この2つのメソッド、日本人の私が言うのも何ですが、直感的にはメソッド名を逆にした方が良かったでしょう…。

.offset()

.offset()

マッチした要素の最初の要素のHTMLドキュメントに対する相対位置を返します。leftとtopをプロパティに持つオブジェクト形式で返ります。

(ドキュメント上での左上からの位置であり、ブラウザウインドウ(viewport)の左上からの位置とは区別しておきましょう。 つまり縦長のサイトで、ずーと下にスクロールしてようやく出てきた要素は、その分の高さがtopに加わっています)

<style>
* {
  margin: 0;
  border: 0;
  padding: 0;
}
#outside {
  background-color: beige;
  margin: 50px;
  padding: 20px;
}
#inside {
  background-color: gold;
  margin: 10px;
}
</style>
 
<div id="outside">
  <div id="inside">
  
  </div>
</div>
var xy;
xy = $("#outside").offset();
console.log(xy);
 
xy = $("#inside").offset();
console.log(xy);

実際のサンプル

Firebugなどで確認すると、次の結果になります。

上記の場合、xy.top、xy.leftなどとして、値を取り出せます。

.offset(coordinates)

下で出てくるposition()と異なり、.offset()は位置の設定に使うこともできます。topとleftをプロパティに持つオブジェクトを引数に指定します。

$("#outside").offset({top: 100, left: 200});

もし指定した要素のCSSのpositionの値がstaticの場合は、座標位置を変更するために、relativeに変更されます。

.position()やや中級

CSSのposition: xxxの知識を必要とするため、やや中級者向けかも知れません。 .offset()が、HTMLドキュメントからの相対位置を返すのに対し、.position()は、offset parentからの相対位置を返します。offset parentと聞きなれない言葉が出てきましたが、これは、jQueryでは、CSSのpositionでstatic以外(relative, absolute, fixed)に設定されている直近の先祖要素を指します。もし、relativeなどを一切使っていなければ、HTMLドキュメントからの相対位置を返すため、.offset()と同じか又は似たような値になります。(offset()とは、マージンの扱いに違いあり)

この.position()では、時折「親要素からの相対位置」という解説を見かけますが、これでは説明不足で、誤解を招きます。更にメソッド名が紛らわしいせいか、.offset()と完全に取り違えて覚えている方もいます。

具定例を見てみましょう。.offset()の例もついでに見てみます。

<style>
* {
  margin: 0;
  border: 0;
  padding: 0;
}
#outside {
  background-color: beige;
  position: absolute;
  top: 100px;
  left: 100px;
  width: 100px;
  height: 100px;
}
#inside {
  background-color: gold;
  position: relative;
  top: 30px;
  left: 30px;
  width: 30px;
  height: 30px;
}
</style>
 
<div id="outside">
  <div id="inside">
  
  </div>
</div>
var xy;
xy = $("#outside").offset();
console.log(xy)
 
xy = $("#outside").position();
console.log(xy)
 
xy = $("#inside").offset();
console.log(xy)
 
xy = $("#inside").position();
console.log(xy)

実際のサンプル

Firebugなどのコンソール画面で確認すると、次の結果になります。

CSSで親要素をposition: absolute;にして子要素をposition: relative;にすると、子要素は、親要素からの相対位置で配置されます。 最初の2つは同じ結果になっています。3つ目は、100pxと30pxが足されて、130pxになっています。そして一番のポイントは、一番最後の.position()です。insideのoffset parentは、outsideなので、outsideからの相対位置が取得されます。

もしまだ余裕のある方は、もう一例見てみましょう。入門者の方は、飛ばして下さい。.offset()と.position()のマージンの取り扱いの違いを見てみます。HTMLとCSSは、.offset()で使ったものと同じです。

<style>
* {
  margin: 0;
  border: 0;
  padding: 0;
}
#outside {
  background-color: beige;
  margin: 50px;
  padding: 20px;
}
#inside {
  background-color: gold;
  margin: 10px;
}
</style>
 
<div id="outside">
  <div id="inside">
  
  </div>
</div>
var xy;
xy = $("#outside").offset();
console.log(xy);
 
xy = $("#outside").position();
console.log(xy);
 
xy = $("#inside").offset();
console.log(xy);
 
xy = $("#inside").position();
console.log(xy);

実際のサンプル

Firebugなどのコンソール画面で確認すると、次の結果になります。

今度は、position: relative;などを使っていないため、.offset()と.position()は、同じ結果になると思いたいところでしたが、違う結果になりました。 よくよく見てみると、マージン分に差があります。つまり、.offset()の場合は、マージンを含まない箇所を左上として計算しているの対し、.position()の場合は、マージンを含めた箇所を左上として計算しています。