目的:html
1.實現:web
我想要模仿一個這樣的響應式導航:佈局
按照Bootstrap官網上介紹的方法,按照規則建立標籤添加類名以後,能夠獲得一個這樣的導航:ui
代碼:spa
<nav class="navbar navbar-default"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand">Live With It</a> </div> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav navbar-right"> <li class="active"><a href="#">Home</a></li> <li><a href="#">Portfolio</a></li> <li><a href="#">Contact</a></li> </ul> </div> </div> </nav>
2.實現原理:設計
從他的源碼中扒出和nav navbar相關的代碼,挑出和位置相關的:3d
@media (min-width: 768px) { .navbar-header { float: left; } } .navbar-brand { float: left; } @media (min-width: 768px) { .navbar-nav { float: left; } .navbar-nav > li { float: left; } }
兩個關鍵的盒子,navbar-header和navbar-navcode
默認是小屏幕,他們的狀態是:component
大屏幕時,navbar-header左浮動,navbar-nav和裏面的li也都左浮動,像下面這樣:htm
因此,他實現的原理就是,利用塊級元素在文檔流中佔滿一行,浮動以後擠到一塊兒的特性,來控制堆疊和並排。
因此,爲了能夠在變成大屏幕時這兩個盒子能夠順利地到一行上去,也就是說不要出現下面的狀況,須要控制navbar-header和navbar-nav裏面元素的總寬度不要超過768px。
再挑出和隱藏於出現相關的樣式:
@media (min-width: 768px) { .navbar-toggle { display: none; } } .collapse { display: none; } @media (min-width: 768px) { .navbar-collapse.collapse { display: block !important; height: auto !important; overflow: visible !important; } }
navbar-collapse是控制導航列表隱藏和出現的盒子,按鈕會在變成大屏後消失。
3.弄清楚每一個類名添加的樣式
.navbar 負責定義一個長條
.navbar { position: relative; min-height: 50px; margin-bottom: 20px; border: 1px solid transparent; } @media (min-width: 768px) { .navbar { border-radius: 4px; } }
.navbar-header ,負責包裹brand和摺疊按鈕,控制小屏幕時brand和按鈕的位置,控制導航列表的佈局。
@media (min-width: 768px) { .navbar-header { float: left; } } .container > .navbar-header, .container-fluid > .navbar-header { margin-right: -15px; //小屏幕的時候header內容左邊緣和container左邊緣對齊 margin-left: -15px; } @media (min-width: 768px) { .container > .navbar-header, .container-fluid > .navbar-header { margin-right: 0; margin-left: 0; } }
.navbar-brand, 負責左邊logo區的默認樣式
.navbar-brand { float: left; height: 50px; padding: 15px 15px; font-size: 18px; line-height: 20px; } .navbar-brand:hover, .navbar-brand:focus { text-decoration: none; } .navbar-brand > img { display: block; } @media (min-width: 768px) { .navbar > .container .navbar-brand, .navbar > .container-fluid .navbar-brand { margin-left: -15px; /*大屏幕的時候內容左邊緣和header左邊緣對齊*/ } }
container和navbar-brand都在左右兩邊設置了15px的內填充,因此container、header、brand三個盒子左邊線本該是這樣的:
小屏幕的時候,header左右兩邊各有一個負邊距,因此是這樣的狀態:
大屏幕的時候,brand左邊有一個負邊距:
.nav 負責定義成垂直導航的樣式
.nav { padding-left: 0; margin-bottom: 0; list-style: none; } .nav > li { position: relative; display: block; } .nav > li > a { position: relative; display: block; padding: 10px 15px; } .nav > li > a:hover, .nav > li > a:focus { text-decoration: none; background-color: #eee; }
.navbar-nav { margin: 7.5px -15px; /*摺疊以後添加一個上下邊距,每一行都和屏幕等寬*/ } .navbar-nav > li > a { padding-top: 10px; padding-bottom: 10px; line-height: 20px; } @media (min-width: 768px) { .navbar-nav { float: left; margin: 0; } .navbar-nav > li { float: left; } .navbar-nav > li > a { padding-top: 15px; padding-bottom: 15px; } }
navbar-right,navbar-left :負責定位
@media (min-width: 768px) { .navbar-left { float: left !important; } .navbar-right { float: right !important; margin-right: -15px; //第一個添加navbar-right的元素右邊會有一個負邊距 } .navbar-right ~ .navbar-right { //以後的都不會有 margin-right: 0; } }
navbar-toggle:負責定義按鈕的樣式,裏面用三個盒子繪製三條線。在大屏幕時消失。
.navbar-toggle { position: relative; float: right; padding: 9px 10px; margin-top: 8px; margin-right: 15px; margin-bottom: 8px; background-color: transparent; background-image: none; border: 1px solid transparent; border-radius: 4px; } .navbar-toggle:focus { outline: 0; } @media (min-width: 768px) { .navbar-toggle { display: none; } } .navbar-toggle .icon-bar { display: block; width: 22px; height: 2px; border-radius: 1px; } .navbar-toggle .icon-bar + .icon-bar { margin-top: 4px; }
collapse,負責控制顯示和隱藏
.collapse { display: none; } @media (min-width: 768px) { .navbar-collapse.collapse { display: block !important; height: auto !important; padding-bottom: 0; overflow: visible !important; } }
.navbar-collapse: 負責被摺疊盒子的樣式
.navbar-collapse { padding-right: 15px; padding-left: 15px; overflow-x: visible; -webkit-overflow-scrolling: touch; border-top: 1px solid transparent; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); } .container > .navbar-collapse, .container-fluid > .navbar-collapse { margin-right: -15px; margin-left: -15px; } @media (min-width: 768px) { .navbar-collapse { width: auto; border-top: 0; -webkit-box-shadow: none; box-shadow: none; } } @media (min-width: 768px) { .container > .navbar-collapse, .container-fluid > .navbar-collapse { margin-right: 0; margin-left: 0; } }
以上這些類負責的樣式是除了顏色以外的樣式,與顏色相關的一切都由.navbar-default負責。
4.改裝
如今的導航條是這個樣子的:
和我想要的還有一些差別,不過知道了它的實現方式,就能夠進行想要的改動。
首先讓小屏幕的時候導航列表也是水平顯示,而且與屏幕兩邊有必定距離:
.navbar-nav { text-align:center; } .nav li { display:inline-block; } .navbar { border: 0; } .navbar .navbar-header { padding-top:10px; padding-bottom:10px; } @media(min-width:768px){ .navbar-collapse { padding-top:10px; padding-bottom:10px; } } .navbar-brand { font-size: 34px; font-family: Lobster, Monospace; } .nav { font-size: 20px; } @media(max-width:768px){ .container .navbar-collapse { margin-left: 12px; margin-right: 12px; } }
(若是之後也會用到這種版式,也能夠爲他定義一個類)
而後定義一個新的配色方案,替換掉.navbar-default
@media(min-width:768px){ .navbar { background-color: #F79C9C; } } .navbar-girl .navbar-header, .navbar-girl .navbar-collapse { background-color: #F79C9C; } .navbar-girl .navbar-brand { color: #FFF; } .navbar-girl .navbar-text { color: #F7846B; } .navbar-girl .navbar-nav > li > a { color: #F7846B; } .navbar-girl .navbar-nav > li > a:hover, .navbar-girl .navbar-nav > li > a:focus { color: #CEE6E6; background-color: transparent; } .navbar-girl .navbar-nav > .active > a, .navbar-girl .navbar-nav > .active > a:hover, .navbar-girl .navbar-nav > .active > a:focus { color: #F7846B; background-color: #FFF; } .navbar-girl .navbar-toggle { border-color: #FFF; } .navbar-girl .navbar-toggle:hover, .navbar-girl .navbar-toggle:focus { background-color: #CEE6E6; } .navbar-girl .navbar-toggle .icon-bar { background-color: #FFF; } .navbar-girl .navbar-collapse { border-color: #FFF; }
大功告成啦。
5.反思
以前用本身的思路實現了一個響應式導航:CSS3media queries+jQuery實現響應式導航
和Bootstrap的思想對比以後,發現本身的一些問題
①定位:
個人思路是經過position:absolute來控制導航列表的位置。這樣有一個明顯的缺點,導航列表已經徹底脫離普通流。
我這樣思考的根源是,我沒有抓住這個變化的本質,當我看到兩個相同的東西在不一樣狀況下出如今不一樣地方的時候,(也就是從一個地方換到另外一個地方),我首先想到的就是直接挪過去,即利用absolute定位。
而Bootstrap看到了這個變化的本質,讓一些塊級元素由堆疊排列變成水平排列(或者相反),這樣的變化經過利用塊級元素的特色和浮動就能夠實現。
②出發點:
Bootstrap的中心思想是:mobile first,先把在小屏幕上的佈局實現,而後再作一些改變來實如今大屏幕上的佈局。
而個人思想是:每個佈局和樣式都考慮到這兩種狀況,對比一下看哪一種狀況方便就用哪一個。因此個人代碼中會出現@media(min-width:768px)和@media(max-width:768px)兩種條件,對於一個設計我可能默認大屏幕的,小屏幕的用media,另外一個設計我可能就會默認小屏幕的,大屏幕的用media。
這樣作能夠減小一些重複的沒必要要的代碼。可是缺點遠遠大於優勢:
①對於寫的人來講,若是邏輯清晰的話,寫的會很順暢。若是思惟稍微有點混亂的話,就會把本身繞進去。
②對於看的人來講,理解起來會很彆扭。
③若是過段時間想改一個小樣式,都須要從新理解一下當時的邏輯。