許多應用場景都需要在網格中顯示可選擇的項目,例如日曆、購物車、圖庫、文件瀏覽器和在線圖書館,甚至那些要求你選擇所有帶有斑馬線的圖片的安全檢查。
本文介紹一種巧妙的方法來顯示網格中的可選項目,並非重新創建reCAPTCHA,而是能夠選擇多個項目。當選擇兩個或多個相鄰項目時,我們可以巧妙地使用:nth-of-type
組合器、偽元素和:checked
偽類來設計它們,使它們看起來組合在一起。
這種組合器和偽元素來實現圓角複選框的想法源於我之前寫的一篇文章。那是一個簡單的單列設計:
然而,這一次,圓角效果應用於網格上垂直和水平軸上的元素。你不需要閱讀我關於復選框樣式的上一篇文章,因為我將在這裡涵蓋你需要知道的一切。但是,如果你對本文中所做內容的簡化版本感興趣,那麼那篇文章值得一看。
注意以下幾點將非常有用。例如,為了簡單起見,我在我的演示中使用了靜態HTML 和CSS。根據你的應用程序,你可能需要動態生成網格及其中的項目。為了專注於效果,我省略了輔助功能的實際檢查,但在生產環境中,你肯定需要考慮這類事情。
此外,我使用CSS Grid 進行佈局。我推薦這樣做,但這只是一個個人偏好,你的體驗可能會有所不同。對我來說,使用網格允許我輕鬆使用同級選擇器來定位項目的::before
和::after
偽元素。
因此,無論你可能想要在你的應用程序中使用什麼佈局標準,請確保偽元素仍然可以在CSS 中被定位,並確保佈局在不同的瀏覽器和屏幕上保持不變。
正如你在之前的演示中可能注意到的那樣,選中和取消選中復選框元素會修改框的設計,具體取決於周圍其他復選框的選擇狀態。這是因為我使用相鄰元素的偽元素而不是它自己的元素來設置每個框的樣式。
下圖顯示了每個列(第一列除外)中框的::before
偽元素如何與它們左側的框重疊,以及每個行(第一行除外)中框的::after
偽元素如何與上面的框重疊。
標記非常簡單:
<main></main>
初始CSS 中還有更多內容。但是,首先是網格本身:
/* 網格*/ main { display: grid; grid: repeat(5, 60px) / repeat(4, 85px); align-items: center; justify-items: center; margin: 0; }
這是一個包含複選框的五行四列的網格。我決定清除複選框的默認外觀,然後賦予它們我自己的淺灰色背景和超圓角邊框:
/* 所有復選框*/ input { -webkit-appearance: none; appearance: none; background: #ddd; border-radius: 20px; cursor: pointer; display: grid; height: 40px; width: 60px; margin: 0; }
還要注意,複選框本身也是網格。這是放置其::before
和::after
偽元素的關鍵。說到這裡,讓我們現在就做吧:
/* 除第一列和第一行外的偽元素*/ input:not(:nth-of-type(4n 1))::before, input:nth-of-type(n 5)::after { content: ''; border-radius: 20px; grid-area: 1 / 1; pointer-events: none; }
我們只選擇不在網格第一列或第一行的複選框的偽元素。 input:not(:nth-of-type(4n 1))
從第一個複選框開始,然後選擇從那裡開始的每四個項目的::before
。但是請注意我們說的是:not()
,所以實際上我們所做的是跳過從第一個開始的每個第四個複選框的::before
偽元素。然後,我們從第五個複選框開始,將樣式應用於每個複選框的::after
偽元素。
現在我們可以為不在網格第一列或第一行的每個複選框設置::before
和::after
偽元素的樣式,以便它們分別向左或向上移動,默認情況下隱藏它們。
/* 除第一列外的偽元素*/ input:not(:nth-of-type(4n 1))::before { transform: translatex(-85px); } /* 除第一行外的偽元素*/ input:nth-of-type(n 5)::after { transform: translatey(-60px); }
現在是設置複選框處於:checked
狀態時的樣式。首先,讓我們給它們一個顏色,比如青檸綠背景:
input:checked { background: limegreen; }
一個選中的框應該能夠重新設置所有相鄰選中框的樣式。換句話說,如果我們選擇網格中的第11 個複選框,我們也應該能夠設置其上方、下方、左側和右側周圍框的樣式。
這是通過定位正確的偽元素來完成的。我們如何做到這一點?好吧,這取決於網格中列的實際數量。如果在5×4 網格中選中兩個相鄰框,則CSS 如下:
/* 選中框的右邊界(如果其右側的元素已選中)*/ input:not(:nth-of-type(4n)):checked input:checked::before { border-top-right-radius: 0; border-bottom-right-radius: 0; background: limegreen; } /* 選中框的下邊界(如果下面的元素已選中)*/ input:nth-last-of-type(n 5):checked * * * input:checked::after { border-bottom-right-radius: 0; border-bottom-left-radius: 0; background: limegreen; } /* 選中框的相鄰(右側)選中框的左邊界*/ input:not(:nth-of-type(4n)):checked input:checked input::before { border-top-left-radius: 0; border-bottom-left-radius: 0; background: limegreen; } /* 選中框的相鄰(下方)選中框的上邊界*/ input:not(:nth-of-type(4n)):checked * * * input:checked input::before { border-top-left-radius: 0; border-top-right-radius: 0; background: limegreen; }
如果你願意,你可以動態生成上面的代碼。但是,對於一個典型的網格(例如圖片庫),列的數量將很小,並且可能是固定數量的項目,而行可能會不斷增加。特別是如果設計用於移動屏幕。這就是為什麼這種方法仍然是一種有效的方法。如果由於某種原因你的應用程序恰好具有有限的行和擴展的列,那麼考慮將網格旋轉成側面,因為對於一系列項目,CSS Grid 將它們從左到右、從上到下(即逐行)排列。
我們還需要為網格中的最後一個複選框添加樣式——它們並非都由偽元素覆蓋,因為它們是每個軸中的最後一項。
/* 選中框(最後一列)的左邊界*/ input:nth-of-type(4n-1):checked input:checked { border-top-left-radius: 0; border-bottom-left-radius: 0; } /* 選中框(最後一列)的相鄰(下方)選中框的上邊界*/ input:nth-of-type(4n):checked * * * input:checked { border-top-left-radius: 0; border-top-right-radius: 0; }
這些選擇器很棘手!第一個……
input:nth-of-type(4n-1):checked input:checked
……基本上是這樣說的:
在倒數第二列中,一個選中的元素緊挨著一個選中的元素。
nth-of-type
的計算方式如下:
<code>4(0) - 1 = 无匹配项4(1) - 1 = 第3 个项目4(2) - 1 = 第7 个项目4(3) - 1 = 第11 个项目等等。</code>
所以,我們從第三個複選框開始,從那裡選擇每個第四個複選框。如果該序列中的複選框被選中,那麼如果它們也被選中,我們也會設置相鄰複選框的樣式。
以及這一行:
input:nth-of-type(4n):checked * * * input:checked
是這樣說的:
一個元素,前提是它被選中,直接與一個元素相鄰,該元素又直接與另一個元素相鄰,該元素又直接與另一個元素相鄰,而該元素又直接與一個處於選中狀態的元素相鄰。
這意味著我們正在選擇每個第四個被選中的複選框。如果該序列中的複選框被選中,那麼如果它也被選中,我們將設置從該複選框開始的下一個第四個複選框的樣式。
我們剛才看到的只是設計背後的普遍原則和邏輯。同樣,它在你的應用程序中的實用性將取決於網格設計。
我使用了圓角邊框,但你可以嘗試其他形狀,甚至可以嘗試背景效果(Temani 為你提供了想法)。既然你知道公式是如何工作的,剩下的完全取決於你的想像力。
這是一個在簡單日曆中可能的樣子:
同樣,這只是一個使用靜態標記的粗略原型。而且,在日曆功能中需要考慮很多輔助功能方面的考慮。
就是這樣!很巧妙,對吧?我的意思是,發生的事情沒有什麼完全“新的”。但它是一個關於在CSS 中選擇事物的好例子。如果我們掌握了更多使用組合器和偽元素的高級選擇技術,那麼我們的樣式能力就可以超越只設置一個項目的樣式——正如我們所看到的,我們可以根據另一個元素的狀態有條件地設置項目的樣式。
以上是在網格容器中有條件造型選定的元素的詳細內容。更多資訊請關注PHP中文網其他相關文章!