咱們今天用css來實現一個常見的tab切換效果css
查看原文能夠有更好的排版效果哦html
先看效果前端
https://codepen.io/xboxyan/pe...react
哪些簡單的效果能夠考慮用css來實現呢,目前css可以作的交互有jquery
hover
:cheked
那是否是上述全部的交互均可以用css來實現呢?顯然不是的,css實現依賴於html結構,由於css選擇器有限,有子選擇器,沒有父選擇器,有後選擇器,沒有前選擇器,因此侷限性很大。因此當咱們思考可否用css來實現時還應考慮到html的結構,能不能構造出知足css已存在的選擇器的html佈局。css3
通常在碰到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來實現
這裏有兩種思路
herf
+ :target
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
就實現了隱藏顯示,固然還能夠實現更多的效果,好比淡入淡出等
下面是演示效果
https://codepen.io/xboxyan/pe...
固然,這種方式也有必定的不足,因爲這裏內容區域用到了絕對定位,因此整個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) }
https://codepen.io/xboxyan/pe...
經過css咱們也能實現導航效果,並且更容易複用,只須要複製html結構就行(固然這裏確定也是須要改一下name
和id
的)。這就有點相似組件的意思了,給你一個html結構,你不須要關係切換邏輯,只須要根據接口取到數據,而後塞到每一個tab標籤頁裏面去,事實上如今react
實現的組件也通常都是這種思路,只需關注業務邏輯,但這些都是大工程,哪裏有css直接來的快。
這就讓我想到了剛進公司那會,每碰到一個tab,那就要取一個id
,而後用jquery
實現一遍tab切換邏輯,後來放聰明瞭,把tab封裝成一個插件,碰到一個tab就調用一次插件...看着代碼變少了,其實也沒什麼本質區別。
用css來實現的好處就是能夠儘可能大的把組件功能和業務邏輯分離開來,真正作一個UI組件
該作的事,但願css愈來愈好