この記事は非常に長いですが、間違いなく中身の濃い実用的な内容です。HTML、JavaScript、CSS、jQueryの使用に関する規範や提案を説明しています。フロントエンド開発者はこの記事をじっくり読み、日頃の自分の習慣と比較して、改善すべき点があるかどうかを確認してみてください……


HTML

どうした、DOCTYPE?

DOCTYPEを定義しないことは、死刑に値する罪です。以前は以下のDOCTYPEを使っていたかもしれませんが、今はもっと簡潔で明確なコードに置き換えられていることを知っておくべきです。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

理想的なのはHTML5 DOCTYPEを使用することです。すべてのモダンブラウザがこれをサポートしており、HTML5をサポートしないブラウザ(IE6、IE7など)でも、これにより標準モードに移行します。参照:出典。

<!DOCTYPE html>

妥当で意味的に明確なマークアップを書く

きれいで意味的に明確なHTMLでWebサイトのコードを書くことは、私たちが常に追求していることです。時には、先人がページを設定した方法に制約されたり、HTML形式のメールテンプレートを書くこともあります。しかし、特定のブラウザ互換性のバグを解決するためであっても、HTMLの仕様から逸脱してはなりません。

すべての見出しは<h2>から階層的に作成し始め、テキストの段落は常に<p>タグ内に置く、といった具合です。意味的に明確なHTMLを書けば、生成されるページはよりきれいで簡潔になり、検索エンジンのクローラーにも解析されやすくなります。これはあなたができる最も簡単なSEO対策です。

次の段落を見てください。どちらがきれいだと思いますか?これですか?

<span class="sectionHeading">A Heading</span>
<br /> <br />
Lorem ipsum dolor sit amet. ...
<br /> <br />

それともこれですか?

<h2>A Heading</h2>
<p>
    Lorem ipsum dolor sit amet. ...
</p>

マウス中クリックへの対処方法

現代のWebアプリケーションにおける最もイライラさせられるユーザビリティの欠陥の1つは、ハイパーリンク機能のバリエーションです。ハイパーリンクのように見える一部の要素は、JavaScriptによってクリック機能がマッピングされている可能性があり、そのためマウス中クリック(新しいタブでリンクページを開く)の機能が壊れています。仮に新しいタブで開けたとしても、それらは単に#のhrefを持っているだけで、同じページに戻されてしまいます。

この問題を如実に示す現代の人気Webサイトの例がTwitterです。Twitterアプリ全体で、ユーザー名やアバターをマウス中クリックすると、まったく異なる結果になります。

<!-- 旧的方式,破坏网页语义 -->
<a href="../index.html"></a>

<!-- 如果鼠标点击不能产生一个页面,那就不是超链接 -->
<span class="link" role="link"></span>

もう1つの代替案は、#ハッシュで誘導されるパスを使用することです。これにより、通常のURLを#ハッシュで誘導されるリンクにマッピングし、AJAXでページの断片を取得します。この機能を提供するライブラリは、マウス中クリック時にページを正常に表示できるようにするか、左クリック時にそのページの内容を指定された領域に読み込むようにする必要があります。ただし、この方法は慎重に行う必要があります。多くの人が「#リンクはWebアプリを壊している」と考えています。。

Microformats形式で連絡先情報を表す

Microformatは、連絡先情報を機械が読み取りやすくするための方法です。hCardクラス(vCardではなく)は、要素に含まれるコンテンツの種類を定義するために使われます。これらのコンテンツはブラウザによって抽出され、強調表示されます。

<span class="tel">
    <span class="type">home</span>:
    <span class="value">+1.415.555.1212</span>
</span>

この形式を採用したWebページを閲覧したことがあれば、SkypeのようなプログラムがWebページ上のどの数字が電話番号かを簡単に検出できることに気づくでしょう。iOSデバイスのSafariブラウザも同様のことができます。

Microformatの詳細については、次を参照してください。http://microformats.org/wiki/hcard

画像には 'Alt' テキストが必要

<img>タグにはaltテキストが必要です。読みやすさの要件を確認し満たすためです。alt属性内のテキストは、画像が表示する内容や達成しようとする効果を説明できなければなりません。ただし、その画像が重要でない場合は除きます。

画像がリストの箇条書き記号やその他の重要でないアイコンにすぎない場合は、alt属性には空文字列を指定するのが最善ですが、属性自体は残しておきます。そうすればスクリーンリーダーはそれを無視し、「箇条書き記号」を20回も読み上げることはありません。

<img src="dog.gif.html" alt="Fido and I at the park!" />
<!-- 很好,描述清晰 -->

<img src="bullet.gif.html" alt="bullet" />
<!-- 不好,显得多余 -->

<img src="bullet.gif.html" alt="" />
<!-- 好 -->

tableタグはテーブルデータにのみ使用する

tableタグは常にテーブルデータの表示にのみ使用すべきです。唯一の例外はHTML形式のメールを作成する場合で、その場合、tableは一部の迷惑なメールクライアントが唯一サポートするスタイルである可能性があります。

読みやすさのため、テーブルの見出しには常に<th>要素を使用します。また、必ずcellpadding, cellspacingとborderの値を0に設定します。これらのスタイルはCSSで制御する方が一貫性を保ちやすいためです。

<table cellpadding="0" cellspacing="0" border="0">
    <thead>
        <tr>
            <th>
                Cell Header
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                Cell Item
            </td>
        </tr>
    </tbody>
</table>

jQuery と jQuery UI Widgets を使用する

jQueryとjQuery UIは、さまざまなブラウザでほぼ同じ外観と機能を提供するように作られています。jQuery UIはWAI WCAG 2.0およびWAI ARIAに準拠するように設計されているため、このフレームワークを採用することで、サイト上で動作するプラグインやスクリプトの不確実性をすべて回避できます。


JavaScript

コードの空白と書式

