CSS 搞事技巧:checkbox+label+selector

shanyuhai123發表於2019-04-01

介紹

其實這篇文章寫到一大半時它的名字還叫做 《重溫 Flex 佈局》,結果寫著寫著就走了心,附上一圖表示心情吧:

CSS 搞事技巧:checkbox+label+selector

其實我並不是一個喜歡搞事的人,真的,從我遊戲:屠夫沉默(DOTA2),蓋倫(LOL),亞瑟(農藥)的英雄池完全可以看出來。

這三個元素作為這個 《CSS 搞事技巧》的第一篇並非僅僅是在接下來的 《重溫 Flex 佈局》中要使用,而是因為這個技巧的確是很基礎。

核心概念:所謂技巧,無非就是儲存狀態(劃重點啦)。

示例

示例部分僅放 Gif 圖樣及原始碼地址,詳情請檢視技巧說明部分(技巧是通用的)。

1. switch 開關

樣式模仿的是 Vuetify 的 Switches

Gif 預覽:

CSS 搞事技巧:checkbox+label+selector

動畫原始碼線上動畫

2. 關燈效果

上面實現了開關,那麼一個簡單的聯想當然是開關燈啦。

Gif 預覽:

CSS 搞事技巧:checkbox+label+selector

動畫原始碼線上動畫

技巧說明

在 JavaScript 中,我們可以利用變數,DOM 來儲存狀態,而 CSS 當中,我們也可以利用偽類選擇器來儲存狀態,這就是 CSS 搞事的核心了,也是上面示例實現的本質。

回到主題,也就是 Flex 佈局來,我們初步回顧一下,Flex 佈局的相關概念,首先被宣告瞭 Flex 彈性佈局的元素叫做彈性容器,其子元素被稱為彈性專案。這個彈性容器中預設存在兩個軸,一個叫做主軸(main axis),側軸(cross axis)。整個 Flex 容器具有六個屬性,此次僅介紹兩個:justify-contentalign-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 // 雪白
複製程式碼

測試繫結情況:

CSS 搞事技巧:checkbox+label+selector

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 搞事技巧:checkbox+label+selector

這樣就大功告成啦,線上檢視

最後

CSS 的美麗是有多個屬性組合而成。切記要和設計師搞好關係,不然你這些屬性都會了,做出來的東西還是會很難看的……

預告:《重溫 Flex 佈局》正在路上。

連結:《重溫 Flex 佈局

相關連結:

  1. CSS 搞事技巧:hover+active

參考資料

  1. Vuetify
  2. 配色方案:中國色
  3. MDN

相關文章