其實這篇文章寫到一大半時它的名字還叫作 《重溫 Flex 佈局》,結果寫着寫着就走了心,附上一圖表示心情吧:css
其實我並非一個喜歡搞事的人,真的,從我遊戲:屠夫沉默(DOTA2),蓋倫(LOL),亞瑟(農藥)的英雄池徹底能夠看出來。
這三個元素做爲這個 《CSS 搞事技巧》的第一篇並不是僅僅是在接下來的 《重溫 Flex 佈局》中要使用,而是由於這個技巧的確是很基礎。html
核心概念:所謂技巧,無非就是保存狀態(劃重點啦)。vue
示例部分僅放 Gif 圖樣及源碼地址,詳情請查看技巧說明部分(技巧是通用的)。git
樣式模仿的是 Vuetify 的 Switches 。github
Gif 預覽:ide
上面實現了開關,那麼一個簡單的聯想固然是開關燈啦。測試
Gif 預覽:flex
在 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 的問題;該效果參考 來源 。
功能欄與展現欄分列兩側,首先是完成 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>
接着須要一堆 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
要想生效的話,還須要將 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 // 雪白
測試綁定狀況:
首先在其中添加三個元素,幫助咱們觀察效果:
<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 佈局》正在路上。