# 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(如 `<!DOCTYPE html>` 所示)。因为 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 表达式并将结果插入模板中要使用 `<%= … %>`。)注意,文件名 `_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;
}
```
- Ruby on Rails 教程
- 致中国读者
- 序
- 致谢
- 作者译者简介
- 版权和代码授权协议
- 第 1 章 从零开始,完成一次部署
- 1.1 简介
- 1.2 搭建环境
- 1.3 第一个应用
- 1.4 使用 Git 做版本控制
- 1.5 部署
- 1.6 小结
- 1.7 练习
- 第 2 章 玩具应用
- 2.1 规划应用
- 2.2 用户资源
- 2.3 微博资源
- 2.4 小结
- 2.5 练习
- 第 3 章 基本静态的页面
- 3.1 创建演示应用
- 3.2 静态页面
- 3.3 开始测试
- 3.4 有点动态内容的页面
- 3.5 小结
- 3.6 练习
- 3.7 高级测试技术
- 第 4 章 Rails 背后的 Ruby
- 4.1 导言
- 4.2 字符串和方法
- 4.3 其他数据类型
- 4.4 Ruby 类
- 4.5 小结
- 4.6 练习
- 第 5 章 完善布局
- 5.1 添加一些结构
- 5.2 Sass 和 Asset Pipeline
- 5.3 布局中的链接
- 5.4 用户注册:第一步
- 5.5 小结
- 5.6 练习
- 第 6 章 用户模型
- 6.1 用户模型
- 6.2 用户数据验证
- 6.3 添加安全密码
- 6.4 小结
- 6.5 练习
- 第 7 章 注册
- 7.1 显示用户的信息
- 7.2 注册表单
- 7.3 注册失败
- 7.4 注册成功
- 7.5 专业部署方案
- 7.6 小结
- 7.7 练习
- 第 8 章 登录和退出
- 8.1 会话
- 8.2 登录
- 8.3 退出
- 8.4 记住我
- 8.5 小结
- 8.6 练习
- 第 9 章 更新,显示和删除用户
- 9.1 更新用户
- 9.2 权限系统
- 9.3 列出所有用户
- 9.4 删除用户
- 9.5 小结
- 9.6 练习
- 第 10 章 账户激活和密码重设
- 10.1 账户激活
- 10.2 密码重设
- 10.3 在生产环境中发送邮件
- 10.4 小结
- 10.5 练习
- 10.6 证明超时失效的比较算式
- 第 11 章 用户的微博
- 11.1 微博模型
- 11.2 显示微博
- 11.3 微博相关的操作
- 11.4 微博中的图片
- 11.5 小结
- 11.6 练习
- 第 12 章 关注用户
- 12.1 “关系”模型
- 12.2 关注用户的网页界面
- 12.3 动态流
- 12.4 小结
- 12.5 练习