介紹
其實這篇文章寫到一大半時它的名字還叫做 《重溫 Flex 佈局》,結果寫著寫著就走了心,附上一圖表示心情吧:
其實我並不是一個喜歡搞事的人,真的,從我遊戲:屠夫沉默(DOTA2),蓋倫(LOL),亞瑟(農藥)的英雄池完全可以看出來。
這三個元素作為這個 《CSS 搞事技巧》的第一篇並非僅僅是在接下來的 《重溫 Flex 佈局》中要使用,而是因為這個技巧的確是很基礎。
核心概念:所謂技巧,無非就是儲存狀態(劃重點啦)。
示例
示例部分僅放 Gif 圖樣及原始碼地址,詳情請檢視技巧說明部分(技巧是通用的)。
1. switch 開關
樣式模仿的是 Vuetify 的 Switches 。
Gif 預覽:
2. 關燈效果
上面實現了開關,那麼一個簡單的聯想當然是開關燈啦。
Gif 預覽:
技巧說明
在 JavaScript 中,我們可以利用變數,DOM 來儲存狀態,而 CSS 當中,我們也可以利用偽類選擇器來儲存狀態,這就是 CSS 搞事的核心了,也是上面示例實現的本質。
回到主題,也就是 Flex 佈局來,我們初步回顧一下,Flex 佈局的相關概念,首先被宣告瞭 Flex 彈性佈局的元素叫做彈性容器,其子元素被稱為彈性專案。這個彈性容器中預設存在兩個軸,一個叫做主軸(main axis),側軸(cross axis)。整個 Flex 容器具有六個屬性,此次僅介紹兩個:justify-content
和 align-items
(提一下 align-content
是多行的概念)。
列出這個兩個屬性的常用值(看 MDN 可知已經增加了更多的值):
.flex {
justify-content: flex-start | flex-end | center | space-between | space-around;
align-items: flex-start | flex-end | center;
}
複製程式碼
程式碼解讀
該專案是通過 VuePress 來渲染的,所以會使用到 Vue 的語法,不過此處僅使用 Vue 的 for
迴圈來解決重複書寫 DOM 的問題;該效果參考 來源 。
1. label
功能欄與展示欄分列兩側,首先是完成 DOM 結構:
flex__feats
為左側功能欄,flex__exh
為展示欄。
<div class="flex">
<section class="flex__feats">
<div class="feat__list">
<h4 class="feat__list_title">justify</h4>
<div class="feat__list_labels">
<label>flex-start</label>
<label>flex-end</label>
<label>center</label>
<label>space-between</label>
<label>space-around</label>
</div>
</div>
<div class="feat__list">
<h4 class="feat__list_title">align</h4>
<div class="feat__list_labels">
<label>flex-start</label>
<label>flex-end</label>
<label>center</label>
</div>
</div>
</section>
<div class="divider"></div>
<section class="flex__exh"></section>
</div>
複製程式碼
接著使用 Flex 佈局來將它們分割,因為這次主要將的不是 Flex,所以就不進行闡述了。
<style lang="stylus" scoped>
.flex
width 100%
height 100%
display flex
*
box-sizing border-box
&__feats
flex-basis 28%
height 100%
display flex
justify-content space-around
.feat__list
display flex
flex-direction column
justify-content flex-start
align-items center
.feat__list_labels
flex-grow 1
display flex
flex-direction column
justify-content space-around
align-items center
.divider
width 1px
height 100%
margin 0 2px
background-color #000;
</style>
複製程式碼
可以注意到功能欄的 DOM 結構是重複的,使用 Vue 來簡化一下吧:
<section class="flex__feats">
<div class="feat__list" v-for="(feat, index) in feats()" :key="index">
<h4 class="feat__list_title">{{feat.title}}</h4>
<div class="feat__list_labels">
<label v-for="(item, index) in feat.list" :key="index">{{item}}</label>
</div>
</div>
</section>
<script>
export default {
data() {
return {
bgColor: "#c0c4c3", // 月影白
feats: () => {
return [
{title: "jusitify", list: ["flex-start", "flex-end", "center", "space-between", "space-around"]},
{title: "align", list: ["flex-start", "flex-end", "center"]}
]
}
};
}
};
</script>
複製程式碼
2. checkbox
接著需要一堆 checkbox 來觸發狀態,因為 DOM 解析是深度優先,CSS 中也沒有父選擇器這一說,雖然有一定的辦法 hack 一下,所以這一堆 checkbox 就需要放在頂部:
<div class="flex">
<input type="checkbox" class="toggle" v-for="(checkbox, index) in checkboxs()" :id="checkbox">
</div>
複製程式碼
接著需要將其隱藏:
.toggle[type="checkbox"]
width 0
height 0
filter opacity(0)
opacity 0
display none
複製程式碼
3. selector
要想生效的話,還需要將 input 的 id 繫結到 label 上:
<label v-for="(item, index) in feat.list" :key="index" :for="`${feat.title}-${item}`">{{item}}</label>
複製程式碼
接著利用 selector(選擇器),獲取到 label 並改變其顏色證明它是被選召的孩子,舉個例子(完整版):
#jusitify-flex-start:checked ~ .flex__feats .jusitify-flex-start
padding 4px 4px
background-color #5a191b // 慄紫
color #fffef9 // 雪白
複製程式碼
測試繫結情況:
4. 右側展示
首先在其中新增三個元素,幫助我們觀察效果:
<section class="flex__exh">
<div class="exh__item" v-for="n in 3" :key="n"></div>
</section>
複製程式碼
&__exh
flex-grow 1
padding 16px
.exh__item
width 15%
height 15%
box-shadow 0 0 4px rgba(0, 0, 0, .5)
&:nth-child(1)
width 18%
height 20%
&:nth-child(2)
width 14%
height 18%
&:nth-child(3)
width 15%
height 15%
複製程式碼
接著繼續使用 selector 來完成最後的任務,示例(完整版):
#jusitify-flex-start:checked ~ .flex__exh
display flex
justify-content flex-start
複製程式碼
這樣就大功告成啦,線上檢視 。
最後
CSS 的美麗是有多個屬性組合而成。切記要和設計師搞好關係,不然你這些屬性都會了,做出來的東西還是會很難看的……
預告:《重溫 Flex 佈局》正在路上。
連結:《重溫 Flex 佈局》
相關連結: