CSS 關於多級菜單的內邊距的處理方式

clipboard.png

原文地址,排版效果更好css

https://blog.codelabo.cn/article/5ce4f0eb8aab210ff34d0150html

https://xboxyan.codelabo.cn/post/css-tree-padding/前端

在平時的項目中會常常碰到這樣一種佈局,暫且稱之爲多級菜單吧wordpress

clipboard.png

(截圖來自於ant-design佈局

這類佈局也很容易,大概就是這樣ulli嵌套,以下post

<ul class="parent">
    <li>
        <div>Navigation01</div>
        <ul>
            <li><div>Option01</div></li>
            <li><div>Option02</div></li>
            <li>
                <div>Submenu</div>
                <ul>
                    <li><div>Option03</div></li>
                    <li><div>Option04</div></li>
                </ul>
            </li>
        </ul>
    </li>
    <li><div>Navigation02</div></li>
</ul>

因而就獲得下面一個很原始的樣式。學習

clipboard.png

再通過簡單的修飾就能夠達到上面的效果了。優化

固然,這個很容易,通常狀況下咱們是經過設置內邊距來完成的,好比默認爲spa

ul{
    padding-left:40px;
}

而後每一層級跟隨父級逐步累積,而後就實現了,層級越深,距離左邊的縮進越多的效果。設計

多級菜單選中範圍

經過上面的佈局和樣式,很顯然每一項的選擇範圍都是逐步縮進的,

clipboard.png

可是,可能設計師以爲很差看,每每會設計成通欄的形式,好比像上面ant-design的設計

clipboard.png

那麼,該如何處理呢?

通欄的處理方式

首先,一個很天然的思路就是去除ulpadding,改成每個子項分別指定padding

ul.parent{
    padding: 0;
}

而後將內邊距直接寫在html上,以下

<ul  class="parent">
    <li>
        <div style="padding-left:40px">Navigation01</div>
        <ul>
            <li><div style="padding-left:80px">Option01</div></li>
            <li><div style="padding-left:80px">Option02</div></li>
            <li>
                <div style="padding-left:80px">Submenu</div>
                <ul>
                    <li><div style="padding-left:120px">Option03</div></li>
                    <li><div style="padding-left:120px">Option04</div></li>
                </ul>
            </li>
        </ul>
    </li>
    <li><div style="padding-left:40px">Navigation02</div></li>
</ul>

若是菜單層級較多,咱們一般使用js來輔助生成,注意每一次循環來指定不一樣的內邊距就能夠了

clipboard.png

ant-design也是採起這種方式,能夠自行打開控制檯去查看。

記得剛入前端的時候就是採起的這種方式,效果實現就好。

不過,在如今看來,在html中使用內聯樣式始終不雅,並且數量較多時還須要和js扯上關係,可否優化一下呢

下面列舉兩種css方式

1.子選擇器

咱們能夠在上面的基礎上,分別控制每一級的內邊距,這裏咱們可使用子選擇器>

ul.parent>li>div{/**第一級**/
    padding-left: 40px;
}
ul.parent>li>ul>li>div{/**第二級**/
    padding-left: 80px;
}
ul.parent>li>ul>li>ul>li>div{/**第三級**/
    padding-left: 120px;
}
/** ... **/

一般,在層級不是特別多的狀況下,咱們能夠一一羅列出來,只需用選擇器ul>li疊加便可,是否是比style方便維護了不少呢?

2.absolute半依賴定位

在講這個方法以前,首先搞清楚一個問題

absolute在不設置方向屬性lefttoprightbottom時,默認位置是哪裏?

在個人學習過程當中,不少地方講到的都是說absolute是絕對定位,是相對於第一個有定位屬性的父級的,因此基本上都是和relative一塊兒使用,反正無論三七二十一,直接就給父級加上position:relative,有一個可靠的父級,看着比較靠譜,不是嗎?

其實,當元素設置了absolute屬性,沒有方向屬性時,元素仍保留在原來位置,只是不佔空間而已

好比,我給上面每一項後面加一個角標

ul.parent div:after{
    content:'new';
    font-size: 10px;
    position:absolute;
    margin-top: -5px;
    color: red
}

clipboard.png

能夠看到,雖然設置了absolute屬性,但元素仍保留在原來位置,一旦設置了left等方位屬性,就會查找第一個有定位屬性的父級。

如今,咱們把css還原爲默認的狀態,也就是

ul{
    padding-left:40px;
}

如今狀況就和初始狀態一致,選中範圍逐層遞減,那麼,如何實現選中範圍爲通欄呢

咱們能夠給最外層父級設置position:relative,由於通欄的寬度是相對於最外層的,而後給選中元素設置

ul.parent div:hover:before{
    content:'';
    position:absolute;
    left:0;
    right:0;
    height:21px;
    background: violet;
    z-index: -1;
}

clipboard.png

這裏只設置了水平方向的leftright,沒有設置垂直方向上的屬性,因此水平位置會跟隨父級定位元素(這裏是最外層),而垂直方向位置仍是基於當前父級(這裏是父級li元素)

注意,這裏的高度因爲是基於最外層元素,因此,這裏不能設置height:100%,那麼,如何解決這一個小瑕疵呢,畢竟在這裏寫一個固定高度實在不怎麼合適。

這裏有兩種方式來優化。

方式一

上面的方式若是不指定高度,因爲沒有內容,高度天然爲0,解決方式也很簡單,在content插入一個空字符或者透明字符便可

ul.parent div:hover:before{
    content:'\A0';
}

或者

ul.parent div:hover:before{
    content:'任意字符';
        color:transparent;
}

方式二

一般子項目的高度都是固定的,能夠給子項目手動指定一個高度,而後選中項繼承該高度便可

ul.parent div{
    height:24px;
    line-height:24px;
}
ul.parent div:hover:before{
    content:'';
        height:inherit
}

注意這裏的height:inherit是繼承直接父級的高度,有興趣的能夠看張鑫旭的這篇文章

這樣也實現了通欄的效果

https://codepen.io/xboxyan/pe...

小節

上面介紹了兩種實現通欄的方法,相比而言,absolute效果更好,也易於維護,可能一個並不怎麼起眼的屬性,有時候也能發揮出意想不到的效果。

下面有一個案例,純css實現,能夠查看一下

clipboard.png

https://codepen.io/xboxyan/pe...

相關文章
相關標籤/搜索