1. 程式人生 > >CSS3的nth-child選擇器

CSS3的nth-child選擇器

如果你對這篇文章感興趣,可以瞭解更多的有關 CSS4 的知識來提升自己。

CSS3的:nth-child:nth-last-child 選擇器的神奇之處,不僅僅是可以替代 :first-child:last-child 選擇器,它還可以匹配更為複雜的子元素,比如匹配某個元素(或除第一個元素外)的三個子孫元素,元素中四的倍數的子元素,又或者通過 a*n+b 這樣的表示式來進行匹配子元素。

但你有沒有想過這個選擇器還有其他的妙用?比如,你可以使用它來獲取僅有五個子元素的元素中的第三個元素子元素(接下來我們會介紹一個偽選擇器 :nth-of-m-child 選擇器)。你還可以獲取僅有M個子元素的元素中的所有的子元素(另一個偽選擇器,我們稱之為 :family-of-m

)。

我們什麼時候需要用這兩個選擇器呢?比如我們有一個大小不固定,個數不固定的照片牆,但不想依賴於JS來實現這個效果,能否實現呢?點選 示例 預覽實現的效果。

:nth-of-M-child

選擇含有M個子元素的第某個元素。

很感謝 xantys 向我提供了相關資料連結。資料1資料2

首先,第一個我要介紹的是:nth-of-m-child 偽類。假設元素的子元素位置固定,我們可以通過結合使用:nth-child:nth-last-child 來獲取元素。

如果,我們想獲取僅含有五個子元素的第三個子元素 。示例

span:nth-child(3):nth-last-child(3)
{ ... }

由此我們得出一個通用的公式(m,n為變數)
如果,我們想獲取僅含有五個子元素的第三個子元素 。示例

:nth-child(n):nth-last-child(m+1-n).

:FAMILY-OF-M

現在我們可以獲取一共含有M個元素的第N個元素,如果我們想擴充套件一下,直接獲取某個含有M個元素的父節點下的所有子元素。這裡的祕密是我們使用了CSS3的~兄弟選擇器,它會暴力地匹配到所有的同級兄弟元素。如:

img ~ span { ... }

這種方法會獲取到所有的同級的元素,而不管它一共有幾個。那麼,我們可以嘗試結合加入我們的 :nth-of-m-child

選擇器來實現。

span:nth-child(1):nth-last-child(5) ~ span { ... }

這種方法會獲取到一共只含有5個子元素的第一個子元素(不包含它本身)的所有的兄弟節點,也就是說從第二個子元素到第五個子元素。最後,我們可以通過逗號,把第一個子元素的選擇器加上,程式碼如下, 預覽地址

span:nth-child(1):nth-last-child(5), span:nth-child(1):nth-last-child(5) ~ span { ... }

更進一步的探討

我們準備好了圖片,接下來來填寫它的樣式。

一行展示一張圖片是很容易的,但當我們準備放置三張圖片,希望其中第一張或者第二張圖片稍大一些,我們就會需要用到選擇器匹配。我們的這種匹配方式可以不用在意圖片的個數。

下面是一個帶註釋的例子。需要我們注意的是,可能使用彈性伸縮盒子更為簡單實現,我們這裡只是為讀者提供一種練習使用這種選擇器的方式。

我們使用第五個,第八個,第十一個….來進行特殊匹配。我們可以使用:nth-child(1):nth-last-child(3n+5)來代替我們之前使用的:nth-child(1):nth-last-child(...) 這種方式,獲取第 5,8,11,…等的子元素

/* First two are half-sized (99% / 2) */
img:first-child:nth-last-child(3n+5) ~ img, img:first-child:nth-last-child(3n+5) {
    max-width: 49.5%;
    margin-right: 1%;
}

/* Last n - 2 are (98% / 3) */
img:first-child:nth-last-child(3n+5) + img ~ img {
    max-width: 32.6%;
    margin-right: 1%;
}

/* But second, fifth, eighth, ... have no right margin */
img:first-child:nth-last-child(3n+5) ~ img:nth-child(3n+2) {
    margin-right: 0;
}

想匹配6,9,12那就更容易了。

/* Six, nine, twelve, ... are all (98% / 3) */
img:first-child:nth-last-child(3n+6) ~ img, img:first-child:nth-last-child(3n+6) {
    max-width: 32.6%;
    margin-right: 1%;
}

/* Every third one of these has no right margin. */
img:first-child:nth-last-child(3n+6) ~ img:nth-child(3n) {
    margin-right: 0;
}

7,10,13…類似於5/8/11

/* First four are half-sized (99% / 2) */
img:first-child:nth-last-child(3n+7) ~ img, img:first-child:nth-last-child(3n+7) {
    max-width: 49.5%;
    margin-right: 1%;
}

/* Last n - 4 are (98% / 3) */
img:first-child:nth-last-child(3n+7) + img + img + img ~ img {
    max-width: 32.6%;
    margin-right: 1%;
}

/* The second and fourth, seventh, tenth, ... have no right margin */
img:first-child:nth-last-child(3n+7) + img,
    img:first-child:nth-last-child(3n+7) ~ img:nth-child(3n+4) {
    margin-right: 0;
    outline: 1px solid red;
}

總結

我們可以通過使用:nth-child和其他的選擇器來實現更多有趣的效果。這種匹配方式也同樣適用於 :nth-of-type:nth-last-of-type

這種方式在手機端和PC端並沒有明顯差距,但如果你介意的話,可以自己做一下測試。
如果你打算結合彈性盒子中的 flex-wrap 來簡化示例,那麼你可能可以更優雅的使用更多不同的尺寸來展示我們的圖片。
你也可以將表示式中的引數改為even 或者 odd,來匹配奇數偶數,或者其他限定符。
如果你對這篇文章有任何疑問或者更好的建議,可以通過JSFiddle展示給我。
歡迎關注我的Twitter賬號@mmastrac ,與我聯絡。

2015.01.09