記一次糟心的前端筆試(2)

  接下來講說糟心的另外一題,第一題:css選擇器有哪些?它們的優先級如何計算?css

  怎麼說呢,這題目一看,考css選擇器還不簡單。立刻就要開始寫,可剛要下筆的時候才發現,本身居然不知道要怎麼去回答這個問題。平時本身寫代碼的時候根據本身的需求很天然就能夠寫出那些選擇器,然而本身不清楚的是:這些選擇器有沒有分類?若是沒有分類,要如何在這麼窄的空間裏寫下那麼多選擇器?想到一個寫一個?  如今就像是,每天吃着某些菜,真到要說出它們學名的時候,才發現本身對這些菜其實一點也不瞭解;就像是,遊戲角色中每天都使用的技能,本身對它的效果瞭如指掌,卻忽然想不起它的技能名是啥。 這算什麼。。。html

  我我的可能有一個很大的缺點,總喜歡對事情有一個宏觀的把握,對於那些沒法得出自認爲滿意的答案,一般我都會持有否認態度。這讓我想起曾經一個朋友問我一個問題,一個農民給一個地主打工七天,天天薪酬是一塊金條的1/7,而地主只有那麼一整塊金條。若是隻能切兩次,要怎麼切,才能保證地主天天能付給農民報酬。 我說不知道。他當時給個人答案是1,2,4分,而後跟農民換,就能實現天天給相應的薪酬給他。其實這也是我當時考慮的解法之一,可是我以爲既然是日結,沒法保證這個農民不會把第一天的工資花掉。並且這樣子支付,這七天這個農民都不能使用它每日的酬勞。 這不是我理想中的答案,因此我否認了它,而後說不知道。而這道筆試題之因此答得很差,可能也是受我這種思惟影響。 後來我想通了,這確實是個人一大缺點。我應當是去作一名提供解決建議的人,而不是去作一名只知道否認建議的人。給出建議比否認難太多了。一樣的,若是沒法當即給出一個更好的建議,就應當正視別人的想法。css3

  好了,聽我講了那麼多廢話,下面進入正題。如今總算有充足的時間來組織語言了,爲了肯定信息來源的可靠性,特地去看了官方文檔。如下信息參考自 https://www.w3.org/TR/css3-selectors/   。有興趣的人能夠去看看。ide

  上面確實仍是有分類的,並且還挺詳細。根據個人渣英語理解上面的內容,css選擇器大概分爲如下幾類:spa

1. 類型選擇器(type selectors)code

  話很少說,直接上代碼:orm

p /*文檔內的全部p元素*/

2. 通配選擇器(universal selectors)htm

* /*文檔內的全部元素*/

3. 屬性選擇器(attribute selectors)blog

[attr] /*全部帶有屬性attr的元素*/ [attr=val] /*全部屬性attr等於val的元素*/ [attr~=val] /*全部屬性attr中包含單詞 "val" 的元素。爲了更深刻理解或者避免本身理解有誤,這裏上官網原話:Represents an element with the att attribute whose value is a whitespace-separated list of words, one of which is exactly "val". If "val" contains whitespace, it will never represent anything (since the words are separated by spaces). Also if "val" is the empty string,it will never represent anything. 大概意思就是,會以空格對attr的值進行分割,而後與val進行對比匹配。若是val中含有空格或者爲空字符串,這個選擇器將匹配不到任何元素*/ [attr|=val] /*全部屬性attr等於val或者attr的值以val開頭(後面必須跟有"-")的元素 。這裏仍是上官網原話:Represents an element with the att attribute, its value either being exactly "val" or beginning with "val" immediately followed by "-" (U+002D).因此在w3School中對於這個選擇器的描述是有問題的,還請注意*/ [attr^=val] /*全部屬性attr中以val開頭的元素*/ [attr$=val] /*全部屬性attr中以val結尾的元素*/ [attr*=val] /*全部屬性attr中含有val的元素*/

4. 類選擇器(class selectors)遊戲

div.test /*全部類名爲test的div元素*/

5. ID選擇器(ID selectors)

div#test /*全部id名爲test的div元素*/

 6. 僞類選擇器(pseudo classes)

a:visited /*全部被用戶訪問過一次的a元素*/ a:link /*全部尚未被用戶訪問過的a元素*/ a:hover a:active a:focuse /**/ :target :lang() /*元素的lang屬性是用來標記該元素(及其子元素)所用語言的。注意假如只有html元素中有lang="en"屬性的話,用:lang(en)匹配到的將是html元素下的全部元素,由於其子元素也是用英文寫的。*/ :enabled :disabled :checked
div:nth-child() div:nth-last-child() img:nth-of-type() img:nth-last-of-type() div:first-child
/*the same as div:nth-child(1) represents an element that is the first child of some other element. 我以爲理解這一句話很重要,我一開始就對這幾個僞類有些誤解。這裏匹配的是 是父元素第一個子元素的全部div元素*/ :last-child /*全部是父元素最後一個子元素的元素*/ :first-of-type /*same as :nth-of-type(1)*/ :last-of-type /*same as :nth-last-of-type(1)*/ :only-child /*same as :first-child:last-child*/ :only-of-type /*same as :first-of-type:last-of-type*/