コードの書式、空白、中括弧の位置に関する議論は、常に激しい論争を引き起こします。これについて、最も簡単なルールは、コードファイル全体を再フォーマットする気がない限り、既存のコードファイルの書式を尊重し維持することだと思います。つまり、JSファイルで中括弧が改行されずに書かれているのを見たら、あなたのコードも中括弧を改行せずに書き続ける必要があります。あなたのコードがコードファイル内の他の部分と一貫性がなければ、コードレビューのプロセスを通過すべきではありません。

一貫したコード書式はコードを読みやすくし、検索/置換コマンドで簡単に変更できるようにもします。ありがたいことに、私たち自身のプログラミング習慣はjQueryが公式に推奨する方法と非常によく似ています。わずかな違いもありますが、それは個人的な問題か、私たちが維持できないと感じるものによるものです。参照:jQueryコアスタイルガイド

文字間隔

// 不好
if(blah==="foo"){
    foo("bar");
}

// 好 :)
if (blah === "foo") {
    foo("bar");
}

中括弧は改行しない

// 不好
if (foo)
{
    bar();
}

// 好 :)
if (foo) {
    bar();
}

常に中括弧を使用する

// 不好
if (foo)
    bar();

// 好 :)
if (foo) {
    bar();
}

文字列処理

文字列を引用するときは常に二重引用符を使用する。C言語風の文字列(一重引用符)を好む人もいますが、その習慣はスクリプト内でスタイルの衝突を引き起こします。C言語風の文字列処理では、空文字列と単一文字は一重引用符で囲み、フレーズや単語は二重引用符で囲む必要があります。

コメント

コードに必死でコメントを追加するという要求は、さまざまなマネージャーやスーパーバイザー、その他コードにほとんど触れない人々によって主導されています。そのような要求は、従業員の評価項目のチェックボックスにすぎず、それに費やす時間はほとんど利益をもたらしません。もし賢明な開発者がこの文書で提案されたアドバイスに従えば、彼らのコードは非常に読みやすく、一目で理解できるようになり、それらをコメントで説明することがかえって恥ずかしいほど冗長になります。次の例を見てください。ここでは、ブール変数が質問として提示され、関数にも直感的な名前が付けられています。

if (user.hasPermission) {
    editPage();
}

少なくともこのシナリオでは、コメントはまったく不要です。

コメントが重要な場合

プロジェクトには、常に調べたり理解したりするのが難しい部分が存在します。たとえば、複雑な正規表現や、角度を計算したり度とラジアンの単位を切り替えたりする数学関数などです。上記のようなコメントがないと、初級または中級の読者はスクリプトの意味をまったく把握できません。

// 校验美国电话号码的正则表达式,号码格式是 (XXX) XXX-XXXX (减号、空格和括号都是可选的,可以有也可以没有)
var phoneRegEx = /^\(?(\d{3})\)?[- ]?(\d{3})[- ]?(\d{4})$/;

常に === 比較演算子を使用する

== 比較演算子を使用すると、イライラするバグが跡形もなく消えることがあります。これによりJavaScript Garden中には、弱い型付けについて明確に説明されています。厳密な === 比較演算子は型強制を実行しないため、2つのオブジェクト間の差異を厳密に評価できます。繰り返しますが、詳細については次を参照してください。JavaScript Garden。

var zeroAsAString = "0";

if (zeroAsAString == 0) {
    // 这样也能判断为true,呵呵...
}

if (zeroAsAString === 0) {
    // 判断为false
}

例外

null と比較する場合、== 比較演算子の使用は許可されます。なぜなら、null と undefined の両方を検出するからです。この仕組みを完全に理解していないのであれば、=== 比較演算子を使うことをお勧めします。

var foo = null;

// foo 是 null, 但 bar 是 undefined ,因为它尚未被声明
if (foo == null && bar == null) {
    // 上面的判断还是成立的
}

.parseInt() を使用するときは、常に2番目の 'radix' パラメータを指定する

文字列を整数に解析するとき、2番目の基数引数を指定するのは良い習慣です。これにより、その文字列が何進数に変換されるかが決まります。文字列が0で始まる場合、デフォルトでは16進数が基数として使用されます。ほとんどの初心者および中級ユーザーは、10この基数だけを使うでしょう。João Moreno が記録したこの正誤表。

alert( parseInt("08") ); // alerts: 2

alert( parseInt("08", 10) ); // alerts: 8

true と false の比較を避ける

true と false の値を直接比較する必要はありません。場合によっては明確にすることに利点があるかもしれませんが、それは結局のところ余分なコードです。

if (foo === true) {
    // 用了 === 倒是不错,可这是多余的
}

if (foo) {
    // 赞!
}

if (!bar) {
    // 反过来也赞
}

グローバル名前空間の汚染を避ける

グローバル変数への過度の依存は、私たちチーム全員、特に私自身が特に罪悪感を感じていることの一つです。なぜグローバル変数が良くないのかという議論は非常に単純明快です。それはスクリプトや変数の衝突の可能性を高め、ソースファイルや名前空間自体が、名前の不明瞭な変数で数え切れないほど溢れることになります。

Douglas CrockfordJavaScript アプリケーションのコード品質は、そこで使用されるグローバル変数の数で評価できると確信しています。少なければ少ないほど良いのです。すべてを local に定義できるわけではありませんが(正直に言うと、今考えているその変数は local にできます。怠けないでください)、衝突を避けて名前空間の膨張を最小限に抑えるために、変数を整理する方法を考える必要があります。最も簡単な方法は、単一の変数を採用するか、それらのグローバル変数を使用するモジュールを可能な限り減らすことです。Crockford は YUI が YAHOO という1つのグローバル変数だけを使っていると述べています。彼は自身のブログ記事「グローバル支配」で、より詳細な問題について論じています。

次のようなケースを考えてみましょう。小規模な Web アプリケーションでは、グローバル変数は通常、アプリケーションレベルの設定を保存するために使用されます。プロジェクト名や settings を名前としてオブジェクトを定義する方が、全体的に良いでしょう。

// 被污染的全局命名空间
var settingA = true;
var settingB = false;
var settingC = "test";

