三分鐘,純 CSS 實現一個 tabs 組件
作者:程序員Sunday
tabs? 組件是在日常開發中的常見組件,很多同學表示:組件庫的 tabs 不好看,自己實現又不知道怎么去做。所以說,今天,咱們就花上幾分鐘的時間,通過純 css? 的方式來實現一個 tabs? 組件,以幫助大家完成自定義 tabs 組件的邏輯。
Hello,大家好,我是 Sunday。
tabs 組件是在日常開發中的常見組件,很多同學表示:組件庫的 tabs 不好看,自己實現又不知道怎么去做。
所以說,今天,咱們就花上幾分鐘的時間,通過純 css 的方式來實現一個 tabs 組件,以幫助大家完成自定義 tabs 組件的邏輯。
最終效果圖
html 部分
先上代碼:
<div class="container">
<div class="tabs">
<input type="radio" id="radio-1" name="tabs" checked="" />
<label class="tab" for="radio-1">
首頁
<span class="notification">2</span>
</label>
<input type="radio" id="radio-2" name="tabs" />
<label class="tab" for="radio-2">分類</label>
<input type="radio" id="radio-3" name="tabs" />
<label class="tab" for="radio-3">我的</label>
<span class="glider"></span>
</div>
</div>
這里需要 注意:在 html 部分需要設計成 input + label 的形式,而不能使用 div 的方案。
核心原因有兩點:
- input[type='radio'] 元素天生就具有 互斥性,即只能選中一個。這使得在實現多選一的標簽頁功能時非常簡便和自然,無需手動管理狀態。
- 當選擇某個標簽頁時,其對應的 radio 按鈕會被選中,而 CSS 可以通過 :checked 偽類來捕捉這一狀態的變化,從而觸發樣式變化,比如滑塊的移動、文本顏色的變化等。
整個 HTML 結構設計邏輯如下:
- container:最外層容器,用于包裹整個標簽頁組件。
- tabs:用于包含標簽頁的所有內容,包括input、label和glider滑塊。
- input[type='radio']:作為標簽頁的控制器,決定哪個標簽頁被選中。每個標簽頁對應一個radio按鈕,三個input元素的id和label元素的for屬性配對,使得點擊label可以選擇對應的radio按鈕。
- label.tab:每個標簽頁的實際顯示部分,包括文字和可選的通知標記notification。
- glider:滑塊,用于在標簽頁切換時移動,表示當前選擇的標簽頁。
CSS樣式
body {
padding: 300px;
}
.tabs {
width: 152px;
display: flex;
position: relative;
background-color: #fff;
box-shadow: 0 0 1px 0 rgba(24, 94, 224, 0.15), 0 6px 12px 0 rgba(24, 94, 224, 0.15);
padding: 12px;
border-radius: 99px;
}
- body:在body中添加了padding,使頁面內容離頂部和邊界有一定的距離,便于演示。
- tabs:設置了tabs容器的寬度(152px),使用flex布局,子元素排列在一行。容器具有一定的陰影效果和圓角,使其更具層次感。
.tabs * {
z-index: 2;
}
- 將tabs內部的所有元素的z-index設置為2,確保這些元素位于滑塊(glider)之上。
.container input[type='radio'] {
display: none;
}
- 隱藏radio按鈕,只保留它們的功能,不顯示在頁面上。
.tab {
display: flex;
align-items: center;
justify-content: center;
height: 30px;
width: 50px;
font-size: 14px;
color: black;
font-weight: 500;
border-radius: 99px;
cursor: pointer;
transition: color 0.15s ease-in;
}
- 每個標簽頁label.tab設置了固定的大小,字體樣式和顏色。使用flex布局使文本居中,邊角圓滑,鼠標懸停時呈現為點擊手勢。使用transition實現顏色過渡效果。
.notification {
display: flex;
align-items: center;
justify-content: center;
width: 14px;
height: 14px;
position: absolute;
top: 10px;
left: 30%;
font-size: 10px;
margin-left: 10px;
border-radius: 50%;
background-color: #e6eef9;
transition: 0.15s ease-in;
}
- notification是標簽頁上的小圓點,用于顯示通知數量。設置了大小、位置、字體大小和顏色。transition使背景色和位置的變化更為平滑。
.container input[type='radio']:checked + label {
color: #185ee0;
}
.container input[type='radio']:checked + label > .notification {
background-color: #185ee0;
color: #fff;
margin: 0px;
}
- 當radio按鈕被選中時,相應的label顏色變為藍色,通知標記的背景色和文本顏色也會改變。
.container input[id='radio-1']:checked ~ .glider {
transform: translateX(0);
}
.container input[id='radio-2']:checked ~ .glider {
transform: translateX(100%);
}
.container input[id='radio-3']:checked ~ .glider {
transform: translateX(200%);
}
- 通過CSS選擇器,當某個radio按鈕被選中時,glider滑塊將根據不同的radio按鈕移動相應的距離,translateX是基于父容器的寬度(這里是152px)。
.glider {
position: absolute;
display: flex;
height: 30px;
width: 50px;
background-color: #e6eef9;
z-index: 1;
border-radius: 99px;
transition: 0.25s ease-out;
}
- glider的樣式定義了滑塊的大小、位置和顏色,設置為absolute以便在容器內自由移動,transition使其移動平滑。
責任編輯:武曉燕
來源:
程序員Sunday