Bootstrap上有個navbar的功能,裡面提供了一個External content的功能讓我們可以將內容先隱藏起來,等到使用者點擊按鈕觸發後才會以動畫的方式拉開內容,這樣的動畫呈現是使用了Bootstrap它自己的Collapse元件,但是Collapse只提供上下的展開,並沒有左右伸縮的功能,這讓我很苦惱,因為需求是要做從左邊展開的導覽列,自己刻一個是沒有問題,但既然Bootstrap都有提供Collapse以及跟按鈕的整合了,不用一下說不過去,這篇就來看看要怎麼使用Bootstrap做出一個可以有轉換動畫做隱藏及顯示的左清單列吧。
2018-02-08: add new content: 使用transform的轉場動畫
Navbar external content
先來做個一般的隱藏內容。
新增一個隱藏內容的元素:
1 | <div class="collapse" id="navbarToggleExternalContent"> |
class
要加上collaspe
。
新增一個觸發按鈕:
1 | <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggleExternalContent"> |
data-toggle
要設為collapse
。data-target
設定選擇器,指向你要隱藏的元素(這裡是#navbarToggleExternalContent
)。
這樣我們就完成了一個簡單的隱藏/顯示內容的功能了,下面是完整的程式碼:
See the Pen bootstrap 4 simple collapse with navbar by Peter Chen (@peterhpchen) on CodePen.
Collapse
要動手前我們要先知道關於Collapse這個元件的用法,它是一個可以讓對象在動作時有慢慢展開的效果,主要是由下面三個class來控制:
collapse
: 初始化時設定的class,會將元素隱藏。collapsing
: 觸發展開/縮回時開始到完成前會有的class,這上面設定了轉換時的動畫。collapse.show
: 展開後的元素會多一個show的class,將元素顯示出來。
小小的原碼探險
我們由文件知道了上面三個類別會做的動作,從我們的需求上看,collapsing
是我們應該深入的地方,因為這裡是在處理動畫呈現的部分,現在來看Bootstrap是怎麼實作出來的,我們可以看到_transitions.scss這個檔案,把焦點聚在Collapsing
這邊:
1 | /* _transitions.scss */ |
我們可以注意到transition-property
是設定height
,所以Collapse是不會有橫向的動畫的,所以之後再覆寫時應該要改動這個設置。
上面collapsing
的樣式會看到它將height
設為0
,而transition
會在height
改變的時候動作,所以一定有個地方改變了元素的height
,接著找到了collapse.js:
1 | ... |
這邊有兩個重點:
_getDimension()
會決定要抓的是Width還是Height,如果有設定Width類別的話就會抓Width。- 展開的大小是由scrollwidth(scrollHeight)決定。
這樣就萬事具備了,接著我們來試著開發吧。
將隱藏內容由左邊展開
接著進入本篇的重點,我們想要把隱藏的內容由左邊展開。
加上width
類別讓_getDimension()
取到的是Width:
1 | <div class="collapse width" id="navbarToggleExternalContent"> |
覆寫.collapsing
:
1 | .collapsing { |
覆寫的原因說明在下面:
width
設為0
: 起始寬度設置。transition-property
設為width
: 轉換的目標變為width
。height
設為100%
: 因高度不再是轉換的目標,所以原本的height: 0
要改為原來的高度,要不然會因為長寬都是0造成在轉換期間會看不到元素的錯誤。
下面是依照上面設置後的演示:
See the Pen bootstrap 4 simple collapse with navbar(have scrollWidth Problem) by Peter Chen (@peterhpchen) on CodePen.
上面這樣成功讓隱藏內容由右邊展開了,但有兩個問題:
- 展開後的元素會擠掉其他元素。
- 在展開過程中內文的文字會依照目前的寬度折行。
第一個問題可以用position:fixed
的設置來解決,我們用Bootstrap的position-fixed
類別來實作。
1 | <div class="collapse width position-fixed" id="navbarToggleExternalContent"> |
第二個問題可以white-space
設為nowrap
來實現(參考自StackOverflow)。
解決這兩個問題後,現在會像是下面這樣。
See the Pen bootstrap 4 left navbar(have scrollWidth Problem) by Peter Chen (@peterhpchen) on CodePen.
如果觸發的話我們又會看到另一個問題,在轉換的最後會突然的顯示一節,有不平滑的感覺。
經過觀察發現scrollwidth
的長度並不是真正的長度,它並不包含right padding
,從這篇StackOverflow我們可以知道將padding
改為用margin
實作就好,因此我們將內容改為下面這樣:
1 | <div class="bg-dark py-4"> |
程式如下:
See the Pen bootstrap v4 left menu bar(not height 100%) by Peter Chen (@peterhpchen) on CodePen.
使用transform的轉場動畫
上面的例子所使用的轉場對象是width
,看到的是清單內容慢慢隱沒的效果,還有另一種是直接把內容向左推,推動的是整個區塊,我們來看兩者的效果差別:
上面的比較圖我們可以看到左邊的是我們目前使用width
做轉換的版本,可以看到它會慢慢的把內容文字從又變捲掉,而右邊會是整個區塊往左推,所以可以看到是從左邊的內容開始消失。
兩種不同的版本會因設計需求不同而被採用,現在來示範用translate
的方式實作。
首先因為bootstrap的collapse
是對長度(寬度或高度)做轉換,而translate
的效果是不需要動到長度的,因此我們先把原本設定寬度dimension
的width
類別拿掉:
1 | <div class="bg-dark collapse position-fixed" id="navbarToggleExternalContent">...</div> |
拿掉width
後,bootstrap變回抓預設的dimension
: Height
了,所以我們現在要固定高度:
1 | #navbarToggleExternalContent{ |
在固定高度後,就要來修改動畫的部分,前面有說因為collapse
是以長度為動畫依據,所以全部的預設動畫都沒有用處了,我們需要自己加上動畫。
為此我們需要定義一個class
,在show
的時候加到元素上,藉這個class
來設定開啟時候的狀態,為了達到這個目的我們用bootstrap提供的js事件來實作:
1 | const $menu = $('#navbarToggleExternalContent'); |
使用menu-show
class,在show
的時候加上,在hidden
的時候清掉,現在我們在show
的時候元素上會有menu-show
這個類別了。
最後我們來加上動畫吧,在初始的狀態下我們是要隱藏menu的,所以我們用translateX(-100%)
來隱藏清單:
1 | #navbarToggleExternalContent{ |
接著在顯示的狀態下,清單的起始位置應該要在0px
(靠左)的地方:
1 | #navbarToggleExternalContent.menu-show{ |
如此一來,我們就可以得到一個translate
的左導覽列了:
See the Pen bootstrap v4 left menu transform bar by Peter Chen (@peterhpchen) on CodePen.
結語
Bootstrap是個很易用的元件庫,我們可以用它來節省不少的時間及精力,像這次的覆寫也是因為Bootstrap本身就已經有開好入口讓我們可以輕鬆地修改,會卡住的應該就是對Transition還不太了解的人(就是我),理解CSS的Transition後就很簡單了。
備註
- 本文使用的是Bootstrap 4。