// 用 settings 作为对象命名
var settings = {
    settingA: true,
    settingB: false,
    settingC: "test"
}

しかし、グローバル変数を避けることで衝突の可能性を減らせるとしても、名前空間を標準化して同じにしてしまったら、アプリケーション間で衝突が起こる可能性が高まるのではないでしょうか?ええ、その懸念はもっともです。そこで、独自のアプリケーション名をグローバル変数の名前空間として使うか、jQuery が採用している$.noConflict()パターンと同じ方法で名前空間を再割り当てすることをお勧めします。

var myAppName = {
    settings: {
        settingA: true
    }
}

//访问全局变量
myAppName.settings.settingA; // true

変数名はキャメルケースで付ける

JavaScript の変数におけるキャメルケース命名は、ほとんどのプログラミング環境で標準とされています。コメントで読者が唯一の例外として挙げたのは、定数を表すために大文字とアンダースコアを使うことです。

var X_Position = obj.scrollLeft;

var xPosition = obj.scrollLeft; // 更好,更简洁

SCENE_GRAVITY = 1; // 常量

ループのパフォーマンス - 配列の長さをキャッシュする

ループは、おそらく JavaScript のパフォーマンスチューニングの中で最も重要な部分です。ループ内で1〜2ミリ秒節約できれば、全体で数秒の節約になるかもしれません。ここでのコツは、配列の長さをキャッシュして、ループ内で反復のたびに毎回計算しなくても済むようにすることです。

var toLoop = new Array(1000);

for (var i = 0; i < toLoop.length; i++) {
    // 败家玩意 - 长度会反复算 1000 次你知道不?
}

for (var i = 0, len = toLoop.length; i < len; i++) {
    // 会过日子 - 长度只计算一次,然后缓存了
}

例外

配列をループして要素を検索し削除する場合、配列の長さが変わります。ループ内で要素を追加または削除して配列の長さを変える可能性があるときはいつでも、自分自身に問題を招いています。この場合、変更のたびに配列の長さを再設定するか、キャッシュしないかのどちらかにすべきです。

ループのパフォーマンス - 'break;' と 'continue;' を使用する

ループをスキップしたり抜け出したりする機能は、コストの高いループ周期を避けるのに非常に役立ちます。

ループ内で検索を行っている場合、検索が成功した後、あなたは何をしますか?例えば、1000要素のループが半分まで実行されたところで、探しているものを見つけたとします。後の if 文がもう一致する可能性がないと分かっていても、ループを続けて残り500要素を反復し終えますか?いいえ、ループを抜けるべきです。絶対に!

var bigArray = new Array(1000);

for (var i = 0, len = bigArray.length; i < len; i++) {
    if (i === 500) {
        break;
    }
    console.log(i); // 这样只会输出 0 - 499
}

もう一つの問題は、特定の反復をスキップしてループを続けることです。奇数・偶数などの条件は、i++に置き換えるi + 2という方法で管理できますが、一部の条件は具体的に検出してスキップ操作をトリガーする必要があります。完全な反復処理の実行を避けられるものは何でも非常に有用です。

var bigArray = new Array(1000);

for (var i = 0, len = bigArray.length; i < len; i++) {
    if (condition) {
        continue;
    }
    doCostlyStuff();
}

関数呼び出しではパラメータを渡しすぎない

可読性という点だけを考えても、次の方法は最悪です:

function greet(name, language, age, gender, hairColour, eyeColour) {
    alert(name);
}

次の例では、オブジェクトを事前に構築して引数として渡すか、インラインオブジェクトを渡します。これならはるかに良いです。

function greet(user) {
    alert(user.name);
}

greet({
    name: "Bob",
    gender: "male"
});

'this' を 'self' にマッピングする

オブジェクト指向(OO)JavaScript コードを書くときは、thisの作用範囲を理解する必要があります。擬似クラスを構築するためにどのようなデザインパターンを使うにしても、thisへの参照は、インスタンスを指す最も簡単な方法です。jQuery のヘルパーメソッドを自分の擬似クラスと統合し始めると、thisの作用範囲が変化することに気づくでしょう。

Bob.findFriend("Barry");

Person.prototype.findFriend = function(toFind) {
    // this = Bob
    $(this.friends).each(function() {
        // this = Bob.friends[i]
        if (this.name === toFind) {
            // this = Barry
            return this;
        }
    });
}

上記の例では、thisは、Bobへの参照から、その友人であるBarryへの参照へと変化する過程をたどります。thisの値が時間とともに変化することを理解することは重要です。プロトタイプ関数の内部では、thisは、所にする擬似クラスの現在のインスタンスを指します(ここではBob)。しかし、$.each()ループに入ると、thisは、解析対象の配列のi番目の要素に再マッピングされます。

解決策は、thisの値をselfまたは_selfに再マッピングすることです。self(アンダースコアなし)は、予約語ではありません。しかし、それは確かに windowオブジェクトのプロパティです。上記でselfの例は jQuery のソースコードから取ったものですが、彼らもこの間違いを認識しており、現在の状況を修正しようとしています。具体的には_selfに変更する予定です。個人的にはselfが好きです。他でもなく、その簡潔さのためです。ただし、非常に紛らわしいバグを引き起こす可能性があります。とにかく、selfを使用するのはリスクがあり、慎重に使用する必要があります。

次の例では、$.each()ヘルパー内で提供される引数をより有効に活用し、同時にthisの値を再マッピングします。

Bob.findFriend("Barry");

Person.prototype.findFriend = function(toFind) {

    // 就这一次用到了 "this"
    var _self = this;

    $(_self.friends).each(function(i,item) {
        if (item.name === toFind) {
            return item;
        }
    });

}

Boolean を使ってもいいですか?

ブール変数は、命名によって簡単に識別できる必要があります。例えばis, canまたはhasのような接頭辞を使って疑問文を形成できます。

isEditing = true;

obj.canEdit = true;

user.hasPermission = true;  

再描画と再レイアウトを最小限に抑える

