你們好,有一段時間沒有發表《前端每日實戰》做品了,今天,2020年的第一天,終於又從新啓程,我將繼續實踐 PBL(Project-based Learning)的學習方法,並把學習筆記分享出來,和你們交流探討、共同進步。css
這段沒有發表做品的日子裏,我在人民郵電出版社的支持和幫助下,寫出了一本書,命名爲《CSS3 藝術》,它脫胎於《前端每日實戰》的一百多個做品,把僞元素、邊框、背景、陰影、剪切、濾鏡、色彩混合、變量、計數器、變換、緩動、動畫這些概念進行了梳理和總結,但願能爲你們學習 CSS 提供一些幫助。此書已於近日上市,京東、天貓、噹噹都可購買。html
接下來進入正題,今天的項目是用純 CSS 製做一個 2020 造型圖案,併爲它增長一點動畫效果。前端
按下右側的「點擊預覽」按鈕能夠在當前頁面預覽,點擊連接能夠全屏預覽。app
https://codepen.io/comehope/pen/jOEGzZxdom
dom 結構的最外層用 <figure>
元素,表示這是一個圖片:函數
<figure></figure>
頁面用深紅色背景,並採用 grid 佈局:佈局
body { margin: 0; height: 100vh; display: flex; align-items: center; justify-content: center; background-color: darkred; } figure { display: grid; grid-template-columns: repeat(8, 1em); grid-template-rows: repeat(3, 1em); font-size: 60px; color: whitesmoke; }
grid 佈局比定位佈局的語義化更好,一樣的佈局效果,grid 佈局的代碼量比定位佈局的代碼量明顯減小。此項目建立了一個 3 行 8 列的網格,爲了能明顯看出網格線,咱們增長一些輔助線,這些輔助線會在做品完成後被刪除掉:學習
figure { background-image: linear-gradient(to bottom, transparent 0%, transparent 99%, pink 100%), linear-gradient(to right, transparent 0%, transparent 99%, pink 100%), linear-gradient(to top, transparent 0%, transparent 99%, pink 100%), linear-gradient(to left, transparent 0%, transparent 99%, pink 100%); background-size: 1em 1em; background-repeat: repeat, repeat, repeat-x, repeat-y; }
效果以下圖:字體
在 dom 中增長有關數字 2 的元素,數字 2 被分紅了 4 部分:flex
<figure> <span class="two part1"></span> <span class="two part2"></span> <span class="two part3"></span> <span class="two part4"></span> </figure>
把這 4 部分分別放置在網格的相應位置上,grid-area
的屬性 x/y 分別表示頂部網格線編號和左側網格線編號,網格線是從 1 開始編號的,以 .part4
爲例,它的頂部網格線是從上數的第3條,左側網格是從左數的第2條,因此它的屬性值是 3/2
:
.two { background-color: currentColor; } .two.part1 {grid-area: 1/1;} .two.part2 {grid-area: 2/2;} .two.part3 {grid-area: 3/1;} .two.part4 {grid-area: 3/2;}
效果以下圖:
接下來把各部分的形狀都改成扇形,border-radius
屬性有 4 個值,分別表明左上、右上、右下、左下的圓角值,以 .part4
爲例,它是左下角爲圓角的扇形,因此它的屬性值是 0 0 0 100%
:
.two.part1 {grid-area: 1/1; border-radius: 100% 0 0 0;} .two.part2 {grid-area: 2/2; border-radius: 0 0 100% 0;} .two.part3 {grid-area: 3/1; border-radius: 100% 0 0 0;} .two.part4 {grid-area: 3/2; border-radius: 0 0 0 100%;}
效果以下圖:
這時一個數字 2 已經繪製出來了,另外一個數字 2 不須要增長 dom 元素,只要把第 1 個元素複製一下就能夠了,這裏使用的是 drop-shadow()
函數,它的 2 個參數分別表明複製後的偏移量,此處的參數值爲 4em 0
,即水平方向向右平移 4em,垂直方向不變:
.two { filter: drop-shadow(4em 0); }
效果以下圖:
至此,2個數字 2 就都畫出來了。
在 dom 中增長有關數字 0 的元素,和數字 2 不一樣,每個數字 0 只須要 1 個 dom 元素,因此 2 個數字 0 須要 2 個 dom 元素:
<figure> <span class="two part1"></span> <span class="two part2"></span> <span class="two part3"></span> <span class="two part4"></span> <span class="zero copy-1"></span> <span class="zero copy-2"></span> </figure>
在網格中分別定位 2 個數字 0,仍使用 grid-area
參數,但它們的屬性值爲 4 個數字,後 2 個數字分別表明底部網格線編號和右側網格線編號,可知每一個 0 佔據 2 * 2 的網格區域:
.zero.copy-1 {grid-area: 2/3/4/5;} .zero.copy-2 {grid-area: 2/7/4/9;}
畫出數字 0 的大體輪廓,這裏是利用邊框屬性繪製的,元素自己寬高爲 0,可是有 1em 的邊框,其中上、下邊框是白色,左、右邊框是透明色,注意,在 CSS 中邊框並不必定以線條的形式存在,在此處每條邊框都是三角形:
.zero { width: 0; height: 0; border: 1em solid; border-color: currentColor transparent; }
效果以下圖:
增長圓角效果:
.zero { border-radius: 50%; }
效果以下圖:
再傾斜 45 度:
.zero { transform: rotate(-45deg); }
效果以下圖:
至此,2 個數字 0 也都畫出來了。
在 dom 中增長有關文本的元素,一共 3 個單詞,分別用 3 個元素表示:
<figure> <span class="two part1"></span> <span class="two part2"></span> <span class="two part3"></span> <span class="two part4"></span> <span class="zero copy-1"></span> <span class="zero copy-2"></span> <span class="text happy">happy</span> <span class="text new">new</span> <span class="text year">year</span> </figure>
效果以下圖,能夠看到這 3 個單詞都重疊在第1行的第2個網格中,這是由於在 grid 佈局下會自動把未指定 grid-area
屬性的元素排放在未被佔用的網格中:
接下來爲 3 個文本元素設置它們的網格位置:
.text.happy {grid-area: 1/2;} .text.new {grid-area: 2/4;} .text.year {grid-area: 1/6;}
效果以下圖:
接下來設置文字的樣式,把文字都改成大寫字母,加粗,字體用花式字體,爲避免與左側的圖案靠得太緊,再把文字左側增長一點內邊距:
.text { text-transform: uppercase; font-size: 0.66em; line-height: 1.5em; font-weight: bold; font-family: cursive; padding-left: 0.25em; }
效果以下圖:
至此,文字繪製完成。
由於數字 0 造型太抽象,因此咱們讓數字 0 轉動起來,動畫很簡單,就是以 4 秒每圈的速度不斷地轉啊轉,由於數字 0 此前設置了旋轉 45 度,因此動畫的 to
關鍵幀要加上 45 度,另外旋轉的度數是負值,表示逆時針旋轉:
.zero { animation: round 4s linear infinite; } @keyframes round { to { transform: rotate(calc(-45deg + -1turn)); } }
效果以下圖:
不過咱們看到左側的數字 0 在轉動時遮擋住了文字「new」,爲了不遮擋,咱們用色彩混合模式來解決,這樣當數字 0 和文字「new」重疊時,重疊的部分會變爲黑色:
.text { mix-blend-mode: difference; }
效果以下圖:
至此,整個做品所有完成了,最後把輔助線刪除掉:
figure { /*background-image: linear-gradient(to bottom, transparent 0%, transparent 99%, pink 100%), linear-gradient(to right, transparent 0%, transparent 99%, pink 100%), linear-gradient(to top, transparent 0%, transparent 99%, pink 100%), linear-gradient(to left, transparent 0%, transparent 99%, pink 100%); background-size: 1em 1em; background-repeat: repeat, repeat, repeat-x, repeat-y;*/ }
效果以下圖:
完整的 CSS 代碼以下:
body { margin: 0; height: 100vh; display: flex; align-items: center; justify-content: center; background-color: darkred; } figure { display: grid; grid-template-columns: repeat(8, 1em); grid-template-rows: repeat(3, 1em); font-size: 60px; color: whitesmoke; } .two { background-color: currentColor; filter: drop-shadow(4em 0); } .two.part1 {grid-area: 1/1; border-radius: 100% 0 0 0;} .two.part2 {grid-area: 2/2; border-radius: 0 0 100% 0;} .two.part3 {grid-area: 3/1; border-radius: 100% 0 0 0;} .two.part4 {grid-area: 3/2; border-radius: 0 0 0 100%;} .zero.copy-1 {grid-area: 2/3/4/5;} .zero.copy-2 {grid-area: 2/7/4/9;} .zero { width: 0; height: 0; border: 1em solid; border-color: currentColor transparent; border-radius: 50%; transform: rotate(-45deg); animation: round 4s linear infinite; } @keyframes round { to { transform: rotate(calc(-45deg + -1turn)); } } .text.happy {grid-area: 1/2;} .text.new {grid-area: 2/4;} .text.year {grid-area: 1/6;} .text { text-transform: uppercase; font-size: 0.66em; line-height: 1.5em; font-weight: bold; font-family: cursive; padding-left: 0.25em; mix-blend-mode: difference; }