首页 > 代码库 > Bootstrap Navbar应用及源码解析

Bootstrap Navbar应用及源码解析

目的:

  • 用Bootstrap Navbar component 实现一个响应式导航
  • 理解Bootstrap Navbar component是如何工作的(不包括collepse.js)
  • 清楚自己添加一个规定的类名时是做了些什么
  • 根据自己的需求进行改装
  • 对比自己的实现方法,找出差距。

1.实现:

我想要模仿一个这样的响应式导航:

技术分享

技术分享

 

按照Bootstrap官网上介绍的方法,按照规则创建标签添加类名之后,可以得到一个这样的导航:

技术分享

代码:

<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相关的代码,挑出和位置相关的:

@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-nav

默认是小屏幕,他们的状态是:

技术分享

大屏幕时,navbar-header左浮动,navbar-nav和里面的li也都左浮动,像下面这样:

技术分享

所以,他实现的原理就是,利用块级元素在文档流中占满一行,浮动之后挤到一起的特性,来控制堆叠和并排。

所以,为了可以在变成大屏幕时这两个盒子可以顺利地到一行上去,也就是说不要出现下面的情况,需要控制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:负责竖版导航的填充、实现横版导航。
.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。

这样做可以减少一些重复的不必要的代码。但是缺点远远大于优点:

①对于写的人来说,如果逻辑清晰的话,写的会很顺畅。如果思维稍微有点混乱的话,就会把自己绕进去。

②对于看的人来说,理解起来会很别扭。

③如果过段时间想改一个小样式,都需要重新理解一下当时的逻辑。

 

Bootstrap Navbar应用及源码解析