再描画と再レイアウトは、特定の属性や要素が変更されたときに発生する DOM の再レンダリングのプロセスに関連しています。再描画は、要素の外観が変更されたがレイアウトの調整が行われていない場合にトリガーされます。Nicole Sullivan は、包括的なブログ記事の中で、これらの変更を可視性や背景色の変化などのスタイルの変更として説明しています。再レイアウトは、ページレイアウトを調整する変更によって引き起こされる、よりコストの高い操作です。例えば、要素の追加や削除、要素の幅や高さの変更、さらにはブラウザウィンドウのサイズ変更などです。最悪の場合、再レイアウトは祖先、兄弟、子ノードの要素も再レイアウトする必要があるドミノ効果を引き起こします。

疑いなく、再描画と再レイアウトは可能な限り避けるべきですが、どうすればよいでしょうか?

再レイアウトの例

実際、次のコードがひどいというわけではありません。ただし、配列arrに10個の要素があると仮定しましょう。

var myList = document.getElementById("myList");

for (var i = 0, len = arr.length; i < len; i++) {

    myList.innerHTML += "<li>" + arr[i].title + "</li>"; //重新布局 -- 增加到元素

}

上記のforループ内では、各反復ごとに1回の再レイアウトがトリガーされます。10回の反復は10回の再レイアウトになります。

次に、以下のコードを考えてみましょう:

var constructedHTML = "";

for (var i = 0, len = arr.length; i < len; i++) {
    constructedHTML += "<li>" + arr[i].title + "</li>"; //没有重新布局 - 增加到字符串
}

document.getElementById("myList").innerHTML = constructedHTML; //在这里重新布局

このシナリオでは、追加する要素は文字列内で構築されます。DOM が変更されないため、ループ内では再レイアウトは発生しません。配列が完全にループされ、構築された文字列がオブジェクトのinnerHTMLに適用されたときにのみ、関数内で唯一の再レイアウトが発生します。

回避できる再レイアウトや再描画は無数にあります。幸運にもそれらのコツを理解できたことを願います。この分野の読み物はたくさんありますが、そのほとんどは Nicole Sullivan のこのブログ記事は完璧な出発点です。ここでの経験に加えて、「web 3.0」や HTML5 時代のさまざまな技術用語に関わる場合、他にも重要な教訓が得られます。上記の分析は、jQuery コードを書くことに直接適用できます。〜を扱うcanvasときにもこれらの原則は重要です。また、フレームレートを30〜60の範囲に保つようにしてください。

一意のIDを生成するためにマイクロ秒を使わない

Web 開発の初期の頃から、一意の ID を生成する方法が広く使われていました。具体的には、1970年1月1日からのマイクロ秒数を静的な ID の末尾に追加するというものです。次のようになります:

var myID = "static" + new Date().getTime();

これはもともと非常に確実な方法でした。というのも、このようなコードが2回連続して実行されたとしても、実行の間には数ミリ秒の間隔があるからです。しかし、現在の新しいブラウザは新しい JavaScript エンジンを搭載し、クロック周波数は上がり続けています。今では、上記のコードが同じミリ秒数を生成する可能性は、間隔が生じる可能性よりも高くなっています。

これにより、従来の方法ではデバッグが難しいバグが発生します。DOMは実行中に作成されるため、ページのソースコードに対して従来のテストを行うだけでは、複数の重複IDによるエラーを特定できません。JavascriptとjQueryのエラー処理メカニズムは、最初に一致したものをIDとして扱い、他の重複IDを無視します。そのため、JSエラーすら発生しないのです!

それではダメで、唯一の本当の方法は行ごとにブレークポイントとログを設定することです。しかし、ブレークポイントの位置が間違っていると、ミリ秒のタイミングが衝突しなくなることもあります!

良い知らせとして、一意のIDを生成する代替方法はたくさんあります。学術的に言えば、コンピュータの乱数関数は実際には完全にランダムではなく、システム時間に由来しています。これは注目に値しますが、乱数が衝突する可能性は極めて低いです。

var myID = "static" + Math.round(Math.random() * 10000);

個人的には、手動でGUIDを生成する方法が好みです。技術的に言えば、GUIDはハードウェアに基づいて作成されますが、以下のJavascript関数はかなり優れています。これは私がStack Overflow の投稿からこっそり拝借した、かなり使い勝手のいい関数です。

function S4() {
   return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
}
function guid() {
   return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
}

var myID = "static" + guid();

ブラウザの種類を検出するのではなく、機能を検出する

ユーザーのブラウザは地理位置情報に対応していますか?ユーザーのブラウザはWeb Workersに対応していますか?HTML5 ビデオ?HTML5 オーディオ?かつて答えは次のようなものでした:

if ($.browser.msie) {
    // 哦,是IE啊,那肯定不支持
}

しかし、世界は急速に変化しています。最新版のIEはほぼモダンブラウザと言えますが、それでもフロントエンド開発に痛みをもたらしています。それ以前のバージョンのIEは、その前のバージョンと同様にひどいものでした。そのため、怠惰なJavascriptプログラマーは、次のような検出を行うことに慣れていました。if (ie)そして、マイクロソフト専用の壊れた構文を実行していました。現在、IE9はこれらの専用関数を廃止しており、かつてのif (ie)古い遺物は逆に悪さをするようになりました。

それでは、user-agent(信頼性が低く偽装も可能)を検出せずに、各機能を検出できるとしたらどう思いますか?

もしあなたの答えが「それはかなり信頼できる」なら、あなたは正しいです。

用 Modernizrさて、これは業界の超一流マスターであるPaul Irishが開発に参加したJavascriptライブラリです。このライブラリは、広範な応用、軽量さ、そして膨大なドキュメントという3つの利点を兼ね備えており、実装は考える必要がなく、まさに家庭でも旅行でも、はたまた殺人の口封じにも必需品です。これはModernizrオブジェクトを生成し、その中にはすべての検出テストの結果が含まれています。そのため、特定の機能のサポート有無を検出するのは、以下の例のように簡単です:

