CSSセレクタ優先度の計算を深く理解する
18006 ワード
選択の優先度は、要素がどのスタイルを適用するかに関係します.CSS 2.1の仕様(http://www.w3.org/TR/2009/CR-CSS2-20090908/cascade.html#specificity)では、宣言が「スタイル」属性であって、セレクタ付きの規則ではなく、0(=a)(HTML要素のスタイル属性もスタイルルールであり、これらのスタイル規則はセレクタがないので、a=1,b=0,c=0,d=0) と記載されている.は、セレクタにおけるID属性の個数(=b) を計算する.は、セレクタにおける他の属性(クラス、属性セレクタ)と疑似種類の個数(=c) を計算する.は、セレクタにおける要素名と疑似要素の個数(=d)を計算する .
4つの数字をa-b-c-dのように接続し(大数進のデジタルシステムにおいて)、セレクタの優先度を構成する.
最新のSelector Level 3仕様では、は、セレクタにおけるID属性の個数(=a) を計算する.は、セレクタにおける他の属性(クラス、属性セレクタ)と疑似種類の個数(=b) を計算する.は、セレクタにおける要素名と疑似要素の個数(=c) を計算する.汎用セレクタ* を無視する.
3つの数字をa-b-cのように接続し(大数進法のデジタルシステムにおいて)、セレクタの優先度を構成する.style属性計算はcss 2.1仕様を参照してください.
問題:
1、選択器の全体優先度はどう計算しますか?ネットで言っているa*1000+b*100+c*10+dのようですか?
いいえ、違います.この答えは明らかに望文生義である.四級(a、b、c、d)の間は簡単な加算関係ではありません.同じレベル(例えば、a対a)の方が比較可能な関係があります.
分析:
以下はwebkitのwebCoreの優先度計算に関するコードです.
)
上のコードから分かるように、webkitでは、aレベルセレクタ(「style」属性のスタイルルール)に対して優先演算にはまったく関与していません.bレベル(IDセレクタ)、cレベル(クラスセレクタ)、dレベル(要素セレクタ)については、各ステージごとに最大値(最大数255)があり、それを超えると最大値(最大数)が適用されます.bレベルの最大値は0 xff0000(16711680)であり、重み付けは0 x 1000(65536)であり、数が256を超える時も最大値を使用する.c級、d級は似ています.したがって、下位レベルが一定の数を超えて、高いレベルが上書きされることはありません.一つのセレクタグループ(em:铉a.d div)において、すべてのセレクタの合計は16777215を超えないことを保証している(各クラスのセレクタは最大値を超えないことを保証している).デモ:http://trac.webkit.org/browser/trunk/Source/WebCore/css/CSSSelector.cpp.そうですimpotant、webkitは歩くもう一つの経路(持っています!importentのスタイル規則はないより大きいです!importentのスタイル規則は、同時に!import属性を持っている場合のみ選択の全体優先度を比較します.)全体的には、webkitの中で、!impotant>inline style>ID>class.
webkitは
http://jsbin.com/duker/2今回の改訂では、優先度オーバーフローの処理(chromeリリースバージョンが速いので、今年はblinkに変更されました.chromeは特殊性(優先度)計算の基準を守っていると考えられます.
タイムスタンプ:2012-10-04 19:04:44(
http://trac.webkit.org/changeset/130444/trunk/Source/WebCore/css/CSSSelector.cpp前)作者:[email protected]メッセージ:
セレクタの特殊カテゴリが高カテゴリ20ヶ月にオーバーフローしました.
Patch by Tab Atkins<https://bugs.webkit.org/show_bug.cgi?id=98295>on 201-10-04 Review by Eric Seiddel.
今回追加したパッチはCSSセレクタの特殊性にオーバーフローポリシーを追加するためです.
以前は各カテゴリの特殊性オーバーフロー問題を検出しませんでした.元のポリシーは、各カテゴリを1バイト(2^8=256)に格納し、全体として符号なし整数が存在する.このようにすると256個の同じカテゴリの単一セレクタが1つの高カテゴリのセレクタに等しいという結果になります.しかし、これはセレクタの特別な規則に違反して、スタイル規則の並べ替え問題を引き起こします.
Tests:/fast/selectors/specifinity-overflow. css/CSSSelector.cpp: (WebCore:CSSSelector::specifinity):
mozilaで優先度計算に関するコード(アドレスは
[email protected](472行-537行):
IEはコードを読めませんので、IEシリーズに対してはデモテストの方法でしか確認できません.すべてのIEシリーズ(q、s)において、表現はすべてmozilaと一致している.最新のIE 11を含む.
注:CSSセレクタにはもう一つの継承性があります.
<>JS Bin
4つの数字をa-b-c-dのように接続し(大数進のデジタルシステムにおいて)、セレクタの優先度を構成する.
最新のSelector Level 3仕様では、
3つの数字をa-b-cのように接続し(大数進法のデジタルシステムにおいて)、セレクタの優先度を構成する.style属性計算はcss 2.1仕様を参照してください.
問題:
1、選択器の全体優先度はどう計算しますか?ネットで言っているa*1000+b*100+c*10+dのようですか?
いいえ、違います.この答えは明らかに望文生義である.四級(a、b、c、d)の間は簡単な加算関係ではありません.同じレベル(例えば、a対a)の方が比較可能な関係があります.
分析:
以下はwebkitのwebCoreの優先度計算に関するコードです.
)
unsigned CSSSelector::specificity() const
{
// make sure the result doesn't overflow
static const unsigned maxValueMask = 0xffffff; // , :idMask + classMask + elementMak = 16777215
static const unsigned idMask = 0xff0000; // ID , :(16*16+16)*16^4=16711680
static const unsigned classMask = 0xff00; // class( 、 ) , :(16*16+16)*16^2=65280
static const unsigned elementMask = 0xff; // , :16*16+16=255
if (isForPage())
return specificityForPage() & maxValueMask;
unsigned total = 0;
unsigned temp = 0;
for (const CSSSelector* selector = this; selector; selector = selector->tagHistory()) {
temp = total + selector->specificityForOneSelector();
// Clamp each component to its max in the case of overflow.
if ((temp & idMask) < (total & idMask)) // ID
total |= idMask; // ID ID ,
else if ((temp & classMask) < (total & classMask))
total |= classMask;
else if ((temp & elementMask) < (total & elementMask))
total |= elementMask;
else
total = temp;
}
return total;
}
inline unsigned CSSSelector::specificityForOneSelector() const
{
// FIXME: Pseudo-elements and pseudo-classes do not have the same specificity. This function
// isn't quite correct.
switch (m_match) {
case Id:
return 0x10000; // ID
case PseudoClass:
// FIXME: PsuedoAny should base the specificity on the sub-selectors.
// See http://lists.w3.org/Archives/Public/www-style/2010Sep/0530.html
if (pseudoClassType() == PseudoClassNot && selectorList())
return selectorList()->first()->specificityForOneSelector();
FALLTHROUGH;
case Exact:
case Class:
case Set:
case List:
case Hyphen:
case PseudoElement:
case Contain:
case Begin:
case End:
return 0x100; // class
case Tag:
return (tagQName().localName() != starAtom) ? 1 : 0; //
case Unknown:
return 0;
}
ASSERT_NOT_REACHED();
return 0;
}
上のコードから分かるように、webkitでは、aレベルセレクタ(「style」属性のスタイルルール)に対して優先演算にはまったく関与していません.bレベル(IDセレクタ)、cレベル(クラスセレクタ)、dレベル(要素セレクタ)については、各ステージごとに最大値(最大数255)があり、それを超えると最大値(最大数)が適用されます.bレベルの最大値は0 xff0000(16711680)であり、重み付けは0 x 1000(65536)であり、数が256を超える時も最大値を使用する.c級、d級は似ています.したがって、下位レベルが一定の数を超えて、高いレベルが上書きされることはありません.一つのセレクタグループ(em:铉a.d div)において、すべてのセレクタの合計は16777215を超えないことを保証している(各クラスのセレクタは最大値を超えないことを保証している).デモ:http://trac.webkit.org/browser/trunk/Source/WebCore/css/CSSSelector.cpp.そうですimpotant、webkitは歩くもう一つの経路(持っています!importentのスタイル規則はないより大きいです!importentのスタイル規則は、同時に!import属性を持っている場合のみ選択の全体優先度を比較します.)全体的には、webkitの中で、!impotant>inline style>ID>class.
webkitは
http://jsbin.com/duker/2今回の改訂では、優先度オーバーフローの処理(chromeリリースバージョンが速いので、今年はblinkに変更されました.chromeは特殊性(優先度)計算の基準を守っていると考えられます.
タイムスタンプ:2012-10-04 19:04:44(
http://trac.webkit.org/changeset/130444/trunk/Source/WebCore/css/CSSSelector.cpp前)作者:[email protected]メッセージ:
セレクタの特殊カテゴリが高カテゴリ20ヶ月にオーバーフローしました.
Patch by Tab Atkins<https://bugs.webkit.org/show_bug.cgi?id=98295>on 201-10-04 Review by Eric Seiddel.
今回追加したパッチはCSSセレクタの特殊性にオーバーフローポリシーを追加するためです.
以前は各カテゴリの特殊性オーバーフロー問題を検出しませんでした.元のポリシーは、各カテゴリを1バイト(2^8=256)に格納し、全体として符号なし整数が存在する.このようにすると256個の同じカテゴリの単一セレクタが1つの高カテゴリのセレクタに等しいという結果になります.しかし、これはセレクタの特別な規則に違反して、スタイル規則の並べ替え問題を引き起こします.
Tests:/fast/selectors/specifinity-overflow.
mozilaで優先度計算に関するコード(アドレスは
[email protected](472行-537行):
int32_t nsCSSSelector::CalcWeightWithoutNegations() const
{
int32_t weight = 0;
#ifdef MOZ_XUL
MOZ_ASSERT(!(IsPseudoElement() &&
PseudoType() != nsCSSPseudoElements::ePseudo_XULTree &&
mClassList),
"If non-XUL-tree pseudo-elements can have class selectors "
"after them, specificity calculation must be updated");
#else
MOZ_ASSERT(!(IsPseudoElement() && mClassList),
"If pseudo-elements can have class selectors "
"after them, specificity calculation must be updated");
#endif
MOZ_ASSERT(!(IsPseudoElement() && (mIDList || mAttrList)),
"If pseudo-elements can have id or attribute selectors "
"after them, specificity calculation must be updated");
if (nullptr != mCasedTag) {
weight += 0x000001;
}
nsAtomList* list = mIDList;
while (nullptr != list) {
weight += 0x010000;
list = list->mNext;
}
list = mClassList;
#ifdef MOZ_XUL
// XUL tree pseudo-elements abuse mClassList to store some private
// data; ignore that.
if (PseudoType() == nsCSSPseudoElements::ePseudo_XULTree) {
list = nullptr;
}
#endif
while (nullptr != list) {
weight += 0x000100;
list = list->mNext;
}
// FIXME (bug 561154): This is incorrect for :-moz-any(), which isn't
// really a pseudo-class. In order to handle :-moz-any() correctly,
// we need to compute specificity after we match, based on which
// option we matched with (and thus also need to try the
// highest-specificity options first).
nsPseudoClassList *plist = mPseudoClassList;
while (nullptr != plist) {
weight += 0x000100;
plist = plist->mNext;
}
nsAttrSelector* attr = mAttrList;
while (nullptr != attr) {
weight += 0x000100;
attr = attr->mNext;
}
return weight;
}
int32_t nsCSSSelector::CalcWeight() const
{
// Loop over this selector and all its negations.
int32_t weight = 0;
for (const nsCSSSelector *n = this; n; n = n->mNegations) {
weight += n->CalcWeightWithoutNegations();
}
return weight;
}
webkitと同じで、inline style要素は計算に含まれません.b級(ID)、c級、d級の最大値と最小値もwebkitと一致しています.異なるのは、mozilaでは同じカテゴリのセレクタを最大値で制御するのではなく、直接加算することです.このようにすると、同じレベルのセレクタの数が255よりも高いレベルになる、つまり、結果がオーバーフローするという問題が発生します.また、セレクタグループ全体の優先度計算は、webkitのようなビットと演算によって結果がオーバーフローしないことを保証するため、簡単に加算するだけで、mozilaにオーバーフローが発生する可能性があります.IEはコードを読めませんので、IEシリーズに対してはデモテストの方法でしか確認できません.すべてのIEシリーズ(q、s)において、表現はすべてmozilaと一致している.最新のIE 11を含む.
注:CSSセレクタにはもう一つの継承性があります.
<>