《前端每日實戰》第171號做品:用純 CSS 繪製一朵美麗的雪花

171.gif

昨夜北京下了大雪,讓咱們用 CSS 繪製一朵雪花,迎接這潔白美好的世界吧!css

1、效果預覽

按下右側的「點擊預覽」按鈕能夠在當前頁面預覽,點擊連接能夠全屏預覽。html

https://codepen.io/comehope/pen/LYEeRBb前端

2、源代碼下載

每日前端實戰系列的所有源代碼請從 github 下載:git

https://github.com/comehope/front-end-daily-challengesgithub

3、代碼解讀

定義 DOM 結構、頁面背景和容器尺寸

最外層容器是一個名爲 .snowflake<figure> 元素,內含 6 個 <div> 元素,分別表明雪花的6個花瓣,每一個 <div> 中又包含 5 個 <span> 元素,每一個 <span> 表明雪花上的冰凌。ide

<figure class="snowflake">
    <div>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
    </div>
    <div>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
    </div>
    <div>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
    </div>
    <div>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
    </div>
    <div>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
    </div>
    <div>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
    </div>
</figure>

頁面背景取黑色,雪花取白色,併爲容器畫出黃色的輪廓做爲輔助線,雪花圖案將繪製在這個黃色虛線框內:函數

body {
    margin: 0;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: black;
    overflow: hidden;
}

.snowflake {
    font-size: 100px;
    color: snow;
    width: 4em;
    height: 4em;
    outline: 1px dashed yellow;
}

效果以下圖:佈局

01.png

繪製出6個花瓣

先繪製出1個花瓣中間的豎線:flex

div {
    width: 0.1em;
    height: 2em;
    background-color: currentColor;
    border-radius: 0.05em;
}

效果以下圖:動畫

02.png

發現6個花瓣的豎線重疊在一塊兒了,把它們合併到一塊兒,看起來就像只有1條豎線:

div {

position: absolute;

}

效果以下圖:

03.png

分別旋轉每一個花瓣,一共6個花瓣,因此各花瓣的旋轉角度均相差60度:

div {
    transform-origin: bottom;
    transform: rotate(calc((var(--n)  - 1)* 60deg));
}

div:nth-child(1) {--n: 1;}
div:nth-child(2) {--n: 2;}
div:nth-child(3) {--n: 3;}
div:nth-child(4) {--n: 4;}
div:nth-child(5) {--n: 5;}
div:nth-child(6) {--n: 6;}

效果以下圖:

04.png

繪製花瓣上的冰凌

接下來修飾花瓣,繪製花瓣上的冰凌。

先來出頂端的圓點,用 <div> 裏的第1個 <span> 元素實現:

div {
    display: flex;
    flex-direction: column;
    align-items: center;
}

div span:nth-child(1) {
    width: 0.2em;
    height: 0.2em;
    background-color: currentColor;
    border-radius: 50%;
}

效果以下圖:

05.png

而後增長離圓點最近的折線,用第 2 個 <span> 元素畫出,這是用一個正方形4條邊框中的2條實現的:

div span:nth-child(2) {
    width: 0.5em;
    height: 0.5em;
    border: 0.1em solid;
    border-width: 0.1em;
    border-style: none solid solid none;
    border-radius: 0.05em;
}

效果以下圖:

06.png

把折線旋轉45度,讓它的尖部和豎線重合:

div span:nth-child(2) {
    transform: rotate(45deg);
}

效果以下圖:

07.png

增長第2條折線,和上面的代碼相似,只是正方形的邊長從 0.5em 縮短到 0.4em 了:

div span:nth-child(3) {
    width: 0.4em;
    height: 0.4em;
    border: 0.1em solid;
    border-width: 0.1em;
    border-style: none solid solid none;
    border-radius: 0.05em;
    transform: rotate(45deg);
}

效果以下圖:

08.png

再增長第3條折線:

div span:nth-child(4) {
    width: 0.3em;
    height: 0.3em;
    border: 0.1em solid;
    border-width: 0.1em;
    border-style: none solid solid none;
    border-radius: 0.05em;
    transform: rotate(45deg);
}

效果以下圖:

09.png

再增長第4條折線:

div span:nth-child(4) {
    width: 0.3em;
    height: 0.3em;
    border: 0.1em solid;
    border-width: 0.1em;
    border-style: none solid solid none;
    border-radius: 0.05em;
    transform: rotate(45deg);
}

效果以下圖:

10.png

你已經發現上面 4 條折線的代碼有不少重複的,堅定不能忍,來重構吧,把這 4 段代碼合併起來:

div span:nth-child(2),
div span:nth-child(3),
div span:nth-child(4),
div span:nth-child(5) {
    width: var(--side-length);
    height: var(--side-length);
    border: 0.1em solid;
    border-width: 0.1em;
    border-style: none solid solid none;
    border-radius: 0.05em;
    transform: rotate(45deg);
}

div span:nth-child(2) {--side-length: 0.5em;}
div span:nth-child(3) {--side-length: 0.4em;}
div span:nth-child(4) {--side-length: 0.3em;}
div span:nth-child(5) {--side-length: 0.3em;}

最後,讓第1條折線離中心稍遠點,這樣還能讓雪花中心更加漂亮:

div span:nth-child(2) {
    margin-top: -0.2em;
}

效果以下圖:

11.png

增長動畫效果

動畫效果很簡單,就是轉啊轉地,讓這片雪花用10秒時間轉一圈:

.snowflake {
    animation: round 10s linear infinite;
}

@keyframes round {
    to {
        transform: rotate(1turn);
    }
}

效果以下圖:

12.gif

最後,刪除掉輔助助線:

.snowflake {
    /* outline: 1px dashed yellow; */
}

效果以下圖:

13.gif

大功告成!

4、參考

  • flex 佈局,《CSS3 藝術》第1.8.1節
  • 邊框屬性 border,《CSS3 藝術》第3.1節
  • 變量 var() 和 表達式 calc(),《CSS3 藝術》第7.1節
  • 變換旋轉函數 rotate(),《CSS3 藝術》第8.1.2節
  • 變換原點 transform-origin,《CSS3 藝術》第8.2節
  • 動畫 animation,《CSS3 藝術》第10章
相關文章
相關標籤/搜索