// 检测浏览器是否支持canvas的老办法
if (!!document.createElement('canvas').getContext) { ... }

// 用 Modernizr 检测
if (Modernizr.canvas) { ... }

読みやすいミリ秒数を使用する

ミリ秒の便利な表記方法として、読みやすい形式で書くことができます。初心者には素晴らしいですが、ほとんどの場合、実際にはただの目新しさ(ギミック)にすぎません。

// 这是3秒,30秒还是300秒啊?
var timeout = 30000;

// 增加了额外的计算开销,但是读和修改会更容易
var timeout = 30 * 1000;

jQueryコードについて

狂ったようにチェーンする

jQueryの最も優れた特徴の1つは、関数のチェーンです。あなたも少しは使ったことがあるでしょう。おそらく簡単な呼び出しを次々にチェーンしたことはあるかもしれません...しかし、狂ったようにDOMの中を上へ下へと飛び回りながら走査したことはありますか?それとも、時間をかけて.end()関数を覚えてください。開始セレクタからDOMの中を上へ下へと移動するときに、この関数が重要になります。

$(".quote")
    .hide()
    .find("a").text("Click here").bind("click",doStuff).end()
    .parent().removeClass().addClass("testimonial").draggable().end()
    .fadeIn("slow");

上記の例では、あるDOMオブジェクトに対する操作を完了するたびに、DOMを逆方向に走査して参照していた元のオブジェクトに戻る必要があります。そのようなときに.end()関数を使用します。そして、それに沿って元のDOM内の位置まで戻るわけです。

data-* 属性を使用する

長い間Javascript(ネイティブで、jQueryではない)コードを書いてきた人たちは、おそらくさまざまな属性に精通しているでしょう。属性を設定したり、取得したり、あるいは濫用したりしてきました。relとtitle ...

HTML5やjQueryが何も助けにならなかったとは言わせません。新しい仕様では、HTML要素内でdata-プレフィックスを使ってデータを含む属性を示すことができます。jQueryは指定された文字列を正しいJavascriptデータ型に変換してくれるので、非常にうまく機能します。いくつかのデータ属性を持つDIV 。

<div id="test" data-is-bool="true" data-some-number="123"></div>

要素を作成してみましょう。

typeof $("#test").data("isBool"); // boolean

typeof $("#test").data("someNumber"); // number

特別な大文字・小文字の扱い

注意すべき重要な点として、これらのコードスニペットを正しく動作させるには、(HTML内の属性定義で)小文字を使用する必要があります。しかし、もし熟練したフロントエンド開発者なら、データ変数にはキャメルケースを使いたいと思うでしょう。Javascriptの多くの場面で見られるように、前にあるハイフンは次の文字がキャメルケースの大文字になることを意味します。ただし、以下の例のようにHTML属性定義でキャメルケースを使用することはできませんそのため、上記のJavascriptコードはundefined。

動作しません :(

<div id="test" data-isBool="true" data-someNumber="123"></div>

動作します :)

<div id="test" data-is-bool="true" data-some-number="123"></div>

'.stop()' は協調とリスニングを停止する

jQueryのアニメーション効果とマウスイベントを結びつけることは、ウェブベースの現代的なユーザーインタラクションの重要な部分ですが、この点において、最も有名なWebサイトでさえも下手な実装をしていることがあります。この記事は、アニメーションを実装する直接的な例を提供し、これらのアニメーションを組み合わせると、視覚的にどれほど不快な効果が生じるかを示しています。$.animate呼び出しに1つのパラメータを追加することで簡単に解決できます。

使用する際には$.animateパラメータにqueue: falseを追加することで、チェーンを回避できます。例えば$.fadeIn 或 $.slideDownのようなアニメーションのショートカットはqueue設定を受け付けないため、必ず$.stopメソッドを使って、これらのアニメーションを事前に停止しなければなりません。clearQueueとjumpToEndこれら2つのパラメータに関するドキュメントを確認しておくことをお勧めします。神にかけて、他にあなたを助ける方法はありませんから。

$("selector").stop(true,true).fadeOut();

