CSS單標(biāo)簽實(shí)現(xiàn)復(fù)雜的棋盤布局
最近,有網(wǎng)友問我,他們的一個(gè)作業(yè),盡量使用少的標(biāo)簽去實(shí)現(xiàn)這樣一個(gè)象棋布局:
他用了 60 多個(gè)標(biāo)簽,而他的同學(xué),只用了 6 個(gè),問我有沒有辦法盡可能的做到利用更少的標(biāo)簽去完成這個(gè)布局效果。
其實(shí),對(duì)于一個(gè)頁面的布局而言,標(biāo)簽越少不一定是好事,我們?cè)诳紤] DOM 的消耗的同時(shí),也需要關(guān)注代碼的可讀性,以及后續(xù)基于這個(gè)布局的制作的交互的難易性等等。
當(dāng)然,僅僅從用更少的標(biāo)簽完成這個(gè)布局的角度而言,我們能夠把標(biāo)簽數(shù)壓縮到多少呢個(gè)?(不考慮 <body>
和 <html>
)
答案是 1 個(gè)。
本文就嘗試使用一個(gè)標(biāo)簽完成這個(gè)效果,當(dāng)然,這僅僅是探索 CSS 的極限,不代表我推薦在實(shí)際業(yè)務(wù)中這樣去寫。
我們對(duì)整個(gè)布局進(jìn)行一下拆分,大致可以分為三部分:網(wǎng)格 + 虛線交叉十字 + 特殊符號(hào):
并且,像虛線交叉十字和特殊的符號(hào)都不止一個(gè),這里必然會(huì)有一些技巧存在。
使用漸變實(shí)現(xiàn)網(wǎng)格
OK,首先,我們實(shí)現(xiàn)最簡(jiǎn)單的網(wǎng)格布局:
不考慮最外層的一圈邊框,我們可以首先利用多重線性漸變實(shí)現(xiàn)一個(gè)網(wǎng)格布局:
<div class="g-grid"></div>
.g-grid { width: 401px; height: 451px; background: repeating-linear-gradient(#000, #000 1px, transparent 1px, transparent 50px), repeating-linear-gradient(90deg, #000, #000 1px, transparent 1px, transparent 50px); background-repeat: no-repeat; background-size: 100% 100%, 100% 100%; background-position: 0 0, 0 0; }
效果如下:
在最外層加一層邊框有非常多辦法,這里我們簡(jiǎn)單使用 outline
配合 outline-offset
即可:
.g-grid { width: 401px; height: 451px; background: repeating-linear-gradient(#000, #000 1px, transparent 1px, transparent 50px), repeating-linear-gradient(90deg, #000, #000 1px, transparent 1px, transparent 50px); background-repeat: no-repeat; background-size: 100% 100%, 100% 100%; background-position: 0 0, 0 0; outline: 1px solid #000; outline-offset: 5px; }
這樣,一個(gè)架子就差不多了:
當(dāng)然,棋盤中間的一行,是沒有格子的。要將上述漸變代碼處理一下,可以分成上下兩塊,利用 background-size
和 background-position
進(jìn)行分隔。
當(dāng)然,我們也可以在最上層直接再疊一層純白色漸變:
.grid { // ... background: // 最上層疊加一層白色漸變 linear-gradient(#fff, #fff), // 下面兩個(gè)重復(fù)線性漸變實(shí)現(xiàn)網(wǎng)格 repeating-linear-gradient(#000, #000 1px, transparent 1px, transparent 50px), repeating-linear-gradient(90deg, #000, #000 1px, transparent 1px, transparent 50px); background-repeat: no-repeat; background-size: calc(100% - 2px) 49px, 100% 100%, 100% 100%; background-position: 1px 201px, 0 0, 0 0; }
到這里,其實(shí)核心還都是漸變,目前共 3 層漸變,得到這樣一個(gè)效果:
利用漸變實(shí)現(xiàn)交叉虛線十字
OK,我們繼續(xù),我們需要基于上述的基礎(chǔ),得到兩個(gè)交叉虛線十字,像是這樣:
這里其實(shí)真的有難度。想象一下,如果給你一個(gè) DIV,去實(shí)現(xiàn)其中一個(gè),可以怎么做呢?
通過 border 中特有的虛線 dashed?這樣可能就需要兩個(gè)元素設(shè)置單邊的虛線邊框,然后旋轉(zhuǎn)相交得到。(可以利用元素的兩個(gè)偽元素,實(shí)現(xiàn)在一個(gè) DOM 中)。
當(dāng)然,這樣的話,我們的標(biāo)簽就不夠用了。
所以,這里我們另辟蹊徑,繼續(xù)使用漸變!
首先,打個(gè)樣,如果是一個(gè) 100px x 100px 的 DIV,可以怎么利用漸變?nèi)ギ嫿徊嫣摼€十字呢?
<div></div>
div { position: relative; margin: auto; width: 100px; height: 100px; border: 1px solid #000; background: linear-gradient( 45deg, transparent 0, transparent calc(50% - 0.5px), #000 calc(50% - 0.5px), #000 calc(50% + 0.5px), transparent calc(50% + 0.5px), transparent 0); }
我們首先利用漸變,實(shí)現(xiàn)一條 1px 的斜線,注意這里的漸變是從透明到黑色到透明,實(shí)現(xiàn)了一條 45° 的斜線。
我們?cè)俜?45° 過來,利用多重線性漸變,實(shí)現(xiàn)透明到白色的漸變效果:
div { position: relative; margin: auto; width: 100px; height: 100px; border: 1px solid #000; background: // 漸變 1 repeating-linear-gradient(-45deg, transparent 0, transparent 5px, #fff 5px, #fff 10px), // 漸變 2 linear-gradient(45deg, transparent 0, transparent calc(50% - 0.5px), #000 calc(50% - 0.5px), #000 calc(50% + 0.5px), transparent calc(50% + 0.5px), transparent 0); }
這樣,我們就得到了一條虛線:
好吧,這一步有一些同學(xué)可能會(huì)有一點(diǎn)疑惑,怎么變過來的。
我把上面漸變 1的透明色改成黑色,就很好理解了:
想象一下,上圖的黑色部分,如果是透明的,就能透出原本的那條斜線沒有被白色遮擋住的地方。
這里,需要提一下,在漸變中,越是先書寫的漸變,層級(jí)越高。
好,有了上面的鋪墊,我們基于上面的代碼,再繼續(xù)利用漸變,把上下兩個(gè)交叉虛線十字補(bǔ)齊即可:
.g-grid { width: 401px; height: 451px; outline: 1px solid #000; outline-offset: 5px; background: // 最上層的白色塊,擋住中間的網(wǎng)格 linear-gradient(#fff, #fff), // 實(shí)現(xiàn)網(wǎng)格布局 repeating-linear-gradient(#000, #000 1px, transparent 1px, transparent 50px), repeating-linear-gradient(90deg, #000, #000 1px, transparent 1px, transparent 50px), // 棋盤上方的虛線1 repeating-linear-gradient(-45deg, transparent 0, transparent 5px, #fff 5px, #fff 10px), linear-gradient(45deg, transparent, transparent calc(50% - 0.5px), #000 calc(50% - 0.5px), #000 calc(50% + 0.5px), transparent calc(50% + 0.5px), transparent 0), // 棋盤上方的虛線2 repeating-linear-gradient(45deg, transparent 0, transparent 5px, #fff 5px, #fff 10px), linear-gradient(-45deg, transparent, transparent calc(50% - 0.5px), #000 calc(50% - 0.5px), #000 calc(50% + 0.5px), transparent calc(50% + 0.5px), transparent 0), // 棋盤下方的虛線1 repeating-linear-gradient(-45deg, transparent 0, transparent 5px, #fff 5px, #fff 10px), linear-gradient(45deg, transparent, transparent calc(50% - 0.5px), #000 calc(50% - 0.5px), #000 calc(50% + 0.5px), transparent calc(50% + 0.5px), transparent 0), // 棋盤下方的虛線2 repeating-linear-gradient(45deg, transparent 0, transparent 5px, #fff 5px, #fff 10px), linear-gradient(-45deg, transparent, transparent calc(50% - 0.5px), #000 calc(50% - 0.5px), #000 calc(50% + 0.5px), transparent calc(50% + 0.5px), transparent 0); background-repeat: no-repeat; background-size: calc(100% - 2px) 49px, 100% 100%, 100% 100%, // 交叉虛線 1 100px 100px, 100px 100px, 100px 100px, 100px 100px, // 交叉虛線 2 100px 100px, 100px 100px, 100px 100px, 100px 100px; background-position: 1px 201px, 0 0, 0 0, // 交叉虛線 1 151px 0, 151px 0, 151px 0, 151px 0, // 交叉虛線 2 151px 350px, 151px 350px, 151px 350px, 151px 350px; }
嚯,這漸變代碼確實(shí)復(fù)雜了點(diǎn),但是其實(shí)每一塊的作用都是很清晰的,這樣,我們的棋盤就變成了這樣:
借助偽元素及 box-shadow 實(shí)現(xiàn)剩余符合
到這里,我們僅僅使用了元素本身,要知道,我們還有元素的兩個(gè)偽元素沒使用。要實(shí)現(xiàn)的只剩下多個(gè)的這個(gè)符合:
因?yàn)橐还惨獙?shí)現(xiàn) 12 個(gè)這樣的符號(hào),有的符合還是不完整的,所有這些要在剩余的元素的兩個(gè)偽元素中完成??蛇x的方法思來想去,也只有 box-shadow 了。
利用 box-shadow
能夠非常好的復(fù)制自身。這個(gè)技巧其實(shí)也反復(fù)講過非常多次了。
我們首先利用元素的一個(gè)偽元素,在這個(gè)位置,實(shí)現(xiàn)一個(gè)短橫線:
代碼大致如下:
.g-grid { // ... &::before { content: ""; position: absolute; top: 95px; left: 35px; width: 10px; height: 1px; background: #000; } }
我們利用 box-shadow
復(fù)制自身,可以完成一半橫線效果。當(dāng)然這里由于是個(gè)鏡面布局,可以利用鏡像 -webkit-box-reflect: below
減少一半的代碼:
.g-grid { // ... &::before { content: ""; position: absolute; top: 95px; left: 35px; width: 10px; height: 1px; background: #000; box-shadow: 20px 0, 0 10px, 20px 10px, 300px 0, 320px 0, 300px 10px, 320px 10px, -30px 50px, -30px 60px, 50px 50px, 50px 60px, 70px 50px, 70px 60px, 150px 50px, 150px 60px, 170px 50px, 170px 60px, 250px 50px, 250px 60px, 270px 50px, 270px 60px, 350px 50px, 350px 60px; -webkit-box-reflect: below 259px; } }
效果如下:
最后,利用另外一個(gè)偽元素,完成另外一半的豎向橫線即可:
.g-grid { // ... &::before { // ... } &::after { // ... box-shadow: 10px 0, 0 20px, 10px 20px, 300px 0px, 300px 20px, 310px 0, 310px 20px, -40px 50px, -40px 70px, 50px 50px, 50px 70px, 60px 50px, 60px 70px, 150px 50px, 150px 70px, 160px 50px, 160px 70px, 250px 50px, 250px 70px, 260px 50px, 260px 70px, 350px 50px, 350px 70px; -webkit-box-reflect: below 260px; } }
這樣,我們就在一個(gè)標(biāo)簽內(nèi),得到這樣一個(gè)效果:
當(dāng)然,還剩下楚河、漢界 4 個(gè)字,這個(gè)也簡(jiǎn)單直接加在 div 中即可,配合一些簡(jiǎn)單的 CSS 調(diào)整,整個(gè)效果就在一個(gè)標(biāo)簽內(nèi)完成啦:
完整的代碼你可以戳這里:CodePen Demo -- CSS Chess board
好,實(shí)際中我確實(shí)不太推薦這么去寫,純粹是為了實(shí)現(xiàn)而實(shí)現(xiàn),少了很多代碼可讀性的考量。因此,本文更多的是給大家?guī)硪恍┧悸罚?dāng)遇到類似的問題的使用能夠有更多的靈感。
最后
到此這篇關(guān)于CSS單標(biāo)簽實(shí)現(xiàn)復(fù)雜的棋盤布局的文章就介紹到這了,更多相關(guān)單標(biāo)簽 實(shí)現(xiàn) 棋盤布局內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
用滑動(dòng)門技術(shù)設(shè)計(jì)按鈕的圖文教程
用滑動(dòng)門技術(shù)設(shè)計(jì)按鈕的圖文教程...2007-07-07div+css在思路和流程上實(shí)現(xiàn)結(jié)構(gòu)與表現(xiàn)的分離分析
內(nèi)容與表現(xiàn)分離,從標(biāo)準(zhǔn)到國(guó)人重視那天起,就已經(jīng)討論了,但是停留在div+css xhtml+css 純代碼的分離,思想上流程上,到底如何分離?2008-08-08《CSS3實(shí)戰(zhàn)》筆記--漸變?cè)O(shè)計(jì)(二)
這篇文章主要介紹了《CSS3實(shí)戰(zhàn)》筆記--漸變?cè)O(shè)計(jì)(二,需要的朋友可以參考下2016-05-05使用display:none時(shí)隱藏DOM元素?zé)o法獲取實(shí)際寬高的解決方法
這篇文章主要介紹了使用display:none時(shí)隱藏DOM元素?zé)o法獲取實(shí)際寬高的解決方法的相關(guān)資料,需要的朋友可以參考下2022-07-07ul+li及css制作韓國(guó)風(fēng)格菜單代碼
ul+li及css制作韓國(guó)風(fēng)格菜單代碼...2007-11-11css網(wǎng)頁布局中注意的幾個(gè)問題小結(jié)
經(jīng)常使用div+css布局的朋友,需要注意以下幾點(diǎn)2008-09-09