:empty /*全部沒有子元素的元素*/

7. 僞元素選擇器(pseudo elements)

p::first-line
p::first-letter
div::before
div::after

  事實上,根據原文的文檔結構,我以爲第7條是不在選擇器之列的,但我沒法肯定,因此仍是把它放進來了;我也不知道像 div>p 這樣的「子代選擇器」(child combinators)到底是單選擇器(simple selector)的組合語法,仍是它自己就是一種類型的選擇器,因此在最後面單獨給出一個小節來介紹。

*. 關係選擇器(combinators)

div p /*全部 祖先元素中有div元素的p元素。 由於css是從右往左解析的,因此這樣解釋比較符合個人邏輯*/ div>p /*全部父元素爲div元素的p元素*/ div+p /*全部前一個同輩元素爲div的p元素(不是最近,而是要挨着,隔着一個元素都不行)*/ h1~pre /*全部在同輩元素h1以後的pre元素*/

不知不覺已經這麼多,這樣子一分類果真清楚多了。如今想來,真的很遺憾錯過這家公司。雖然自認爲去筆試前仍是作了一些準備工做的,說到底本身水平仍是不夠,纔會這樣碰壁吧。繼續,下一個問題,這些選擇器的優先級是怎麼算的

  關於選擇器的優先級問題,本身確實研究不深,只是粗略知道一些簡單的,至於具體的細節還真沒有去了解過。正好趁此機會好好啃一啃。還有啊,網上對於選擇器優先級的計算方法真的是五花八門,貽害不淺。先不說別人,我本身就是深受其害的受害者之一,因此懂得以質疑的眼光看待事物是頗有必要的。固然我不能保證我這篇文章不害人,我儘可能,有什麼錯誤的地方,歡迎指正。如下信息參考自 https://www.w3.org/TR/CSS22/cascade.html#cascade ,應該是目前最新定稿的css規範(2017.9.18),有興趣的能夠本身去看一看。下面我直接copy其中的核心片斷,不想跳去看的能夠直接看下面這些:

Calculating a selector's specificity

A selector's specificity is calculated as follows:

  • count 1 if the declaration is from is a 'style' attribute rather than a rule with a selector, 0 otherwise (= a) (In HTML, values of an element's "style" attribute are style sheet rules. These rules have no selectors, so a=1, b=0, c=0, and d=0.)
  • count the number of ID attributes in the selector (= b)
  • count the number of other attributes and pseudo-classes in the selector (= c)
  • count the number of element names and pseudo-elements in the selector (= d)

The specificity is based only on the form of the selector. In particular, a selector of the form "[id=p33]" is counted as an attribute selector (a=0, b=0, c=1, d=0), even if the id attribute is defined as an "ID" in the source document's DTD.

Concatenating the four numbers a-b-c-d (in a number system with a large base) gives the specificity.

 文中還給出了一些例子,結合例子相信能夠很快明白這種規則:

 /* Some examples: */ * {}  /* a=0 b=0 c=0 d=0 -> specificity = 0,0,0,0 */ li {}  /* a=0 b=0 c=0 d=1 -> specificity = 0,0,0,1 */ li:first-line {}  /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */ ul li {}  /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */ ul ol+li {}  /* a=0 b=0 c=0 d=3 -> specificity = 0,0,0,3 */ h1 + *[rel=up]{}  /* a=0 b=0 c=1 d=1 -> specificity = 0,0,1,1 */ ul ol li.red {}  /* a=0 b=0 c=1 d=3 -> specificity = 0,0,1,3 */ li.red.level {}  /* a=0 b=0 c=2 d=1 -> specificity = 0,0,2,1 */ #x34y {}  /* a=0 b=1 c=0 d=0 -> specificity = 0,1,0,0 */ style="" /* a=1 b=0 c=0 d=0 -> specificity = 1,0,0,0 */

  大概意思就是,有a,b,c,d 這樣四個計數器。這四個計數器分別按照下面的規則計數:

  1. 當樣式聲明來自內聯樣式時,a=1;
  2. 計算選擇器中有多少個id選擇器,每出現一個,b+=1;
  3. 計算選擇器中有多少個其它屬性的選擇器和僞類選擇器,每出現一個,c+=1(注意class也屬於這裏所說的「其它屬性的選擇器」);
  4. 計算選擇器中有多少個元素名或者僞元素,每出現一個,d+=1(注意 * 並不在元素名之列,因此上面第一個例子纔會全爲0);

  像上面這樣計算以後,把 a,b,c,d 按一個規則計算其特徵值(具體怎樣我不清楚,我這裏理解爲按順序拼成一個數字字符串再將其拿來比較),值較大選擇器的樣式聲明會覆蓋掉較小的(more specific selectors will override more general ones.)

 

  好了,這樣這道題就終於告一段落。但願這樣能幫到本身,更但願能幫到有須要的人。

相關文章
相關標籤/搜索