$("selector").animate({
    property: value
}, {
    duration: 1000,
    queue: false
}

セレクタを最適化する

jQuery はとてもクールです。ほとんど何でもできますが、今のところコーヒーを入れてくれるわけではありません。2.0版のロードマップにこの機能があると聞いていますが。注意すべきことの1つは、そのsizzleJSセレクタエンジンの能力を乱用しないことです。この問題を避けるには2つの戦略があります:セレクタの結果をキャッシュするそして高効率なセレクタを使用する。

セレクタの結果をキャッシュする

何かを少し変更するたびに毎回コストの高いDOMクエリを実行するべきか、それとも要素のインデックスを保存しておくべきか?選択は明らかです。

// before
$(".quote a").bind("click", doStuff); // DOM查询

// now
$(".quote a").addClass("quoteLink"); // DOM查询!!

// later
$(".quote a").fadeIn("slow"); // 又一次DOM查询!!!

チェーンを無視して、こちらの方が良いです:

// before
var $quoteLinks = $(".quote a");  // 只需一次DOM查询
$quoteLinks.bind("click", doStuff);

// now
$quoteLinks.addClass("quoteLink");

// later
$quoteLinks.fadeIn("slow");

高効率なセレクタを使用する

さて、jQuery/sizzleJS はCSS3セレクタを簡単に使えますが、本当のコストは何でしょうか? このシナリオでは、ブラウザはdocument.querySelector()を使用する可能性がありますが、セレクタ文字列を分解して手動でDOMをクエリする可能性もあります。

// ID搜索是最快的查询方式,然后它获取孩子节点的列表,匹配其中class为'quotes'的元素
$("#quoteList").children(".quotes");

// 只在预先确定的bar元素下查找'foo'class
$(".foo",bar); 

'for' ループは常に 'each()' ループより速い

今後数年のブラウザ開発の分野で何が起ころうとも、ネイティブのforループは常にjQueryの$.each()ループより速いです。

jQueryが実際に何なのか(ネイティブJS関数をラップしたライブラリ)という高尚な問題を考えると、ネイティブのJavascriptコードが常に高速であることに気づき始めるでしょう。ライブラリを使うかネイティブを使うかは、実行速度とプログラミング速度のトレードオフです。for非常に重要な点として、1秒間に数百回呼び出される可能性のあるパフォーマンス重視の関数では、常に

  • ループを使用します。例:
  • マウスの移動
  • 時間間隔

CSS

ボックスモデルの理解が鍵です

ボックスモデルを理解することが鍵

「ボックスモデル」は、ブラウザがページをどのようにレンダリングするかを理解する上で、決定的かつ重要な要素です。その複雑さを完全に理解することで、作業が驚くほど簡素化されます。ボックスモデルは、HTML要素の物理的な寸法が計算される方法を説明します。ブロック要素が固定幅(たとえば100px)を持つ場合、そのpadding、border、marginはどのように決定されるべきでしょうか?

.foo {
    width: 150px;
    height: 150px;
    padding: 25px;
    border: 25px solid;
    margin: 20px;
}

多くのWebサイトが詳細に説明していますが、簡潔に言いましょう:標準準拠のブラウザでは、borderとpaddingは指定された幅の外側に配置されます。図で説明するのが最適です。例えば次のコード:

あなたが推測したであろう状況(Quirksモード)

paddingとborderは内側に計算され、結果として高さと幅はどちらも150pxのままです。

あなたが実際に見る状況(標準準拠モード)

しかし、実際に得られる幅と高さは250pxです。つまり、150px + (2 * 25) + (2 * 25) です。box-sizingこの結果が奇妙だと思うなら、あなたは一人ではありません(いや、あなたは人間ですが、同じように思う人が他にもいるということです)。 さて、ここで修正方法があります。それはというCSSプロパティを導入する必要があります。このプロパティはIE8 以降caniuse.com 。

/* 旧方法 (178 + 20 + 2 = 200) */
.foo {
    width: 178px;
    padding: 10px;
    border: 1px;
}

/* 更好的方法 */
.foo {
    width: 200px;
    padding: 10px;
    border: 1px;
        -webkit-box-sizing: border-box;
        -moz-box-sizing: border-box;
        box-sizing: border-box;
}

に適用されます。これにより、要素の寸法を計算する正確な方法を選択でき、あなたを窮地から救ってくれます。サポートされるパラメータはブラウザによって異なり、ベンダープレフィックスが必要です。詳細はpadding/margin/bordersとはいえ、最初の方法のように、幅を暗算して各ピクセル数を足したり引いたりすることも常に可能ですが、異なる幅の単位(パーセンテージやEMなど)が関わると、誰も正確に把握できなくなります。現時点では、要素を親要素でラップして、幅と

floatをいつ使い、positionをいつ使うかを知る

floatを使うべき時とpositionを使うべき時を理解する

floatを使ってDOMから要素を取り出し、それらを左または右に強制的に寄せるのは、かなり信頼できる方法です。それらはフロントエンド開発におけるテーブルレイアウド後の時代の万能薬となっています。これはおそらく、以前のブラウザがdisplay: inlineとinline-blockのサポートが不十分だったこと、またpositionのサポートにおいて発生したz-indexバグのせいです。しかし今となっては本当に言い訳はできません。inline-block はすでに十分サポートされており、簡単な修正を加えるだけで IE7 でも適用できます。

ありがたいことに、CSSで要素を絶対配置することを妨げていた以前の議論は消え去りました。理論上、positionプロパティを使えば、ページ上でX座標とY座標で要素を配置できます。この方法はシンプルで直接的であり、Flash開発者にはおなじみのはずです。

Position を理解する

CSSで要素を配置する際、配置位置は常に、positionプロパティを持つ最も近い親要素を基準にするという事実を理解することが非常に重要です。CSSを使い始めたばかりの人々は、次のようなよくある誤解をします。position: absolute;それはページのルート要素を基準に配置されるというものです。この誤解は、ある要素にpositionスタイルを持つ親要素がまったくない場合に由来すると思います。その場合、彼らの結論は正しいのです。このようにDOMツリーを上へ辿ってもpositionスタイルを持つ要素が見つからない場合、ページのルート要素を基準に配置されます。

では、もしposition: absolute;が要素を通常のフローから引き抜くのであれば、どのようにして要素をその親要素に対して配置すればよいでしょうか?方法はとても直接的です。親要素は定義する必要があります。position: relative;スタイルを定義すると、すべての子要素は上、右、下、左の順に配置されます。この知識を利用して、次の非常に直感的なレイアウトをどのように実現しますか?

使用するにはfloat、これらの要素を親要素で包み、次に.onefloatを左に設定し、それから.twoと.threeのfloatとmarginを調整します。最終的には次のようなものになるはずです:

.parent {
    /* ghetto clearfix */
    width: 310px;
    overflow: auto;
}
.one {
    width: 200px;
    height: 210px;
    float: left;
}
.two {
    width: 100px;
    height: 100px;
    float: right;
    margin-bottom: 10px;
}
.three {
    width: 100px;
    height: 100px;
    float: right;
}

前述のとおり、positionを使用すると、X座標とY座標に従って、非常に明確な方法で要素を画面上に表示できます。上記のfloatを使う方法ではページ上の長いテキストが分離されますが、以下の方法では、ページ上に何があってもすべての要素が通常の位置にあることを保証できます。

.parent {
    position: relative;
    width: 310px;
    height: 210px;
}
.one, .two, .three {
    position: absolute;
}
.one {
    top: 0;
    left: 0;
    width: 200px;
    height: 210px;
}
.two {
    top: 0;
    right: 0;
    width: 100px;
    height: 100px;
}
.three {
    bottom: 0;
    right: 0;
    width: 100px;
    height: 100px;
}

前述のとおり、いくつかのz-index問題を考慮する必要があります。上記の例はやや大げさに見えるかもしれませんが、いったんpositionについて考え始めると、可能性に満ちた新しい世界が開けます。

空白

単一行と複数行のCSSパラメータの形式を行き来すると、CSS内の空白も変わってきます。これについてはあまり詳しく説明するつもりはありません。

適切な空白

/* 不好 */
.selector {display:none;background:#FF0000;color:#000000;}

/* 好 -- 单行 */
.selector { display: none; background: #FF0000; color: #000000; }

/* 好 -- 多行 */
.selector {
    display: none;
    background: #FF0000;
    color: #000000;
}

中括弧は改行しない

.selector {
    display: none;
    background: #FF0000;
    color: #000000;
}

子要素のインデント

これを使うかどうかは人それぞれですが、私は個人的に、単一行で定義されたCSSドキュメントでのみこの形式を使用します。

.selector { display: none; background: #FF0000; color: #000000; }
    .selector a { text-decoration: none; }
    .selector span { font-weight: bold; }

ブラウザベンダープレフィックス付きプロパティをまとめてインデントする

.selector {
    background: #FFF; border: 1px solid #000; color: #EAEAEA;
        -webkit-border-radius: 3px;
        -moz-border-radius: 3px;
        border-radius: 3px;
}

CSS のショートハンド書式

プロパティのグループ化

プロパティをグループ化することは、CSSファイルサイズを大幅に削減する最も効果的な方法です。ここで重要なのは、プロパティがどのように並べられるか(時計回り -- 上、右、下、左)、そしてそれらをさらに短縮する方法(上下、左右)を理解することです。

/* 逐个定义,太长了 */
padding-top: 1px;
padding-right: 2px;
padding-bottom: 1px;
padding-left: 2px;

/* 上,右,下,左,好很多 */
padding: 1px 2px 1px 2px;

/* 上和下,左和右,最优 */
padding: 1px 2px;

0px からヒーローへ

値が0のプロパティに単位の種類を割り当てるのは無駄です。ある要素が左から0pxであっても0 elephantsまったく重要ではありません。左にぴったりくっついていることがわかっていれば十分です。

/* 不好 */
padding: 0px 10px;

/* 好 */
padding: 0 10px;

コメントブロック

スタイルシート内で複数のスタイル領域を管理するというタスクには、CSSの大きなブロックにコメントを付けるのが良い方法です。明らかにこれは単一行CSSスタイルと組み合わせると効果的ですが、複数行CSSスタイルでもまったく役に立たないわけではありません。コメント内で強調にダッシュ、等号、下線のどれを使うかは人それぞれですが、以下は私が好む方法です:

/* === HORIZONTAL NAV === */
#horizNav { width: 100%; display: block; }
#horizNav li { display: block; float: left; position: relative; }
#horizNav li a { display: block; height: 30px; text-decoration: none; }
#horizNav li ul { display: none; position: absolute; top: 30; left: 0; }

/* === HOME PAGE - CAROUSEL === */
#carousel { width: 960px; height: 150px; position: relative; }
#carousel img { display: none; }
#carousel .buttons { position: absolute; right: 10px; bottom: 10px; }

フロートの解除

フロートを<div>解除することは、過去には追加のDOM要素を意味していました。これは追加のクリア用要素を増やすことを伴うからです。より良い方法は、親要素に明示的な幅を設定し('auto'はすべてのブラウザやシナリオで有効とは限りません)、overflowプロパティを'auto'または'hidden'に設定することです。'hidden'の方が明らかに互換性が高いですが、IE互換の一部のバージョンでは'auto'の方が効果的な場合があります。

HTML:

<div class="parentElement">
    <div class="childElement">
        I'm floated left!
    </div>
    I'm normal text that wraps around the float
</div>

CSS:

.parentElement {
    width: 100%;
    overflow: hidden;
}
.childElement {
    float: left;
}

このプロジェクトの貢献者が、最新のclearfixに注意するよう私に知らせてくれました。micro clear-fixは非常に安定しており、クロスブラウザ互換性が高いため、最新のHTML5 boilerplateに含まれるに値すると考えられています。私は強くあなたに確認することをお勧めします。私はブラウザ固有のCSSや:afterのような擬似要素の熱烈なファンではありませんが、このmicro clearfixは確かにより堅牢です。また、トップレベルのマージンの相殺問題も回避できます。

垂直方向と水平方向の中央揃え

要素を水平方向に中央揃えすることは、実際には高度な技術ではありません。皆さんのほとんどは以下のコードスニペットに精通しているはずです:

.class {
    width: 960px;
    margin: 0 auto;
}

フロントエンド開発者たちはこのコードを長い間使用してきましたが、なぜこの方法が垂直方向のセンタリングに機能しないのか理解していませんでした。私の理解では、親要素には通常height: auto;スタイルがあり、また垂直方向に中央揃えする要素に必要な100%の高さもありません。そしてposition: absolute;を適用すると、要素を効果的にpositionモードへ移行させ、autoに設定されたmarginが自動的に位置を調整してセンタリング効果をもたらします。

.exactMiddle {
    width: 100px;
    height: 100px;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: auto;
}

この方法の欠点には、IE6 と IE7 でのサポート不足、およびブラウザが中央揃えされたオブジェクトより小さく縮小されたときにスクロールバーが表示されないことが含まれます。のWebページにはさらに多くの方法がリストされています(現在これは4番目の方法です)。ただし、現時点ではこれが最適な方法です。

要素内でテキストを垂直方向に中央揃えするのも非常に簡単です。テキストが単一行の場合、たとえば水平ナビゲーション要素では、line-heightをその要素の物理的な高さに設定できます。

#horizNav li {
    height: 32px;
    line-height: 32px;
}

ブラウザの種類を検出するのではなく、機能を検出する

前述のJavaScript機能検出に関する議論では、ブラウザがいずれかのバージョンのIEであることを検出してから特定のプロパティを適用する手法は、ますます問題になっています。鉄人 Paul Irish は、IEバージョン検出という手法を用いてこれらの問題を解決する流れを先導しました。しかし、Modernizrがそれ以来私たちを救ってきました。Modernizr は root<html>要素にいくつかのclassを追加し、特定の機能がサポートされているかどうかを記述します。そして、先進的なスタイルはこれらのclassから簡単にカスケードさせたり削除したりできます。

.my_elem {
   -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.25);
   -moz-box-shadow: 0 1px 2px rgba(0,0,0,0.25);
   box-shadow: 0 1px 2px rgba(0,0,0,0.25);
}

/* 如果 box shadow 不支持, 就应用 borders 属性 */
.no-boxshadow .my_elem {
   border: 1px solid #666;
   border-bottom-width: 2px;
}

!important を乱用しない

!important タグに依存することは!important危険な現象です。それを使わざるを得ない状況はごくわずかで、特殊なケースです。そのような状況とは、おおむね別のスタイルシートを上書きする必要があるが、それを編集できないか、編集する権限がない場合です。もう1つのシナリオは、Javascriptがオンラインで生成するスタイルがより高い優先順位を持つことを防ぐために、要素のスタイルをハードコードする場合です。しかし実際には、!importantは、あるスタイルを他のスタイルより優先させるための怠惰なショートカットとして使われることがよくあり、そうすると将来多くの問題を引き起こすことになります。

に対して!importantタグの使用の大部分は、CSSセレクタの優先順位と、要素をより正確にターゲットする方法をよりよく理解すれば回避できます。セレクタが具体的であればあるほど、適切なスタイルとして受け入れられる可能性が高くなります。vanseodesign の以下の例は、具体性が機能する状況を示しています。

p { font-size: 12px; }
p.bio { font-size: 14px; }

スタイルの優先順位に関して、彼らの記事は継承性の説明において、私が書けるどんな記事よりも優れているので、ぜひいいねを押してください。

アグレッシブな後方互換性

注意すべき点として、これは私個人の見解であり、特定の状況にのみ当てはまります。古いバージョンのブラウザに依存する大規模な商用プロジェクトやエンタープライズ向けソリューションでは、積極的な下方互換の立場は受け入れられにくいでしょう。

積極的な下方互換とは、特定の(古い)ブラウザが特定の効果をレンダリングできない場合、それを直接無視するという意味です。CSS3 ボタンは良い例です。たとえばborder-radius, box-shadow, text-shadowとgradientsのような効果は、先進的なブラウザでは表示されます。少し古いバージョンのブラウザでは、.PNG画像を無害な代替手段として使用できます。そしてすべての解決策の中で最もエレガントなのは、IE6向けにPNG-Fixを提供するか、filterパラメータを使用して gradients や shadows などのプロパティを置き換えることです。ただし、この場合、積極的な下方互換のアプローチでは、古いブラウザを無視し、その中で平面的でまずまずの見た目のオブジェクトを表示することになります。

簡単に言うと、積極的な下方互換とは要するにこうです:ブラウザがグラデーションやボックスシャドウをレンダリングできなくても、それは運が悪いということです。

すべての状況に理想的というわけではありませんが、この方法はプロジェクトを期限内に納品し、コア製品が使用可能であることを保証できます。ブラウザのハックに依存する必要はありません。


CSS3 と HTML5

このトピックについては、もう十分に語ったと思います。Modernizrを使用して、特定の HTML5 および CSS3 機能が利用可能かどうかを検出してください。

@font-face の使用と滥用

カスタムフォントの埋め込みを検討する前に、[ライセンス]を確認し、EULAWeb埋め込みが許可されているかどうかをチェックすることが非常に重要です。フォントライブラリのベンダーは、デザイナーや開発者がフォントライブラリファイルをサーバーに直接置き、熟練したエンドユーザーにコピーされることを当然望みません。一部のベンダーは、特定のファイルタイプの埋め込みも禁止しています。たとえば.TTFと.OTF。

慎重に検討した結果、希望するフォントが埋め込み可能であると確信した場合は、Font Squirrelの@font-face ジェネレーターを参照してください。それは Fontspring の防弾 @font-face 構造を利用し、必要なすべてのファイル形式を自動的に生成できます。

後方互換性

ありがたいことに、ブラウザはサポートしていないHTML5およびCSS3の機能に対して、優雅な処理を実現しています。タグに追加された<input />タグの新しいタイプ(例: "email"、"search" など)は、ブラウザがネイティブでサポートしていない場合、通常は通常のテキスト入力にフォールバックされます。<input type="text" />同様に、サポートされていないCSS3機能は表示されず、高さと幅のメディアクエリによって制御されるレスポンシブレイアウトも適用されません。

精巧なCSS3エフェクトは、モダンブラウザを使用しているユーザーへのボーナスとして適用されるべきです。

以下の「リソース」セクションには、HTML5およびCSS3機能を多くの古いブラウザで正常に動作させるのに役立つライブラリが含まれています。


リソース

以下のリソースは、コードの標準化とモダンWebページのインタラクションにとって重要です。それらは、以前はサポート能力がなかった多くのブラウザでもCSS3およびHTML5機能を使用できるようにします。

  • jQuery JavaScriptヘルパーライブラリ
  • jQuery UI ユーザーインタラクション/UIのために、jQueryがJavaScriptに対して行うのと同じことを行います。
  • Modernizr 機能を検出しましょう。ブラウザを検出しないでください!
  • RespondJS 古いブラウザにレスポンシブレイアウトをもたらします。
  • @font-face Generator 包括的なフォントの埋め込み
  • RaphaelJS シンプルで使いやすいクロスブラウザベクターグラフィック
  • HTML5 Boilerplate どのプロジェクトにとっても良い出発点です。ただし、その「ライト」版でさえも少し肥大化しています。
  • Twitter Bootstrap シンプルなWebアプリケーションのプロトタイプとスタイルを迅速に生成できます。

この記事はTait Brownによって書かれました (@taitems)、この中国語版はcoderLMN翻訳されました。