單標簽實現複雜的棋盤佈局

来源:https://www.cnblogs.com/coco1s/archive/2022/09/20/16710203.html
-Advertisement-
Play Games

最近,有群友問我,他們的一個作業,儘量使用少的標簽去實現這樣一個象棋佈局: 他用了 60 多個標簽,而他的同學,只用了 6 個,問我有沒有辦法儘可能的做到利用更少的標簽去完成這個佈局效果。 其實,對於一個頁面的佈局而言,標簽越少不一定是好事,我們在考慮 DOM 的消耗的同時,也需要關註代碼的可讀性, ...


最近,有群友問我,他們的一個作業,儘量使用少的標簽去實現這樣一個象棋佈局:

用了 60 多個標簽,而他的同學,只用了 6 個,問我有沒有辦法儘可能的做到利用更少的標簽去完成這個佈局效果。

其實,對於一個頁面的佈局而言,標簽越少不一定是好事,我們在考慮 DOM 的消耗的同時,也需要關註代碼的可讀性,以及後續基於這個佈局的製作的交互的難易性等等。

當然,僅僅從用更少的標簽完成這個佈局的角度而言,我們能夠把標簽數壓縮到多少呢個?(不考慮 <body><html>

答案是 1 個

本文就嘗試使用一個標簽完成這個效果,當然,這僅僅是探索 CSS 的極限,不代表我推薦在實際業務中這樣去寫。

我們對整個佈局進行一下拆分,大致可以分為三部分:網格 + 虛線交叉十字 + 特殊符號:

並且,像虛線交叉十字和特殊的符號都不止一個,這裡必然會有一些技巧存在。

使用漸變實現網格

OK,首先,我們實現最簡單的網格佈局:

不考慮最外層的一圈邊框,我們可以首先利用多重線性漸變實現一個網格佈局:

<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;
}

效果如下:

在最外層加一層邊框有非常多辦法,這裡我們簡單使用 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;
}

這樣,一個架子就差不多了:

當然,棋盤中間的一行,是沒有格子的。要將上述漸變代碼處理一下,可以分成上下兩塊,利用 background-sizebackground-position 進行分隔。

當然,我們也可以在最上層直接再疊一層純白色漸變:

.grid {
    // ...
    background:
        // 最上層疊加一層白色漸變
        linear-gradient(#fff, #fff),
        // 下麵兩個重覆線性漸變實現網格
        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;
}

到這裡,其實核心還都是漸變,目前共 3 層漸變,得到這樣一個效果:

利用漸變實現交叉虛線十字

OK,我們繼續,我們需要基於上述的基礎,得到兩個交叉虛線十字,像是這樣:

這裡其實真的有難度。想象一下,如果給你一個 DIV,去實現其中一個,可以怎麼做呢?

通過 border 中特有的虛線 dashed?這樣可能就需要兩個元素設置單邊的虛線邊框,然後旋轉相交得到。(可以利用元素的兩個偽元素,實現在一個 DOM 中)。

當然,這樣的話,我們的標簽就不夠用了。

所以,這裡我們另闢蹊徑,繼續使用漸變

首先,打個樣,如果是一個 100px x 100px 的 DIV,可以怎麼利用漸變去畫交叉虛線十字呢?

<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);
}

我們首先利用漸變,實現一條 1px 的斜線,註意這裡的漸變是從透明到黑色到透明,實現了一條 45° 的斜線。

我們再反 45° 過來,利用多重線性漸變,實現透明到白色的漸變效果:

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);
}

這樣,我們就得到了一條虛線:

好吧,這一步有一些同學可能會有一點疑惑,怎麼變過來的。

我把上面漸變 1的透明色改成黑色,就很好理解了:

想象一下,上圖的黑色部分,如果是透明的,就能透出原本的那條斜線沒有被白色遮擋住的地方。

這裡,需要提一下,在漸變中,越是先書寫的漸變,層級越高。

好,有了上面的鋪墊,我們基於上面的代碼,再繼續利用漸變,把上下兩個交叉虛線十字補齊即可:

.g-grid {
    width: 401px;
    height: 451px;
    outline: 1px solid #000;
    outline-offset: 5px;
    background:
        // 最上層的白色塊,擋住中間的網格
        linear-gradient(#fff, #fff),
        // 實現網格佈局
        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;
}

嚯,這漸變代碼確實複雜了點,但是其實每一塊的作用都是很清晰的,這樣,我們的棋盤就變成了這樣:

藉助偽元素及 box-shadow 實現剩餘符合

到這裡,我們僅僅使用了元素本身,要知道,我們還有元素的兩個偽元素沒使用。要實現的只剩下多個的這個符合:

因為一共要實現 12 個這樣的符號,有的符合還是不完整的,所有這些要在剩餘的元素的兩個偽元素中完成。可選的方法思來想去,也只有 box-shadow 了。

利用 box-shadow 能夠非常好的複製自身。這個技巧其實也反覆講過非常多次了。

我們首先利用元素的一個偽元素,在這個位置,實現一個短橫線:

代碼大致如下:

.g-grid {
    // ...
    &::before {
        content: "";
        position: absolute;
        top: 95px;
        left: 35px;
        width: 10px;
        height: 1px;
        background: #000;
    }
}

我們利用 box-shadow 複製自身,可以完成一半橫線效果。當然這裡由於是個鏡面佈局,可以利用鏡像 -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-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;
    }
}

這樣,我們就在一個標簽內,得到這樣一個效果:

當然,還剩下楚河、漢界 4 個字,這個也簡單直接加在 div 中即可,配合一些簡單的 CSS 調整,整個效果就在一個標簽內完成啦:

完整的代碼你可以戳這裡:CodePen Demo -- CSS Chess board

好,實際中我確實不太推薦這麼去寫,純粹是為了實現而實現,少了很多代碼可讀性的考量。因此,本文更多的是給大家帶來一些思路,當遇到類似的問題的使用能夠有更多的靈感。

最後

好了,本文到此結束,希望本文對你有所幫助

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一.起步 1.1 配置uni-app開發環境 什麼是uni-app,就是基於vue的一個開發框架,可以將我們寫的一套代碼,同時發佈到ios、安卓、小程式等多個平臺 ==官方推薦使用Hbuilderx來寫uni-app項目== 下載之後可以將預設改為vscode 進入hbuilder插件市場下載scs ...
  • 前端技術的發展不斷融入了很多後端的思想,逐步形成前端的 ”四個現代化“:工程化、模塊化、規範化、流程化。這個主題介紹 *模塊化* ,主要內容包括模塊化前傳(早期模塊化的實現)、模塊化的四個規範(Common JS、AMD、CMD、ESM)。本文就聊聊早期的模塊化。 ...
  • 現在的很多程式應用,基本上都是需要多端覆蓋,因此基於一個Web API的後端介面,來構建多端應用,如微信、H5、APP、WInForm、BS的Web管理端等都是常見的應用。本篇隨筆繼續分析總結一下項目開發的經驗,針對頁面組件化開發經驗方面進行一些梳理總結,內容包括組件的概念介紹,簡單頁面組件的抽取開... ...
  • 每日3題 1 以下代碼執行後,控制臺中的輸出內容為? // index.js console.log(1); import { sum } from "./sum.js"; console.log(sum(1, 2)); //sum.js console.log(2); export const s ...
  • 導讀:面對多種多樣的跨端訴求,有哪些跨端方案?跨端的本質是什麼?作為業務技術開發者,應該怎麼做?本文分享阿裡巴巴ICBU技術部在跨端開發上的一些思考,介紹了當前主流的跨端方案,以及跨端開發的經驗心得。 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 最近在研究一個基於TP6的框架CRMEB,這裡分享下我的開發心得 首先在上篇文章中,我們安裝了CRMEBphp介面項目,需要可以看這一篇 TP6框架--CRMEB學習筆記:項目初始化+環境配置 1.獲取項目 這裡是git地址 https: ...
  • 通過 antd 框架的 Upload 控制項,採用手動上傳的方式,先選擇需要上傳的文件(控制文件數量以及大小),再根據所選的文件列表,迴圈上傳,期間通過 Spin 控制項提示上傳中。 ...
  • 隨著前端的範疇逐漸擴大,深度逐漸下沉,富前端必然帶來的一個問題就是性能。特別是在大型複雜項目中,重前端業務可能因為一個小小的數據依賴,導致整個頁面卡頓甚至崩潰。本文基於Quick BI(數據可視化分析平臺)歷年架構變遷中性能的排查、解決和總結出的“個性”問題,嘗試總結整個前端層面相對“共性”的問題,... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...