ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 5.1 添加一些结构 本书介绍 Web 开发而不是 Web 设计,不过在一个看起来很简陋的应用中开发会让人提不起劲,所以本节要向布局中添加一些结构,再加入一些 CSS 实现基本的样式。除了使用自定义的 CSS 之外,我们还会使用由 Twitter 开发的开源 Web 设计框架 [Bootstrap](http://getbootstrap.com/)。我们会按照一定的方式组织代码——当布局文件中的内容变多以后,使用局部视图清理。 开发 Web 应用时,尽早对用户界面有个统筹安排往往会对你有所帮助。在本书后续内容中,我会经常使用网页构思图(mockup)(在 Web 领域经常称之为“线框图”),展示应用最终外观的草图。[[2](#fn-2)]本章大部分内容都在开发 [3.2 节](chapter3.html#static-pages)编写的静态页面,我们要在页面中加入一个网站 LOGO、导航条和网站底部。这些页面中最重要的是“首页”,它的构思图如[图 5.1](#fig-home-page-mockup) 所示,[图 5.7](#fig-site-with-footer) 是最终实现的效果。你会发现二者之间的某些细节有所不同,例如,在最终实现的页面中我们加入了一个 Rails LOGO——这没什么关系,因为构思图没必要画出每个细节。 ![home page mockup 3rd edition](https://box.kancloud.cn/2016-05-11_5732bd0288306.png)图 5.1:演示应用首页的构思图 和之前一样,如果使用 Git 做版本控制,现在最好创建一个新分支: ``` $ git checkout master $ git checkout -b filling-in-layout ``` ## 5.1.1 网站导航 在应用中添加链接和样式之前,我们先来修改网站的布局文件 `application.html.erb`(上一次见到是在[代码清单 4.3](chapter4.html#listing-application-layout-full-title) 中),添加一些 HTML 结构。我们要添加一些区域,一些 CSS 类,以及导航条。布局文件的完整内容参见[代码清单 5.1](#listing-layout-new-structure), 对各部分的说明紧跟其后。如果你迫不及待想看到结果,请看[图 5.2](#fig-layout-no-logo-or-custom-css)。(注意:结果(还)不是很让人满意。) ##### 代码清单 5.1:添加一些结构后的网站布局文件 app/views/layouts/application.html.erb ``` <!DOCTYPE html> <html> <head> <title><%= full_title(yield(:title)) %></title> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> <%= csrf_meta_tags %> <!--[if lt IE 9]> <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js"> </script> <![endif]--> </head> <body> <header class="navbar navbar-fixed-top navbar-inverse"> <div class="container"> <%= link_to "sample app", '#', id: "logo" %> <nav> <ul class="nav navbar-nav navbar-right"> <li><%= link_to "Home", '#' %></li> <li><%= link_to "Help", '#' %></li> <li><%= link_to "Log in", '#' %></li> </ul> </nav> </div> </header> <div class="container"> <%= yield %> </div> </body> </html> ``` 我们从上往下看一下这段代码中新添加的元素。[3.4.1 节](chapter3.html#testing-titles)简单介绍过,Rails 默认使用 HTML5(如 `&lt;!DOCTYPE html&gt;` 所示)。因为 HTML5 标准还很新,有些浏览器(特别是旧版 IE 浏览器)还没有完全支持,所以我们加载了一些 JavaScript 代码(称作“[HTML5 shim](https://github.com/aFarkas/html5shiv)”)来解决这个问题: ``` <!--[if lt IE 9]> <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js"> </script> <![endif]--> ``` 如下有点古怪的句法 ``` <!--[if lt IE 9]> ``` 只有当 IE 浏览器的版本号小于 9 时(`if lt IE 9`)才会加载其中的代码。这个奇怪的 `[if lt IE 9]` 句法不是 Rails 提供的,其实它是 IE 浏览器为了解决兼容性问题而特别提供的[条件注释](http://en.wikipedia.org/wiki/Conditional_comment)。使用这个句法有个好处,只会在 IE9 以前的版本中加载 HTML5 shim,而 Firefox、Chrome 和 Safari 等其他浏览器不会受到影响。 后面的区域是一个 `header`,包含网站的 LOGO(纯文本)、一些区域(使用 `div` 标签)和一个导航列表元素: ``` <header class="navbar navbar-fixed-top navbar-inverse"> <div class="container"> <%= link_to "sample app", '#', id: "logo" %> <nav> <ul class="nav navbar-nav navbar-right"> <li><%= link_to "Home", '#' %></li> <li><%= link_to "Help", '#' %></li> <li><%= link_to "Log in", '#' %></li> </ul> </nav> </div> </header> ``` `header` 标签表明这个元素应该放在页面的顶部。我们为 `header` 标签指定了三个 CSS 类,[[3](#fn-3)]分别为 `navbar`、`navbar-fixed-top` 和 `navbar-inverse`,类之间用空格分开: ``` <header class="navbar navbar-fixed-top navbar-inverse"> ``` 所有 HTML 元素都可以指定类和 ID,它们不仅是标记,使用 CSS 编写样式时也有用([5.1.2 节](#bootstrap-and-custom-css))。类和 ID 之间主要的区别是,类可以在同一个网页中多次使用,而 ID 只能使用一次。这里的三个类在 Bootstrap 框架中都有特殊的意义。我们会在 [5.1.2 节](#bootstrap-and-custom-css)安装并使用 Bootstrap。 在 `header` 标签内部,有一个 `div` 标签: ``` <div class="container"> ``` `div` 标签是常规的区域,除了把文档分成不同的部分之外,没有特殊的意义。在以前的 HTML 标准中,`div` 标签被用来划分网站中几乎所有的区域,但是 HTML5 增加了 `header`、`nav` 和 `section` 等元素,用来划分大多数网站中都会用到的区域。这个 `div` 标签也有一个 CSS 类,`container`。和 `header` 标签的类一样,这个类在 Bootstrap 中也有特殊的意义。 在这个 `div` 标签中有一些 ERb 代码: ``` <%= link_to "sample app", '#', id: "logo" %> <nav> <ul class="nav navbar-nav navbar-right"> <li><%= link_to "Home", '#' %></li> <li><%= link_to "Help", '#' %></li> <li><%= link_to "Log in", '#' %></li> </ul> </nav> ``` 这里使用 Rails 提供的 `link_to` 辅助方法创建链接([3.2.2 节](chapter3.html#custom-static-pages)直接使用 `a` 标签创建)。`link_to` 的第一个参数是链接文本,第二个参数是链接地址。在 [5.3 节](#layout-links)我们会使用“具名路由”(named route)指定链接地址,现在暂且使用 Web 开发中经常使用的占位符 `#`。第三个参数可选,是一个哈希,本例使用这个参数为 LOGO 添加一个 CSS ID——`logo`。(其他三个链接没有使用这个哈希参数,没关系,因为这个参数是可选的。)Rails 辅助方法的参数经常这样使用哈希,让我们仅使用 Rails 的辅助方法就能灵活添加 HTML 属性。 `div` 标签中的第二个元素是导航链接,使用无序列表标签 `ul`,以及列表项目标签 `li` 编写: ``` <nav> <ul class="nav navbar-nav navbar-right"> <li><%= link_to "Home", '#' %></li> <li><%= link_to "Help", '#' %></li> <li><%= link_to "Log in", '#' %></li> </ul> </nav> ``` `nav` 标签以前是不需要的,它的目的是明确表明这些链接是导航。`ul` 标签中的 `nav`、`navbar-nav` 和 `navbar-right` 三个类在 Bootstrap 中有特殊的意义,[5.1.2 节](#bootstrap-and-custom-css)引入 Bootstrap 的 CSS 之后会自动实现特殊的样式。在浏览器中审查导航元素,你会发现 Rails 处理布局文件并执行其中的 ERb 代码后,生成的列表如下所示:[[4](#fn-4)] ``` <nav> <ul class="nav navbar-nav navbar-right"> <li><a href="#">Home</a></li> <li><a href="#">Help</a></li> <li><a href="#">Log in</a></li> </ul> </nav> ``` 这就是返回给浏览器的文本。 布局文件的最后一部分是一个 `div` 标签,用于显示主内容: ``` <div class="container"> <%= yield %> </div> ``` 和之前一样,`container` 类在 Bootstrap 中有特殊意义。[3.4.3 节](chapter3.html#layouts-and-embedded-ruby)已经介绍过,`yield` 会把各页面中的内容插入网站的布局中。 除了网站的底部([5.1.3 节](#partials)会添加)之外,布局现在完成了。访问“首页”就能看到结果。为了利用后面添加的样式,我们要在 `home.html.erb` 视图中添加一些额外元素,如[代码清单 5.2](#listing-signup-button) 所示。 ##### 代码清单 5.2:“首页”视图,包含一个到注册页面的链接 app/views/static_pages/home.html.erb ``` <div class="center jumbotron"> <h1>Welcome to the Sample App</h1> <h2> This is the home page for the <a href="http://www.railstutorial.org/">Ruby on Rails Tutorial</a> sample application. </h2> <%= link_to "Sign up now!", '#', class: "btn btn-lg btn-primary" %> </div> <%= link_to image_tag("rails.png", alt: "Rails logo"), 'http://rubyonrails.org/' %> ``` 其中第一个 `link_to` 创建一个占位链接,指向[第 7 章](chapter7.html#sign-up)创建的用户注册页面: ``` <a href="#" class="btn btn-lg btn-primary">Sign up now!</a> ``` `div` 标签的 CSS 类 `jumbotron` 在 Bootstrap 中有特殊的意义,注册按钮的 `btn`、`btn-lg` 和 `btn-primary` 也是一样。 第二个 `link_to` 用到了 `image_tag` 辅助方法,第一个参数是图片的路径;第二个参数可选,是一个哈希,本例中这个哈希参数使用一个符号键设置图片的 `alt` 属性。为了能正确显示图片,应用中必须有个名为 `rails.png` 的图片。这个图片可以从本书的网站中下载,地址是 [http://railstutorial-china.org/assets/http://railstutorial-china.org/book/images/rails.png](http://railstutorial-china.org/assets/http://railstutorial-china.org/book/images/rails.png)。下载后把这个图片放在 `app/assets/http://railstutorial-china.org/book/images/` 文件夹中。如果使用云端 IDE 或 Unix 类系统,可以使用 `curl` 完成这个操作,如下所示:[[5](#fn-5)] ``` $ curl -O http://railstutorial-china.org/assets/http://railstutorial-china.org/book/images/rails.png $ mv rails.png app/assets/http://railstutorial-china.org/book/images/ ``` 因为我们使用了 `image_tag` 辅助方法,所以 Rails 会使用 Asset Pipeline([5.2 节](#sass-and-the-asset-pipeline))自动在 `app/assets/http://railstutorial-china.org/book/images/` 文件夹中寻找图片。 为了更好地理解 `image_tag`,我们来看一下生成的 HTML:[[6](#fn-6)] ``` <img alt="Rails logo" src="/assets/rails-9308b8f92fea4c19a3a0d8385b494526.png" /> ``` 其中,字符串 `9308b8f92fea4c19a3a0d8385b494526`(在你的系统中得到的字符串可能不一样)由 Rails 添加,目的是确保文件名的唯一性,如果文件变化了,让浏览器重新加载文件(而不是从缓存中读取)。注意,`src` 属性中并没有 `images`,使用的是静态文件(图片,JavaScript,CSS 等)共用的 `assets` 文件夹。在服务器中,Rails 会把 `assets` 文件夹中的图片和 `app/assets/images` 文件夹中的文件对应起来。这么做是为了让浏览器觉得所有静态文件都在同一个文件夹中,有利于快速伺服。`alt` 属性的内容会在图片无法加载时显示,例如在针对视觉障碍人士的屏幕阅读器中。 ![layout no logo or custom css bootstrap 3rd edition](https://box.kancloud.cn/2016-05-11_5732bd029b169.png)图 5.2:还没添加 CSS 的首页 现在我们终于可以看到劳动的果实了,如[图 5.2](#fig-layout-no-logo-or-custom-css) 所示。你可能会说,这并不很美观啊。或许吧。不过也可以小小的高兴一下,因为我们为 HTML 结构指定了合适的类,可以用来添加 CSS。 ## 5.1.2 Bootstrap 和自定义的 CSS 前一节我们为很多 HTML 元素指定了 CSS 类,这样我们就可以使用 CSS 灵活的构建布局了。如前所述,其中很多类在 Bootstrap 中都有特殊的意义。Bootstrap 是 Twitter 开发的框架,可以方便地把精美的 Web 设计和用户界面元素添加到使用 HTML5 开发的应用中。本节,我们会结合 Bootstrap 和一些自定义的 CSS 为演示应用添加一些样式。 首先,我们要安装 Bootstrap。在 Rails 应用中可以使用 `bootstrap-sass` 这个 gem,如[代码清单 5.3](#listing-bootstrap-sass) 所示。Bootstrap 框架本身使用 [LESS](http://lesscss.org/) 编写动态样式表,而 Rails 的 Asset Pipeline 默认支持的是(非常类似的)Sass 语言。`bootstrap-sass` 会把 LESS 转换成 Sass,而且让 Bootstrap 中所有必要的文件都可以在当前应用中使用。[[7](#fn-7)] ##### 代码清单 5.3:把 `bootstrap-sass` 添加到 `Gemfile` 中 ``` source 'https://rubygems.org' gem 'rails', '4.2.2' gem 'bootstrap-sass', '3.2.0.0' . . . ``` 和之前一样,运行 `bundle install` 安装 Bootstrap: ``` $ bundle install ``` `rails generate` 命令会自动为控制器生成一个单独的 CSS 文件,但很难使用正确的顺序引入这些样式,所以简单起见,本书会把所有 CSS 都放在一个文件夹中。为此,我们要先新建这个 CSS 文件: ``` $ touch app/assets/stylesheets/custom.css.scss ``` (使用 [3.3.3 节](chapter3.html#green)用过的 `touch` 命令,你也可以使用其他方式。)其中文件夹的名字和文件扩展名都很重要。`app/assets/stylesheets/` 文件夹是 Asset Pipeline 的一部分,其中所有的样式表都会引入 `application.css` 文件。文件名 `custom.css.scss` 中包含 `.css`,说明这是 CSS 文件,`.scss` 扩展名则说明这是“Sassy CSS”文件,Asset Pipeline 会使用 Sass 处理其中的内容。([5.2.2 节](#syntactically-awesome-stylesheets)才会使用 Sass,不过加入这个扩展名才能发挥 `bootstrap-sass` gem 的作用。) 在这个 CSS 文件中,我们可以使用 `@import` 函数引入 Bootstrap(以及相关的 Sprockets 工具),如[代码清单 5.4](#listing-bootstrap-css) 所示。[[8](#fn-8)] ##### 代码清单 5.4:添加 Bootstrap 的 CSS app/assets/stylesheets/custom.css.scss ``` @import "bootstrap-sprockets"; @import "bootstrap"; ``` 这两行代码会引入整个 Bootstrap CSS 框架。然后重启 Web 服务器(先按 Ctrl-C 键,然后执行 `rails server` 命令),让这些改动生效,效果如[图 5.3](#fig-sample-app-only-bootstrap) 所示。文本的位置还不合适,LOGO 也没有任何样式,不过颜色搭配和注册按钮看起来都不错。 ![sample app only bootstrap 3rd edition](https://box.kancloud.cn/2016-05-11_5732bd02b416c.png)图 5.3:使用 Bootstrap CSS 后的演示应用 下面我们要加入一些整站都会用到的 CSS,用来样式化网站布局和各个页面,如[代码清单 5.5](#listing-universal-css) 所示。效果如[图 5.4](#fig-sample-app-universal) 所示。代码清单 5.5 中定义了很多样式规则。为了说明 CSS 规则的作用,经常会加入一些 CSS 注释,放在 `/* ... */` 中。 ##### 代码清单 5.5:添加全站使用的 CSS app/assets/stylesheets/custom.css.scss ``` @import "bootstrap-sprockets"; @import "bootstrap"; /* universal */ body { padding-top: 60px; } section { overflow: auto; } textarea { resize: vertical; } .center { text-align: center; } .center h1 { margin-bottom: 10px; } ``` ![sample app universal 3rd edition](https://box.kancloud.cn/2016-05-11_5732bd02d0a42.png)图 5.4:添加一些留白以及其他全局样式 注意,[代码清单 5.5](#listing-universal-css) 中的 CSS 格式都是统一的。一般来说,CSS 规则通过类、ID、HTML 标签或者三者结合在一起来指代目标,然后在后面跟着一些样式声明。例如: ``` body { padding-top: 60px; } ``` 这个规则把页面的上内边距设为 60 像素。我们在 `header` 标签上指定了 `navbar-fixed-top` 类,Bootstrap 会把这个导航条固定在页面的顶部,所以页面的上内边距会把主内容区和导航条隔开一段距离。(导航条的颜色在 Bootstrap 2.0 中变了,所以我们要加入 `navbar-inverse` 类,把亮色变暗。)下面的 CSS 规则: ``` .center { text-align: center; } ``` 把 `.center` 类的样式定义为 `text-align: center;`。`.center` 中的点号说明这个规则是样式化一个类。(在[代码清单 5.7](#listing-logo-css) 中会看到,`#` 样式化一个 ID。)这个规则的意思是,任何类为 `.center` 的标签(例如 `div`),其中包含的内容都会在页面中居中显示。([代码清单 5.2](#listing-signup-button) 中有用到这个类。) 虽然 Bootstrap 中包含了很精美的文字排版样式,我们还是要为文字的外观添加一些自定义的规则,如[代码清单 5.6](#listing-typography-css) 所示。(并不是所有样式都用于“首页”,但所有规则都会在这个演示应用的某个地方用到。)效果如[图 5.5](#fig-sample-app-typography) 所示。 ##### 代码清单 5.6:添加一些精美的文字排版样式 app/assets/stylesheets/custom.css.scss ``` @import "bootstrap-sprockets"; @import "bootstrap"; . . . /* typography */ h1, h2, h3, h4, h5, h6 { line-height: 1; } h1 { font-size: 3em; letter-spacing: -2px; margin-bottom: 30px; text-align: center; } h2 { font-size: 1.2em; letter-spacing: -1px; margin-bottom: 30px; text-align: center; font-weight: normal; color: #777; } p { font-size: 1.1em; line-height: 1.7em; } ``` ![sample app typography 3rd edition](https://box.kancloud.cn/2016-05-11_5732bd02e88f0.png)图 5.5:添加一些排版样式 最后,我们还要为只包含文本“sample app”的网站 LOGO 添加一些样式。[代码清单 5.7](#listing-logo-css) 中的 CSS 会把文字变成全大写字母,还修改了文字大小、颜色和位置。(我们使用的是 ID,因为我们希望 LOGO 在页面中只出现一次,不过也可以使用类。) ##### 代码清单 5.7:添加网站 LOGO 的样式 app/assets/stylesheets/custom.css.scss ``` @import "bootstrap-sprockets"; @import "bootstrap"; . . . /* header */ #logo { float: left; margin-right: 10px; font-size: 1.7em; color: #fff; text-transform: uppercase; letter-spacing: -1px; padding-top: 9px; font-weight: bold; } #logo:hover { color: #fff; text-decoration: none; } ``` 其中,`color: #fff;` 会把 LOGO 文字的颜色变成白色。HTML 中的颜色代码由 3 组 16 进制数组成,分别代表三原色中的红绿蓝。`#ffffff` 是 3 种颜色都为最大值的情况,表示纯白色。`#fff` 是 `#ffffff` 的简写形式。CSS 标准为很多常用的 HTML 颜色定义了别名,例如 `white` 代表 `#fff`。添加[代码清单 5.7](#listing-logo-css) 中的样式后,效果如[图 5.6](#fig-sample-app-logo) 所示。 ![sample app logo 3rd edition](https://box.kancloud.cn/2016-05-11_5732bd030facc.png)图 5.6:添加 LOGO 样式后的演示应用 ## 5.1.3 局部视图 虽然[代码清单 5.1](#listing-layout-new-structure) 中的布局达到了目的,但其中的内容看起来有点混乱。HTML shim 就占用了三行,而且使用了只针对 IE 的奇怪句法,如果能把它打包放在一个单独的地方就好了。头部的 HTML 自成一个逻辑单元,所以也可以把这部分打包放在某个地方。在 Rails 中我们可以使用“局部视图”实现这种想法。先来看一下定义了局部视图之后的布局文件。如[代码清单 5.8](#listing-layout-with-partials) 所示。 ##### 代码清单 5.8:把 HTML shim 和头部放到局部视图之后的网站布局 app/views/layouts/application.html.erb ``` <!DOCTYPE html> <html> <head> <title><%= full_title(yield(:title)) %></title> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> <%= csrf_meta_tags %> <%= render 'layouts/shim' %> </head> <body> <%= render 'layouts/header' %> <div class="container"> <%= yield %> </div> </body> </html> ``` 在这段代码中,我们把 HTML shim 删掉,换成了一行代码,调用 Rails 的辅助方法 `render`: ``` <%= render 'layouts/shim' %> ``` 这行代码会寻找一个名为 `app/views/layouts/_shim.html.erb` 的文件,执行其中的代码,然后把结果插入视图。[[9](#fn-9)](回顾一下,执行 Ruby 表达式并将结果插入模板中要使用 `&lt;%= …​ %&gt;`。)注意,文件名 `_shim.html.erb` 的开头是个下划线,这是局部视图的命名约定,可以在目录中快速定位所有局部视图。 当然,若要局部视图起作用,我们要写入相应的内容。HTML shim 局部视图只包含三行代码,如[代码清单 5.9](#listing-stylesheets-partial) 所示。 ##### 代码清单 5.9:HTML shim 局部视图 app/views/layouts/_shim.html.erb ``` <!--[if lt IE 9]> <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js"> </script> <![endif]--> ``` 类似地,我们可以把头部的内容移入局部视图,如[代码清单 5.10](#listing-header-partial) 所示,然后再次调用 `render` 把这个局部视图插入布局中。(一般都要在文本编辑器中手动创建局部视图对应的文件。) ##### 代码清单 5.10:网站头部的局部视图 app/views/layouts/_header.html.erb ``` <header class="navbar navbar-fixed-top navbar-inverse"> <div class="container"> <%= link_to "sample app", '#', id: "logo" %> <nav> <ul class="nav navbar-nav navbar-right"> <li><%= link_to "Home", '#' %></li> <li><%= link_to "Help", '#' %></li> <li><%= link_to "Log in", '#' %></li> </ul> </nav> </div> </header> ``` 现在我们已经知道怎么创建局部视图了,让我们来加入和头部对应的网站底部吧。你或许已经猜到了,我们会把这个局部视图命名为 `_footer.html.erb`,放在布局文件夹中,如[代码清单 5.11](#listing-footer-partial) 所示。[[10](#fn-10)] ##### 代码清单 5.11:网站底部的局部视图 app/views/layouts/_footer.html.erb ``` <footer class="footer"> <small> The <a href="http://www.railstutorial.org/">Ruby on Rails Tutorial</a> by <a href="http://www.michaelhartl.com/">Michael Hartl</a> </small> <nav> <ul> <li><%= link_to "About", '#' %></li> <li><%= link_to "Contact", '#' %></li> <li><a href="http://news.railstutorial.org/">News</a></li> </ul> </nav> </footer> ``` 和头部类似,在底部我们使用 `link_to` 创建到“关于”页面和“联系”页面的链接,地址先使用占位符 `#`。(和 `header` 一样,`footer` 也是 HTML5 新增加的标签。) 按照 HTML shim 和头部局部视图的方式,我们也可以在布局视图中渲染底部局部视图,如[代码清单 5.12](#listing-layout-with-footer) 所示。 ##### 代码清单 5.12:添加底部局部视图后的网站布局 app/views/layouts/application.html.erb ``` <!DOCTYPE html> <html> <head> <title><%= full_title(yield(:title)) %></title> <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %> <%= javascript_include_tag "application", "data-turbolinks-track" => true %> <%= csrf_meta_tags %> <%= render 'layouts/shim' %> </head> <body> <%= render 'layouts/header' %> <div class="container"> <%= yield %> <%= render 'layouts/footer' %> </div> </body> </html> ``` 当然,如果没有样式的话,底部还很丑。底部的样式参见[代码清单 5.13](#listing-footer-css),效果如[图 5.7](#fig-site-with-footer) 所示。 ![site with footer bootstrap 3rd edition](https://box.kancloud.cn/2016-05-11_5732bd032946e.png)图 5.7:添加底部后的首页 ##### 代码清单 5.13:添加网站底部的 CSS app/assets/stylesheets/custom.css.scss ``` . . . /* footer */ footer { margin-top: 45px; padding-top: 5px; border-top: 1px solid #eaeaea; color: #777; } footer a { color: #555; } footer a:hover { color: #222; } footer small { float: left; } footer ul { float: right; list-style: none; } footer ul li { float: left; margin-left: 15px; } ```