怎么用純css實現Tab切換? - css筆記

    當我們思考能否用css來實現時還應考慮到html的結構,能不能構造出滿足css已存在的選擇器的html布局,這一節和大家分享怎么用純css實現Tab切換

    css實現依賴于html結構,因為css選擇器有限,有子選擇器,沒有父選擇器,有后選擇器,沒有前選擇器,所以局限性很大。所以當我們思考能否用css來實現時還應考慮到html的結構,能不能構造出滿足css已存在的選擇器的html布局

    前言

    哪些簡單的效果可以考慮用css來實現呢,目前css能夠做的交互有

    • 鼠標經過/離開:hover
    • 鼠標點擊::cheked

    那是不是上述所有的交互都可以用css來實現呢?顯然不是的,css實現依賴于html結構,因為css選擇器有限,有子選擇器,沒有父選擇器,有后選擇器,沒有前選擇器,所以局限性很大。所以當我們思考能否用css來實現時還應考慮到html的結構,能不能構造出滿足css已存在的選擇器的html布局。

    效果展示;

    111
    222
    333

    先從html結構說起

    一般在碰到tab類型的組件時,一般會有如下的html

    <div class="tabs">
      <div class="tab-nav">
        <div class="tab-item">tab01</div>
        <div class="tab-item">tab02</div>
        <div class="tab-item">tab03</div>
      </div>
      <div class="tab-content">
        <div>111</div>
        <div>222</div>
        <div>333</div>
      </div>
    </div>

    大致就是這種布局吧,暫且稱作分離模式吧,足夠靈活,就是導航部分和內容結構分開,需要什么動畫效果都可以分別實現。

    還有一種布局,大概是這樣的

    <div class="tabs">
      <div class="tab-pane">
        <div class="tab-item">tab01</div>
        <div class="tab-content">111</div>
      </div>
      <div class="tab-pane">
        <div class="tab-item">tab01</div>
        <div class="tab-content">111</div>
      </div>
      <div class="tab-pane">
        <div class="tab-item">tab01</div>
        <div class="tab-content">111</div>
      </div>
    </div>

    這里每一個tab里面的導航和內容是一起的,我們稱為合并模式吧,這種在組件化里面很常見,比如在react里面,一個tab組件,一般會寫成這樣

    ReactDOM.render(
      <Tabs defaultActiveKey="1" onChange={callback}>
        <TabPane tab="Tab 1" key="1">Content of Tab Pane 1</TabPane>
        <TabPane tab="Tab 2" key="2">Content of Tab Pane 2</TabPane>
        <TabPane tab="Tab 3" key="3">Content of Tab Pane 3</TabPane>
      </Tabs>,
    mountNode);

    是不是很像?

    相信用js只要是一名合格的前端都能輕易的實現吧,這里我們主要是研究如何用css來實現

    第一種布局(分離模式)

    這里有兩種思路

    1. 錨點實現?herf?+?:target
    2. css3?nth-child(n)?選擇器

    錨點實現主要是在a標簽加上href屬性,然后目標元素上添加相同的id,當點擊a標簽時,目標元素的:target就生效了

    <style>
    #item01:target{ background:red }
    </style>
    <a href="#item01">跳轉</a>
    <div id="item01">內容</div>

    這種方式可以將導航和內容鏈接到一塊,但是在瀏覽器中有一個很不友好的地方,就是當點擊帶有錨點的a鏈接的時候,瀏覽器會自動定位到目標位置,很影響體驗,需要去掉這種效果估計還得借助js來實現,故不太推薦用這種方式

    nth-child(n)?選擇器,這種方式就比較傳統了,不過導航切換部分還是用到label+input[type=radio],實現基本和js是同一個思路,甚至還不如js方便,因為你有多少個tab選項就得寫多少個nth-child樣式

    .tab-nav input:nth-of-type(1):checked ~ .tab-content :nth-of-type(1),
    .tab-nav input:nth-of-type(2):checked ~ .tab-content :nth-of-type(2),
    .tab-nav input:nth-of-type(3):checked ~ .tab-content :nth-of-type(3),
    ...
    {
      z-index:1
    }

    你大概會看到這樣的樣式,如果選項卡比較固定,基本是靜態的,比較少,可以一一寫出來,如果比較多,或者是js生成的,那么建議這一部分樣式也通過js生成出來。

    下面著重來實現第二種布局

    第二種布局(合并模式)

    如果是這樣一種布局,那么導航和內容就可以通過相鄰選擇器+聯系上了,重點是如何實現選項卡的樣式,當然,我們也需要改一下html

    <div class="tabs">
      <div class="tab-pane">
        <input type="radio" name="tab" id="tab01"/>
        <label class="tab-item" for="tab01">tab01</label>
        <div class="tab-content">111</div>
      </div>
      <div class="tab-pane">
        <input type="radio" name="tab" id="tab02"/>
        <label class="tab-item" for="tab02">tab02</label>
        <div class="tab-content">222</div>
      </div>
      <div class="tab-pane">
        <input type="radio" name="tab" id="tab03"/>
        <label class="tab-item" for="tab03">tab03</label>
        <div class="tab-content">333</div>
      </div>
    </div>

    然后我們通過樣式美化一下

    .tabs{
      position:relative;
      width:400px;
      height:300px;
    }
    .tab-pane{
      display:inline-block;
    }
    .tabs input[type='radio']{
      position:absolute;
      clip:rect(0,0,0,0)
    }
    .tab-item{
      display:block;
      height:34px;
      line-height:34px;
      cursor:pointer;
      padding:0 10px
    }
    
    .tab-content{
      position:absolute;
      border:1px solid #eee;
      padding:20px;
      left:0;
      top:36px;
      bottom:0;
      right:0;
      background:#fff;
    }

    然后加入交互,主要就是相鄰選擇器+:checked選擇器,

    .tabs input[type='radio']:checked+.tab-item{/**導航選中狀態**/
      background:orangered;
      color:#fff
    }
    .tabs input[type='radio']:checked+.tab-item+.tab-content{/**當前內容切換**/
      z-index:1
    }

    我們這里只用了z-index:1就實現了隱藏顯示,當然還可以實現更多的效果,比如淡入淡出等

    演示效果見頁底Demo2

    當然,這種方式也有一定的不足,由于這里內容區域用到了絕對定位,所以整個tab容器就不能根據里層的內容來自適應,也需要給外層一個固定的高度,不然整個tab容器就只有頂部導航區域才占據空間,這明顯就不合常理。

    添加一點動畫效果

    /**給導航添加橫條的縮放效果**/
    .tab-item:after{
      position:absolute;
      content:'';
      height:3px;
      width:100%;
      background:orangered;
      left:0;
      bottom:2px;
      transition:.3s;
      transform:scaleX(0)
    }
    
    .tabs input[type='radio']:checked+.tab-item:after{
      transform:scaleX(1)
    }
    /**給內容區域添加一個淡入淡出的效果**/
    .tab-content{
      position:absolute;
      background:#eee;
      padding:20px;
      left:0;
      top:36px;
      bottom:0;
      right:0;
      transition:.3s;
      opacity:0;
      transform:translateY(50px)
    }
    
    .tabs input[type='radio']:checked+.tab-item+.tab-content{
      z-index:1;
      opacity:1;
      transform:translateY(0)
    }

    演示效果見頁底Demo3

    小節

    通過css我們也能實現導航效果,而且更容易復用,只需要復制html結構就行(當然這里肯定也是需要改一下nameid的)。這就有點類似組件的意思了,給你一個html結構,你不需要關系切換邏輯,只需要根據接口取到數據,然后塞到每個tab標簽頁里面去,事實上現在react實現的組件也一般都是這種思路,只需關注業務邏輯,但這些都是大工程,哪里有css直接來的快。

    這就讓我想到了剛進公司那會,每碰到一個tab,那就要取一個id,然后用jquery實現一遍tab切換邏輯,后來放聰明了,把tab封裝成一個插件,碰到一個tab就調用一次插件…看著代碼變少了,其實也沒什么本質區別。

    用css來實現的好處就是可以盡量大的把組件功能和業務邏輯分離開來,真正做一個UI組件該做的事,希望css越來越好

    下載權限
    查看
    • 免費下載
      評論并刷新后下載
      登錄后下載
    • {{attr.name}}:
    您當前的等級為
    登錄后免費下載登錄 小黑屋反思中,不準下載! 評論后刷新頁面下載評論 支付以后下載 請先登錄 您今天的下載次數(次)用完了,請明天再來 支付積分以后下載立即支付 支付以后下載立即支付 您當前的用戶組不允許下載升級會員
    您已獲得下載權限 您可以每天下載資源次,今日剩余
    資源

    Vuetify.js - Vue的材料組件框架

    2020-5-14 23:38:25

    教程

    簡單的贊賞引導按鈕 - wordpress美化

    2019-5-10 15:28:09

    ??
    Npcink上的部份代碼及教程來源于互聯網,僅供網友學習交流,若您喜歡本文可附上原文鏈接隨意轉載。
    無意侵害您的權益,請發送郵件至 1355471563#qq.com 或點擊右側 私信:Muze 反饋,我們將盡快處理。
    0 條回復 A文章作者 M管理員
      暫無討論,說說你的看法吧
    ?
    個人中心
    購物車
    優惠劵
    今日簽到
    有新私信 私信列表
    搜索
    主站蜘蛛池模板: 无码AV动漫精品一区二区免费| 日本高清成本人视频一区| 精品女同一区二区三区免费站| 亚洲AV无码国产一区二区三区| 国产福利电影一区二区三区久久久久成人精品综合 | 午夜爽爽性刺激一区二区视频| 日韩免费视频一区| 日本精品高清一区二区| 国产韩国精品一区二区三区久久 | 国产成人一区二区三区电影网站| 亚洲日韩AV一区二区三区中文| 一区二区在线播放视频| 精品国产AV无码一区二区三区| 91久久精品一区二区| 色妞色视频一区二区三区四区| 亚洲一区二区三区无码中文字幕| 成人区人妻精品一区二区三区 | 蜜桃视频一区二区三区在线观看| 日韩精品一区二区三区中文版 | 东京热无码av一区二区| 国产99精品一区二区三区免费| 国产精品亚洲专区一区| 色欲AV蜜桃一区二区三| 国产在线一区二区视频| 精品乱码一区内射人妻无码| 国产伦精品一区二区三区免.费| 在线观看国产一区亚洲bd| 视频在线一区二区三区| 国产成人高清视频一区二区 | 国产色欲AV一区二区三区| 亚洲国产精品成人一区| 一区二区三区国产精品| 亚洲熟女乱色一区二区三区| 国产一区视频在线免费观看| 中文字幕日本精品一区二区三区| 精品国产一区二区三区久久 | 一区二区三区免费精品视频| 亚洲综合av永久无码精品一区二区 | 亚洲精品无码一区二区| 精品无码一区在线观看| 亚洲韩国精品无码一区二区三区 |