选择器的优先级关系到元素应用哪个样式。在css2.1的规范(http://www.w3.org/tr/2009/cr-css2-20090908/cascade.html#specificity)中是这样描述的:
将四个数字按 a-b-c-d 这样连接起来(位于大数进制的数字系统中),构成选择器的优先级。
在最新的Selector Level 3规范中:
unsigned CSSSelector::specificity() <span style="color: #0000ff;">const</span><span style="color: #000000;">
{
</span><span style="color: #008000;">//</span><span style="color: #008000;"> make sure the result doesn't overflow</span>
<span style="color: #0000ff;">static</span> <span style="color: #0000ff;">const</span> unsigned maxValueMask = <span style="color: #800080;">0xffffff</span><span style="color: #000000;">; // 整个选择器的最大值,十进制表示:idMask + classMask + elementMak = <span>16777215</span>
</span><span style="color: #0000ff;">static</span> <span style="color: #0000ff;">const</span> unsigned idMask = <span style="color: #800080;">0xff0000</span><span style="color: #000000;">; // ID选择器的最大值,十进制表示:(16*16+16)*16^4=<span>16711680</span>
</span><span style="color: #0000ff;">static</span> <span style="color: #0000ff;">const</span> unsigned classMask = <span style="color: #800080;">0xff00</span><span style="color: #000000;">; // class(伪类、类)选择器的最大值,十进制表示:(16*16+16)*16^2=65280
</span><span style="color: #0000ff;">static</span> <span style="color: #0000ff;">const</span> unsigned elementMask = <span style="color: #800080;">0xff</span><span style="color: #000000;">; // 元素选择器的最大值,十进制表示:16*16+16=255
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (isForPage())
</span><span style="color: #0000ff;">return</span> specificityForPage() &<span style="color: #000000;"> maxValueMask;
unsigned total </span>= <span style="color: #800080;">0</span><span style="color: #000000;">;
unsigned temp </span>= <span style="color: #800080;">0</span><span style="color: #000000;">;
</span><span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">const</span> CSSSelector* selector = <span style="color: #0000ff;">this</span>; selector; selector = selector-><span style="color: #000000;">tagHistory()) {
temp </span>= total + selector-><span style="color: #000000;">specificityForOneSelector();
</span><span style="color: #008000;">//</span><span style="color: #008000;"> Clamp each component to its max in the case of overflow.</span>
<span style="color: #0000ff;">if</span> ((temp & idMask) < (total &<span style="color: #000000;"> idMask)) // 判断是否为ID选择器
total </span>|=<span style="color: #000000;"> idMask; // 保证ID选择器的同类叠加不会超过ID选择器的总最大值,下同
</span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> ((temp & classMask) < (total &<span style="color: #000000;"> classMask))
total </span>|=<span style="color: #000000;"> classMask;
</span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> ((temp & elementMask) < (total &<span style="color: #000000;"> elementMask))
total </span>|=<span style="color: #000000;"> elementMask;
</span><span style="color: #0000ff;">else</span><span style="color: #000000;">
total </span>=<span style="color: #000000;"> temp;
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> total;
}
inline unsigned CSSSelector::specificityForOneSelector() </span><span style="color: #0000ff;">const</span><span style="color: #000000;">
{
</span><span style="color: #008000;">//</span><span style="color: #008000;"> FIXME: Pseudo-elements and pseudo-classes do not have the same specificity. This function
</span><span style="color: #008000;">//</span><span style="color: #008000;"> isn't quite correct.</span>
<span style="color: #0000ff;">switch</span><span style="color: #000000;"> (m_match) {
</span><span style="color: #0000ff;">case</span><span style="color: #000000;"> Id:
</span><span style="color: #0000ff;">return</span> <span style="color: #800080;">0x10000</span><span style="color: #000000;">; // ID选择器权重
</span><span style="color: #0000ff;">case</span><span style="color: #000000;"> PseudoClass:
</span><span style="color: #008000;">//</span><span style="color: #008000;"> FIXME: PsuedoAny should base the specificity on the sub-selectors.
</span><span style="color: #008000;">//</span><span style="color: #008000;"> See </span><span style="color: #008000; text-decoration: underline;">http://lists.w3.org/Archives/Public/www-style/2010Sep/0530.html</span>
<span style="color: #0000ff;">if</span> (pseudoClassType() == PseudoClassNot &&<span style="color: #000000;"> selectorList())
</span><span style="color: #0000ff;">return</span> selectorList()->first()-><span style="color: #000000;">specificityForOneSelector();
FALLTHROUGH;
</span><span style="color: #0000ff;">case</span><span style="color: #000000;"> Exact:
</span><span style="color: #0000ff;">case</span><span style="color: #000000;"> Class:
</span><span style="color: #0000ff;">case</span><span style="color: #000000;"> Set:
</span><span style="color: #0000ff;">case</span><span style="color: #000000;"> List:
</span><span style="color: #0000ff;">case</span><span style="color: #000000;"> Hyphen:
</span><span style="color: #0000ff;">case</span><span style="color: #000000;"> PseudoElement:
</span><span style="color: #0000ff;">case</span><span style="color: #000000;"> Contain:
</span><span style="color: #0000ff;">case</span><span style="color: #000000;"> Begin:
</span><span style="color: #0000ff;">case</span><span style="color: #000000;"> End:
</span><span style="color: #0000ff;">return</span> <span style="color: #800080;">0x100</span><span style="color: #000000;">; // class选择器权重
</span><span style="color: #0000ff;">case</span><span style="color: #000000;"> Tag:
</span><span style="color: #0000ff;">return</span> (tagQName().localName() != starAtom) ? <span style="color: #800080;">1</span> : <span style="color: #800080;">0</span><span style="color: #000000;">; // 元素选择器权重
</span><span style="color: #0000ff;">case</span><span style="color: #000000;"> Unknown:
</span><span style="color: #0000ff;">return</span> <span style="color: #800080;">0</span><span style="color: #000000;">;
}
ASSERT_NOT_REACHED();
</span><span style="color: #0000ff;">return</span> <span style="color: #800080;">0</span><span style="color: #000000;">;
}</span>时间戳:2012-10-04 19:04:44 (20个月前)作者:commit-queue@webkit.org消息: 选择器特殊性类别溢出到高类别https://bugs.webkit.org/show_bug.cgi?id=98295 Patch by Tab Atkins on 2012-10-04Reviewed by Eric Seidel. 这一次添加的补丁是为了对于CSS选择器的特殊性添加溢出策略。 以前我们并不会检测每个类别的特殊性溢出问题。原始的策略是:把每个类别存储为一个字节(2^8=256),然后整体存在一个无符号整型数中。这样的话就会导致256个同一类别的单选择器等于1个高类别的选择器。但是这违反了选择器的特殊性规则,导致样式规则排序问题。 Tests: /fast/selectors/specificity-overflow.html css/CSSSelector.cpp: (WebCore::CSSSelector::specificity):
int32_t nsCSSSelector::CalcWeightWithoutNegations() <span style="color: #0000ff;">const</span><span style="color: #000000;">
{
int32_t weight </span>= <span style="color: #800080;">0</span><span style="color: #000000;">;
#ifdef MOZ_XUL
MOZ_ASSERT(</span>!(IsPseudoElement() &&<span style="color: #000000;">
PseudoType() </span>!= nsCSSPseudoElements::ePseudo_XULTree &&<span style="color: #000000;">
mClassList),
</span><span style="color: #800000;">"</span><span style="color: #800000;">If non-XUL-tree pseudo-elements can have class selectors </span><span style="color: #800000;">"</span>
<span style="color: #800000;">"</span><span style="color: #800000;">after them, specificity calculation must be updated</span><span style="color: #800000;">"</span><span style="color: #000000;">);
</span><span style="color: #0000ff;">#else</span><span style="color: #000000;">
MOZ_ASSERT(</span>!(IsPseudoElement() &&<span style="color: #000000;"> mClassList),
</span><span style="color: #800000;">"</span><span style="color: #800000;">If pseudo-elements can have class selectors </span><span style="color: #800000;">"</span>
<span style="color: #800000;">"</span><span style="color: #800000;">after them, specificity calculation must be updated</span><span style="color: #800000;">"</span><span style="color: #000000;">);
</span><span style="color: #0000ff;">#endif</span><span style="color: #000000;">
MOZ_ASSERT(</span>!(IsPseudoElement() && (mIDList ||<span style="color: #000000;"> mAttrList)),
</span><span style="color: #800000;">"</span><span style="color: #800000;">If pseudo-elements can have id or attribute selectors </span><span style="color: #800000;">"</span>
<span style="color: #800000;">"</span><span style="color: #800000;">after them, specificity calculation must be updated</span><span style="color: #800000;">"</span><span style="color: #000000;">);
</span><span style="color: #0000ff;">if</span> (nullptr !=<span style="color: #000000;"> mCasedTag) {
weight </span>+= <span style="color: #800080;">0x000001</span><span style="color: #000000;">;
}
nsAtomList</span>* list =<span style="color: #000000;"> mIDList;
</span><span style="color: #0000ff;">while</span> (nullptr !=<span style="color: #000000;"> list) {
weight </span>+= <span style="color: #800080;">0x010000</span><span style="color: #000000;">;
list </span>= list-><span style="color: #000000;">mNext;
}
list </span>=<span style="color: #000000;"> mClassList;
#ifdef MOZ_XUL
</span><span style="color: #008000;">//</span><span style="color: #008000;"> XUL tree pseudo-elements abuse mClassList to store some private
</span><span style="color: #008000;">//</span><span style="color: #008000;"> data; ignore that.</span>
<span style="color: #0000ff;">if</span> (PseudoType() ==<span style="color: #000000;"> nsCSSPseudoElements::ePseudo_XULTree) {
list </span>=<span style="color: #000000;"> nullptr;
}
</span><span style="color: #0000ff;">#endif</span>
<span style="color: #0000ff;">while</span> (nullptr !=<span style="color: #000000;"> list) {
weight </span>+= <span style="color: #800080;">0x000100</span><span style="color: #000000;">;
list </span>= list-><span style="color: #000000;">mNext;
}
</span><span style="color: #008000;">//</span><span style="color: #008000;"> FIXME (bug 561154): This is incorrect for :-moz-any(), which isn't
</span><span style="color: #008000;">//</span><span style="color: #008000;"> really a pseudo-class. In order to handle :-moz-any() correctly,
</span><span style="color: #008000;">//</span><span style="color: #008000;"> we need to compute specificity after we match, based on which
</span><span style="color: #008000;">//</span><span style="color: #008000;"> option we matched with (and thus also need to try the
</span><span style="color: #008000;">//</span><span style="color: #008000;"> highest-specificity options first).</span>
nsPseudoClassList *plist =<span style="color: #000000;"> mPseudoClassList;
</span><span style="color: #0000ff;">while</span> (nullptr !=<span style="color: #000000;"> plist) {
weight </span>+= <span style="color: #800080;">0x000100</span><span style="color: #000000;">;
plist </span>= plist-><span style="color: #000000;">mNext;
}
nsAttrSelector</span>* attr =<span style="color: #000000;"> mAttrList;
</span><span style="color: #0000ff;">while</span> (nullptr !=<span style="color: #000000;"> attr) {
weight </span>+= <span style="color: #800080;">0x000100</span><span style="color: #000000;">;
attr </span>= attr-><span style="color: #000000;">mNext;
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> weight;
}
int32_t nsCSSSelector::CalcWeight() </span><span style="color: #0000ff;">const</span><span style="color: #000000;">
{
</span><span style="color: #008000;">//</span><span style="color: #008000;"> Loop over this selector and all its negations.</span>
int32_t weight = <span style="color: #800080;">0</span><span style="color: #000000;">;
</span><span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">const</span> nsCSSSelector *n = <span style="color: #0000ff;">this</span>; n; n = n-><span style="color: #000000;">mNegations) {
weight </span>+= n-><span style="color: #000000;">CalcWeightWithoutNegations();
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> weight;
}</span>在所有浏览器中文字都会应用p {font-size:24px;}。如果把这句去掉的话,就会应用*{font-size:40px;},*包括p。(继承的样式没有优先级)
1、优先级计算时跨级相加应注意溢出问题;
2、优先级计算不包括inline style和!important;
3、优先级计算只有同一类别才具有可比性(一般也不会有人定义超出255个的同一选择器)。
I am currently using the book CSS Mastery: Advanced Web Standards Solutions.
Chapter 1, page 16 says:
To calculate how specific a rule is, each type of selector is assigned a numeric value. The specificity of a rule is then calculated by adding up the value of each of its selectors. Unfortunately, specificity is not calculated in base 10 but a high, unspecified, base number. This is to ensure that a highly specific selector, such as an ID selector, is never overridden by lots of less specific selectors, such as type selectors.
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号