Bootstrap-实践指南-全-
Bootstrap 实践指南(全)
一、入门指南
随着许多人开始使用手机和平板电脑,创建响应迅速的网站和应用程序正成为一项硬性要求。Twitter Bootstrap 为您提供了所有必要的工具,因此您创建的作品可以在各种尺寸的显示器上观看。
本章从 Twitter Bootstrap 的基础知识开始,主要是它的网格系统。
您将了解 12 列网格系统,这样您就可以将页面分成多行和多列。图 1-1 显示了 Twitter 引导网格系统的一个例子。

图 1-1
展示 Twitter 引导网格系统的演示页面
你将确保你有一个如图 1-2 所示的页面。

图 1-2
在大显示器上观看的页面
它可以在较小的设备上自动转换成图 1-3 的样子。

图 1-3
Page 在较小的设备上调整其布局
学习目标
-
了解什么是 Twitter Bootstrap。
-
了解如何在项目中包含 Twitter Bootstrap CSS 和 JavaScript 库。
-
了解可用的两种主要容器及其区别。
-
了解 Twitter Bootstrap 的网格系统如何帮助您组织页面内容并生成响应性布局。
自举定义
Twitter Bootstrap 是一组 CSS 和 JavaScript 代码,您可以基于它们编写自己的 HTML、CSS 和 JavaScript 代码,以便快速拥有一个响应迅速的网站或 web 应用程序,采用移动优先的设计方法。
换句话说,它为您提供了一些 CSS 类和 JavaScript 代码,您可以直接使用。您应用这些类,使用 JavaScript 模块,很快就可以让您的网站和 web 应用程序拥有一些原本需要您花费大量精力从头开发的功能。
最基本的 Twitter 引导页面
让我们从创建第一个 Twitter 引导页面开始。创建一个新文件index.html,并将以下内容放入其中(清单 1-1 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<title>Bare Bones Twitter Bootstrap Page</title>
</head>
<body>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 1-1Bare-Bones Twitter Bootstrap Page
这是一个没有任何有价值内容的页面。其body元素为空。然而
-
它引用了引导 CSS 库。
-
它引用了
jQuery库,这是 Twitter Bootstrap JavaScript 模块所必需的 JavaScript 库。 -
它引用了
popper库。这是一个 JavaScript 库,Bootstrap 用它来定位工具提示和弹出窗口。 -
最后,它还引用了引导 JavaScript 库。
如果您在浏览器上加载前面的页面,您将看不到任何内容。但是所有的 Twitter 引导特性都会被加载。
容器
当您开始页面布局时,您需要决定包含页面内容的容器样式。有三种类型的容器:
-
container,在每个响应断点设置一个max-width。 -
container-fluid,在所有断点处都是width: 100%。 -
container-{breakpoint},也就是width: 100%,直到指定的断点。在指定的断点(包括)之后,它像使用container一样使用max-width。
Note
max-width定义一个元素可以拥有的最大宽度。这意味着元素试图占据尽可能多的宽度,直到max-width,之后它扩展它的高度以适应内容。这当然意味着元素的实际宽度不能超过max-width,即使width属性可能有一个更大的值。
Tip
Twitter Bootstrap 定义了五个断点,即像素宽度,之后网格布局会发生变化。例如,一个小断点的值为 576px,表示显示宽度在 576px 和 767px 之间。我将在本章的后面谈到断点。
您可以通过设置相应的div元素(或等效的块元素)来应用其中一个元素,使其具有与容器名称相同的类。
增强页面的内容,使其如下所示(粗体显示的是添加的代码——列出了 1-2 )。
-
我添加了一个对名为
stylesheets/index.css的本地 CSS 文件的引用。我把它放在 Twitter Bootstrap CSS 参考之后。我将把特定于网页的 CSS 规则放在这个文件中。这个文件需要在 Twitter 引导 CSS 引用之后,因为它将依赖于它。 -
我已经创建了两个
divs作为页面容器。第一个div是一个container,,而第二个div是一个container-fluid。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>Bare Bones Twitter Bootstrap Page</title>
</head>
<body>
<div class="container">
This is a container
</div>
<div class="container-fluid">
This is a container fluid
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 1-2Add Two Containers
在文件夹stylesheets中创建文件index.css,并添加以下内容(列表 1-3 )。
.container {
background-color: #8DC5CC;
}
.container-fluid {
background-color: #aaad21;
}
Listing 1-3CSS for the index.css File
Caution
现在你正在使用 Twitter Bootstrap,你将不再需要像* {box-sizing: border-box}那样编写 CSS 重置规则。这是因为 Twitter Bootstrap 本身有一系列非常有意义的缺省值,它们与 Twitter Bootstrap 类的其余部分是一致的。
可以想象,这是用来将特定的、不同的颜色应用到两个容器上的,这样我就可以看到它们是如何放在页面上的。
保存所有文件并在浏览器上加载index.html页面。你将看到的应该是类似图 1-4 的东西。

图 1-4
容器与容器流体
如图 1-4 所示,container有左右页边距,而container-fluid没有页边距,覆盖了页面的整个宽度。container页边距不是固定的宽度。它们的宽度根据视口宽度而变化。
另一方面,两个容器都有左右填充,等于15px。您可以看到文本“这是一个容器…”没有从左边界的边缘开始,但是它有一些空闲的空白空间。
请注意,即使您使用了container,当您缩小浏览器窗口的宽度,使其宽度小于576px时,container会失去其左右边距,本质上,其行为类似于container-fluid。换句话说,苹果 iPhone X 设备上的这个页面会像你在图 1-5 中看到的那样显示。

图 1-5
container的行为类似于 iPhone X 上的container-fluid
因此,在这种情况下,container和container-fluid将是相同的。
网格系统
网格系统,也就是把你的布局分成行和列,是设计你的页面布局的一个很好的实践。Twitter Bootstrap 附带了方便的类,允许您随着设备或视口大小的增加,将布局扩展到 12 列。
因此,每当你想把你的页面分成一系列的栏目,你必须
-
决定容器类型。
-
在容器内部,添加一个
row类div。 -
在
row类div内,添加一个或多个col-*类div元素。
我将用一些例子来解释什么是col-*类。
示例:一行 12 列
让我们创建一个一行 12 列的页面,如图 1-6 所示。

图 1-6
单行 12 列网格
创建这个页面的一种方法如下所示(清单 1-4 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>1 row 12 columns</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col">
1
</div>
<div class="col">
2
</div>
<div class="col">
3
</div>
<div class="col">
4
</div>
<div class="col">
5
</div>
<div class="col">
6
</div>
<div class="col">
7
</div>
<div class="col">
8
</div>
<div class="col">
9
</div>
<div class="col">
10
</div>
<div class="col">
11
</div>
<div class="col">
12
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 1-4One-Row 12-Column Page
CSS 文件(名为index.css)在清单 1-5 中给出。
.container {
background-color: #8DC5CC;
}
.container .row div {
background-color: #4e9013;
padding: 10px 0;
border: 1px solid green;
color: white;
text-align: center;
}
Listing 1-5CSS for the One-Row 12-Column Layout
正如你在 HTML 文件index.html中看到的,我使用了一个container,并在其中引入了一个row类div。然后对于 12 列中的每一列,我都使用了一个col类div.
同样,我想要 12 列,我用类col添加了 12 个divs。所有 12 个divs都被添加到一个row div中。row div用于布局列,并且只有列可以是行的直接子级。
示例:两行网格,第二行有六列
让我们在网格页面中再添加一行。但是这一次,让我们假设我们希望第二行有六列,如图 1-7 所示。

图 1-7
两行,第二行有六列
如图 1-7 所示,第二行的每一列都占据了第一行的两倍列宽。
完整的 HTML 代码在清单 1-6 中。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>2 rows 2nd 6 columns</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col">
1
</div>
<div class="col">
2
</div>
<div class="col">
3
</div>
<div class="col">
4
</div>
<div class="col">
5
</div>
<div class="col">
6
</div>
<div class="col">
7
</div>
<div class="col">
8
</div>
<div class="col">
9
</div>
<div class="col">
10
</div>
<div class="col">
11
</div>
<div class="col">
12
</div>
</div>
<div class="row">
<div class="col">
1
</div>
<div class="col">
2
</div>
<div class="col">
3
</div>
<div class="col">
4
</div>
<div class="col">
5
</div>
<div class="col">
6
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 1-6Two Rows, the Second Row Having Six Columns, HTML Code
清单 1-7 是完整的 CSS 代码(这对网格的创建并不重要,但它只是帮助我在页面上可视化网格行的列)。
.container {
background-color: #8DC5CC;
}
.container .row:nth-of-type(1) div {
background-color: #4e9013;
padding: 10px 0;
border: 1px solid green;
color: white;
text-align: center;
}
.container .row:nth-of-type(2) div {
background-color: #902e07;
padding: 10px 0;
border: 1px solid #441180;
color: white;
text-align: center;
}
Listing 1-7CSS for the Page Having Two Rows, the Second Row Having Six Columns
正如您所看到的,只要有六个类为col的divs作为类为row的div的子元素,就很容易拥有六列。
示例:两行网格,第二行有五列
假设您希望一行有五列,而不是六列,第一列的大小是其他列的两倍。例如,参见图 1-8 。

图 1-8
第二行有五列,第一列较宽
你会怎么做?如果你把你的代码改成有五个 div,在第二个row div里面,你会得到什么?您将看到图 1-9 的页面。

图 1-9
第二行有五列大小相同
这不完全是你想要的。如果只放五个divs,生成的列宽度相等。但是您想要的是第一列的宽度是其他列的两倍。另外,如果您更仔细地观察,您会发现第一列占据了 12 个可用标准列中的 4 个,而其他列占据了 2 个。同样,这也是你想要达到的目标(图 1-10 )。

图 1-10
你想实现什么
为了做到这一点,你必须更加精确地确定每一列的类别。你必须准确地说出每一列应该占据多少标准列。
因此,对于第一列,您必须使用类col-4,而对于其他列,您必须使用类col-2。正确的 HTML 代码在清单 1-8 中。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>2 rows 2nd 5 columns</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col">
1
</div>
<div class="col">
2
</div>
<div class="col">
3
</div>
<div class="col">
4
</div>
<div class="col">
5
</div>
<div class="col">
6
</div>
<div class="col">
7
</div>
<div class="col">
8
</div>
<div class="col">
9
</div>
<div class="col">
10
</div>
<div class="col">
11
</div>
<div class="col">
12
</div>
</div>
<div class="row">
<div class="col-4">
1
</div>
<div class="col-2">
2
</div>
<div class="col-2">
3
</div>
<div class="col-2">
4
</div>
<div class="col-2">
5
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 1-8Using col-4 for the First Column and col-2 for the Others
将第二行分成五列的另一种方法如清单 1-9 所示。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>2 rows 2nd 5 columns</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col">
1
</div>
<div class="col">
2
</div>
<div class="col">
3
</div>
<div class="col">
4
</div>
<div class="col">
5
</div>
<div class="col">
6
</div>
<div class="col">
7
</div>
<div class="col">
8
</div>
<div class="col">
9
</div>
<div class="col">
10
</div>
<div class="col">
11
</div>
<div class="col">
12
</div>
</div>
<div class="row">
<div class="col-3">
1
</div>
<div class="col-2">
2
</div>
<div class="col-3">
3
</div>
<div class="col-2">
4
</div>
<div class="col-2">
5
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 1-9Another Way to Divide into Five Columns
如果您在浏览器上保存并加载该页面,您将看到图 1-11 中所示的内容。

图 1-11
分成五列的另一种方法
如图 1-11 所示,第二行同样有五列,但第一列和第三列的大小不同。这两列的大小为3,而所有其他列的大小为2。然而,即使在这种情况下,总的列大小加起来也有 12: 3 + 2 + 3 + 2 + 2。
示例:两行网格,第二行有三列,中间较宽
但是你不必总是精确所有列的宽度。有时,您希望只指定一列的宽度,并希望自动计算其他列的宽度。例如,参见图 1-12 。

图 1-12
中间栏为可用宽度的一半
您希望中间的列占据一半的可用宽度,而剩下的空间由第一列和第三列共享。
您可以通过将col-3赋予第一个和第三个divs并将col-6赋予第二个div来做到这一点,但是似乎您可以通过将col赋予第一个和第三个divs并将col-6赋予第二个div来做到这一点,如清单 1-10 所示。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>Specifying the width of the middle column only</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col">
1
</div>
<div class="col">
2
</div>
<div class="col">
3
</div>
<div class="col">
4
</div>
<div class="col">
5
</div>
<div class="col">
6
</div>
<div class="col">
7
</div>
<div class="col">
8
</div>
<div class="col">
9
</div>
<div class="col">
10
</div>
<div class="col">
11
</div>
<div class="col">
12
</div>
</div>
<div class="row">
<div class="col">
1
</div>
<div class="col-6">
2
</div>
<div class="col">
3
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 1-10Specifying the Width of the Middle Column Only
不同的显示宽度
Twitter Bootstrap 允许你根据网页的不同显示宽度,为你的网格布局(以及网页样式的其他属性)使用不同的类。具体来说,有五个键宽断点,如表 1-1 中所列。
表 1-1
Twitter 引导响应断点
|名字
|
标志
|
显示宽度
|
| --- | --- | --- |
| 超小型 | xs | < 576 像素 |
| 小的 | sm | > = 576 像素 |
| 中等 | md | > = 768 像素 |
| 大型 | lg | > = 992 像素 |
| 超大尺寸 | xl | > = 1200 像素 |
您通过它们相应的符号来引用它们,作为您正在使用的类名的一部分。
因此,如果你正在使用,例如,类col-lg-5,这意味着这个类指的是宽度> =992px 的设备的断点lg。然而,对每个特定类的进一步解释取决于类案例本身。我们将在这一部分学习最重要的课程。
基于前面五个关键断点工作的 Twitter 引导网格类是
-
对于超小型设备,
col-1、col-2等等,直到col-12 -
对于小型设备,
col-sm-1、col-sm-2等等,直到col-sm-12 -
对于中型设备,
col-md-1、col-md-2等等,直到col-md-12 -
对于大型设备,
col-lg-1、col-lg-2等等,直到col-lg-12 -
col-xl-1, col-xl-2,以此类推,up to col-xl-12,用于超大型设备
但是举例来说,col-sm-2和col-md-2有什么区别呢?
它们都占据了两列。对于> =576px 的任何显示区域宽度,col-sm-2将占据两列,但是对于> = 768px 的显示宽度,col-md-2将占据两列。col-md-2,对于< 768px 的显示区域,将不会占据两列,而是将一列堆叠在另一列之上,就好像它们是两行一样,基本上每列占据整个 12 列的可用宽度。
我们来看一个例子。您将创建一个包含一行六列的页面,每一列占据两列宽。将下面的代码写入一个 HTML 文档(清单 1-11 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>Listing 1-11</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-sm-2">
1
</div>
<div class="col-sm-2">
2
</div>
<div class="col-sm-2">
3
</div>
<div class="col-sm-2">
4
</div>
<div class="col-sm-2">
5
</div>
<div class="col-sm-2">
6
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 1-11Six Columns with the sm Breakpoint
在stylesheets文件夹内相应的index.css文件中写入以下(列表 1-12 ) CSS。
.container {
background-color: #8DC5CC;
}
.container .row:nth-of-type(1) div {
background-color: #4e9013;
padding: 10px 0;
border: 1px solid green;
color: white;
text-align: center;
}
Listing 1-12CSS for Listing 1-11
如果您保存前面的代码,然后在浏览器上加载 HTML 页面,您将看到以下内容(图 1-13 )。

图 1-13
一行六列布局—每个占据两列
正如你在 HTML 代码中看到的,我使用了断点sm,,并指示每一列占用 12 列中的两列。这将导致该行被分成六列,但仅适用于宽度> =576px 的显示区域。
启用开发者工具,缩小浏览器窗口,使其宽度正好为 576 像素。您将不会看到页面显示方式的任何显著差异。所有六列都将在那里,水平排列(图 1-14 )。

图 1-14
正好 576 像素宽—仍然是 6 列宽
当你再缩小 1 个像素到 575 像素时,情况就会发生变化。您将看到以下内容(图 1-15 )。

图 1-15
低于sm断点时堆叠六列
这是因为我使用了类col-sm-2。同样,对于每个小于 576px 的显示宽度,该类将列一个接一个地堆叠,对于任何大于或等于 576px 的宽度,该类将列保持水平。
从上图中可以看出,最初的两列宽现在变成了 12 列宽,占据了整个行。
Bootstrap 的好处在于,你可以在同一个div上应用多种不同的断点,以适应不同设备的网格布局。
为了理解我的意思,请看下面的例子。假设对于小型及以上设备,我希望有六列,但对于较小的设备(小于 576px),我不希望每行一列,而是每行两列。
因此
-
对于小型或大型设备,我需要六列。这意味着我需要将
col-sm-2类用于divs(将sm用于小列,将2用于六列,因为12/6给出了2)。 -
对于超小型设备,我希望每行有两列。因此,我需要对
divs使用col-6类(对于 extrasmall,我没有将设备宽度的符号插入类名,因为默认值是两列的xs和6,因为12/2给出了6)。
让我们试试那个。更改前面的 HTML 页面的内容,使其类似于清单 1-13 中的内容。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>Listing 1-12</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-6 col-sm-2">
1
</div>
<div class="col-6 col-sm-2">
2
</div>
<div class="col-6 col-sm-2">
3
</div>
<div class="col-6 col-sm-2">
4
</div>
<div class="col-6 col-sm-2">
5
</div>
<div class="col-6 col-sm-2">
6
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 1-13Two Columns on Extrasmall Displays, but Six on Small Displays and Wider
如果您保存前面的代码并重新加载您的页面,当它的宽度为 575 像素(或更小)时,您会看到,现在您的页面每行有两列(图 1-16 )。

图 1-16
超小型设备上的两列
但是,如果您将显示区域的宽度放大到大于或等于 576px,您将看到您的页面每行有六列。
这就是实现网格响应的方式。
Note
有人可能会说,“等一下!在超小型设备上,div have a number后缀(-6)内的列加起来是 36,而不是 12。您需要知道,Twitter Bootstrap 会自动将第 12 列以上的列换行到新的一行。
前面的网页实际上有一个网格布局断点——576 像素,即低于 576 像素的显示宽度与等于或大于 576 像素的显示宽度。您可以将相同的概念应用于同一网格中的第二个断点。例如,对于大于 576px(小)的显示区域,您可能希望列数为 3,而对于大于或等于 768px(中等或更宽)的显示区域,您可能希望列数为 6。
所以我想要的是以下内容:
-
对于超小型设备(< 576 像素),每行两列(因此,
col-6) -
对于小型设备(> = 576 像素,< 768 像素),每行三列(因此,
col-sm-4) -
对于中等或更宽的设备(> =768px),每行六列(因此,
col-md-2)
现在我知道我想要实现什么,这很简单。我将把前面的类应用到我的专栏divs,我就完成了(列表 1-14 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>Listing 1-14</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-6 col-sm-4 col-md-2">
1
</div>
<div class="col-6 col-sm-4 col-md-2">
2
</div>
<div class="col-6 col-sm-4 col-md-2">
3
</div>
<div class="col-6 col-sm-4 col-md-2">
4
</div>
<div class="col-6 col-sm-4 col-md-2">
5
</div>
<div class="col-6 col-sm-4 col-md-2">
6
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 1-14Two for xs
, Three for sm
, and Six for Wider Displays
现在,如果你将浏览器的宽度调整为 760 像素,你会看到每行有三列。参见图 1-17 。

图 1-17
小尺寸显示器上的三列
但是如果你把它放大到比 768 像素更宽,它将每行显示 6 列(图 1-18 )。

图 1-18
中型显示器上的六列
任务和测验
Task Details
-
您需要实现一个多列布局,就像本章中介绍的那样。以下是根据显示宽度对网格的要求:
-
对于超小型显示器,每行应该显示一列。
-
对于小型显示器,每行应该显示两列。
-
对于中型显示器,每行应该显示三列。
-
对于大型显示器,每行应该显示四列。
-
对于超大显示器,每行应该显示六列。
祝你好运!
关键要点
恭喜你!你刚刚读完了第一章,你已经知道了很多关于如何让你的网页响应的事情。以下是你学到的一些重要东西:
-
最简单的 Twitter 引导页面和它需要包含的内容
-
集装箱
-
这一排分开了
-
列分区是行分区的子分区
-
如何将行拆分成几个等宽或不等宽的列
-
不同的引导断点
-
如何使用不同的类来定义不同显示宽度的页面布局
在下一章中,您将围绕 Twitter Bootstrap 网格系统使用一些更高级的技术。
二、高级网格技术
在前一章中,您开始学习 Twitter Bootstrap 网格系统。在这一章中,你将继续你在网格系统上的工作,但是你将使用一些不同的,更高级的技术来做类似的和其他的事情。
学习目标
你会学到的
-
如何使用行列
-
如何垂直对齐内容
-
如何水平对齐
-
如何使用少于 12 个的可用列
-
如何将内容和网格嵌套在另一个网格中
-
Twitter 引导默认是什么
行上的快捷方式:行列
你现在要探索另一套备选方案,以便完成你在第 1 “开始”一章中所做的所有事情这被称为行列,它是一组帮助你定义一行的列的类,但是在row div使用它们,而不是在col div使用它们。
示例:所有设备的六列布局
假设我想要实现一个适用于所有设备宽度的六列布局。清单 2-1 是我的代码。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>Listing 2-1</title>
</head>
<body>
<div class="container">
<div class="row row-cols-6">
<div class="col">
1
</div>
<div class="col">
2
</div>
<div class="col">
3
</div>
<div class="col">
4
</div>
<div class="col">
5
</div>
<div class="col">
6
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 2-1Six-Column Layout Using Row Columns
如果你将前面的代码保存到你的index.html页面并加载到你的浏览器中,你将会看到类似图 2-1 中的内容。

图 2-1
使用 row-cols-*类的六列
这正是我想要的。是怎么创造出来的?
-
行 div 被属性化为类
row-cols-6。数字6正是我想要的列数。 -
然后每个列
div只有col类,因为我希望所有的列都有相同的宽度。
当然,我现在听到你说,“等等。如果我只使用了row类而没有使用row-cols-6类,同样的事情也会发生。”你可能是对的。在前一个例子中使用row-cols-*并没有增加太多的价值。但是让我们再举一个例子,在这个例子中行列类更有价值。
示例:三列表示中型,六列表示大型
现在我想创建一个响应网格
-
三列用于所有设备,包括中型设备
-
六列,适用于所有配备大显示屏或更宽显示屏的设备
您已经知道如何在列div级别使用col-*类来实现这一点。在这里,我们将使用行级别的row-cols-*类来实现。参见清单 2-2 。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>Listing 2-2</title>
</head>
<body>
<div class="container">
<div class="row row-cols-3 row-cols-lg-6">
<div class="col">
1
</div>
<div class="col">
2
</div>
<div class="col">
3
</div>
<div class="col">
4
</div>
<div class="col">
5
</div>
<div class="col">
6
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 2-2Responsive Breakpoints Using Row Columns
你看到这有多容易了吗?
-
我保持列
divs只有col类。 -
我使用两个行列类
row-cols-3和row-cols-lg-6来根据设备的宽度告诉我想要多少列,特别是-
row-cols-3适用于除以下类别定义的设备以外的所有设备。注意数字3是我们想要占据的列数。 -
row-cols-lg-6对于所有大屏或更宽显示屏的设备,即> =992px。
-
例如,如果您保存您的页面并在浏览器上重新加载,您将看到以下宽度为 991 像素的页面(图 2-2 )。

图 2-2
低于 992 像素时为三列
当您将宽度再放大 1 个像素,达到 992px 时,您将立即获得 6 列(图 2-3 )。

图 2-3
992px 和更宽型号的六列
在表 2-1 中,我将第一个解决方案与列级别的col-*类进行了比较,并将您刚刚学到的最新解决方案与行级别的row-cols-*类进行了比较。
表 2-1
比较col-*和row-cols-*之间的代码
col-*在列级
|
row-cols-*在行级别
|
| --- | --- |
| <div class="row">``<div class="col-4 col-lg-2">``1``</div>``<div class="col-4 col-lg-2">``2``</div>``<div class="col-4 col-lg-2">``3``</div>``<div class="col-4 col-lg-2">``4``</div>``<div class="col-4 col-lg-2">``5``</div>``<div class="col-4 col-lg-2">``6``</div>``</div> | <div class="row row-cols-3 row-cols-lg-6">``<div class="col">``1``</div>``<div class="col">``2``</div>``<div class="col">``3``</div>``<div class="col">``4``</div>``<div class="col">``5``</div>``<div class="col">``6``</div>``</div> |
我重复一遍,这样就很清楚了:
-
当我使用类在列
div级别指定列宽时,我指定了我的列将占用的列数(12 列中的一列)。例如,如果我希望我的列有三列宽,我使用col-3。 -
当我在行
div级别使用类时,我只需指定行中需要的列数。然后 Bootstrap 会自动计算每一列的宽度。 -
显然,当我使用行类时,我将该行的所有列的宽度设置为相同的大小。如果我想在同一行中有不同宽度的列,我必须在列级使用列类
div。
竖向定线
您已经学习了如何使用 12 列宽的网格进行布局,但是 Bootstrap 允许您在纵轴上对齐行内的内容。
中间对齐
你如何将你的内容放在一个高行的中间,如图 2-4 所示?

图 2-4
高行中间的内容
在上图中,您可以看到该行的内容,实际上,该行由三列组成,放置在垂直轴的中心。在清单 2-3 中,您可以看到如何创建这个页面。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>Listing 2-3</title>
</head>
<body>
<div class="container">
<div class="row align-items-center">
<div class="col">
1
</div>
<div class="col">
2
</div>
<div class="col">
3
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 2-3Content in the Middle of a Tall Row
差异由在row div的类align-items-center完成。它指示浏览器在纵轴中行的中心位置绘制这个div的子列。
在之前,你保存并加载这个页面到你的浏览器上,你必须给你的行一些最小高度;否则,你看不出任何区别。将清单 2-4 用于您的index.css文件。
.row {
background-color: #4e9013;
color: white;
min-height: 200px;
}
.col {
background-color: #31907c;
}
Listing 2-4CSS File That Gives the Row a Minimum Height
前面的 CSS 具有将min-height应用于行divs的规则。这将允许您在纵轴方向的行中心看到子divs的内容。
顶部和底部对齐
还有另外两个类可以在行div级别应用,它们与垂直对齐有关:align-items-start和align-items-end。让我们用这些来创建如图 2-5 所示的页面。

图 2-5
使用各种垂直对齐方式
如你所见,中间和底部的行分别有对齐center和end,。我很确定你是在没有我的帮助下编写 HTML 的,但是为了完整起见,让我们在这里包含代码(清单 2-5 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>Listing 2-5</title>
</head>
<body>
<div class="container">
<div class="row align-items-start">
<div class="col">
1-start
</div>
<div class="col">
2-start
</div>
<div class="col">
3-start
</div>
</div>
<div class="row align-items-center">
<div class="col">
1-center
</div>
<div class="col">
2-center
</div>
<div class="col">
3-center
</div>
</div>
<div class="row align-items-end">
<div class="col">
1-end
</div>
<div class="col">
2-end
</div>
<div class="col">
3-end
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 2-5Align Top, Middle, and Bottom
不要忘记让你的index.css有规则,使你的行有最小高度,这样你就可以看到垂直对齐。清单 2-6 包含了这样的规则。
.row {
min-height: 200px;
margin-bottom: 30px;
color: white;
}
.align-items-start {
background-color: #4e9013;
}
.align-items-center {
background-color: #902e07;
}
.align-items-end {
background-color: #8DC5CC;
}
.col {
background-color: #367390;
}
Listing 2-6index.css File That Gives Rows Minimum Height
同一行内不同的垂直对齐
最后,有时您希望同一行中的列具有不同的垂直对齐方式。图 2-6 就是这样一个页面的例子。

图 2-6
在同一行中使用不同的垂直对齐方式
为了实现这一点,我在col级别使用了一些特殊的类。下面是前一页的 HTML 代码(清单 2-7 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>Listing 2-7</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col align-self-start">
1-self-start
</div>
<div class="col align-self-center">
2-self-center
</div>
<div class="col align-self-end">
3-self-end
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 2-7Different Vertical Alignments Within the Same Row
使用下面的index.css(清单 2-8 )来对前面的 HTML 内容进行样式化,这样您就可以得到如图 2-6 所示的结果。
.row {
background-color: #4e9013;
min-height: 200px;
margin-bottom: 30px;
color: white;
}
.align-self-start {
background-color: #441180;
}
.align-self-center {
background-color: #8DC5CC;
}
.align-self-end {
background-color: #902e07;
}
Listing 2-8CSS for Listing 2-7
小于 12 和水平对齐
我将继续向您解释如何在水平方向上对齐列,这在内容没有占据整个页面宽度时更有用。
左边对齐
到目前为止,您的行从左到右显示内容。它们占据了整个集装箱的宽度。有些情况下,您希望占据部分宽度。例如,您希望内容位于前两列,其余水平空间为空。看下面图 2-7 中的例子。

图 2-7
左对齐列
如图 2-7 所示,第二行和第三行的列占据了网格的左侧。第二行占据前两列,第三行占据前三列。你如何实现这一点?清单 2-9 中给出了 HTML 代码。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>Listing 2-9</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
<div class="col">4</div>
<div class="col">5</div>
<div class="col">6</div>
<div class="col">7</div>
<div class="col">8</div>
<div class="col">9</div>
<div class="col">10</div>
<div class="col">11</div>
<div class="col">12</div>
</div>
<div class="row justify-content-start row-1">
<div class="col-2 col">
2-columns-width
</div>
</div>
<div class="row justify-content-start row-2">
<div class="col-3 col">
3-columns-width
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 2-9Left-Aligned Columns
在将前面的 HTML 加载到你的浏览器中之前,确保你的index.css文件中有正确的 CSS 规则,类似于清单 2-10 中的内容。
* {
color: white;
}
.row {
background-color: black;
}
.row-1 .col {
background-color: #902e07;
}
.row-2 .col {
background-color: #31907c;
}
Listing 2-10CSS for Listing 2-9
在清单 2-9 中,类justify-content-start被附加在第二和第三行divs上。
居中和右对齐
但事实上,这并不十分有用。即使没有将这个类附加到 row divs,也可以实现同样的效果。当您使用相应的*-center和*-end类时,事情变得更加有趣,如清单 2-11 所示。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>Listing 2-11</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
<div class="col">4</div>
<div class="col">5</div>
<div class="col">6</div>
<div class="col">7</div>
<div class="col">8</div>
<div class="col">9</div>
<div class="col">10</div>
<div class="col">11</div>
<div class="col">12</div>
</div>
<div class="row justify-content-center row-1">
<div class="col-2 col">
2-columns-width
</div>
</div>
<div class="row justify-content-end row-2">
<div class="col-3 col">
3-columns-width
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 2-11Use *-center and *-end Classes
保存前面的页面,并将其加载到您的浏览器中。您将会看到类似于图 2-8 中所示的内容。

图 2-8
居中和右对齐
因此,在第divs行的这些justify-content-*类是有用的,因为它们允许你对齐而不必使用空的 div。
间距
如果您有三个内容列,并且希望它们以等间距水平对齐,那会怎么样呢?图 2-9 有这种情况的例子。

图 2-9
间距为的列
你必须使用的类是justify-content-between。清单 2-12 中给出了 HTML 代码。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>Listing 2-12</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
<div class="col">4</div>
<div class="col">5</div>
<div class="col">6</div>
<div class="col">7</div>
<div class="col">8</div>
<div class="col">9</div>
<div class="col">10</div>
<div class="col">11</div>
<div class="col">12</div>
</div>
<div class="row justify-content-between">
<div class="col-2">
2-columns, left
</div>
<div class="col-2">
2-columns, middle
</div>
<div class="col-2">
2-columns, right
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 2-12Using justify-content-between
周围的空间
最后,有时你希望空间围绕着你的内容。参见图 2-10 中的示例。

图 2-10
满足于周围的空间
为了实现这一点,您需要使用类justify-content-around。在row div级连接它,如清单 2-13 所示。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>Listing 2-13</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
<div class="col">4</div>
<div class="col">5</div>
<div class="col">6</div>
<div class="col">7</div>
<div class="col">8</div>
<div class="col">9</div>
<div class="col">10</div>
<div class="col">11</div>
<div class="col">12</div>
</div>
<div class="row justify-content-around">
<div class="col-2">
2-columns, left
</div>
<div class="col-2">
2-columns, middle
</div>
<div class="col-2">
2-columns, right
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 2-13Content with Space Around
使用清单 2-14 中给出的index.css文件加载前面的代码。
* {
color: white;
}
.row {
background-color: darkblue;
}
.col-2:nth-child(1) {
background-color: #902e07;
}
.col-2:nth-child(2) {
background-color: #31907c;
}
.col-2:nth-child(3) {
background-color: #89906b;
}
Listing 2-14CSS Content for Listing 2-13
嵌套
我将通过给出一些关于如何在一个网格中嵌套另一个网格的建议来结束这次与 Twitter Bootstrap 的初次接触。
允许将一个网格嵌套在另一个网格中,并遵循适用于根网格的相同规则。你会怎么做?你必须在父col div中使用一个row div和子col divs。
图 2-11 显示了一个网格嵌入另一个网格的例子。

图 2-11
另一个内部的嵌套网格
让我们看看这个页面的 HTML 代码(清单 2-15 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/index.css" type="text/css">
<title>Listing 2-15</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
<div class="col">4</div>
<div class="col">5</div>
<div class="col">6</div>
<div class="col">7</div>
<div class="col">8</div>
<div class="col">9</div>
<div class="col">10</div>
<div class="col">11</div>
<div class="col">12</div>
</div>
<div class="row parent">
<div class="col-6">
<div class="row nested row-cols-md-3 row-cols-lg-6">
<div class="col">
1-nested
</div>
<div class="col">
2-nested
</div>
<div class="col">
3-nested
</div>
<div class="col">
4-nested
</div>
<div class="col">
5-nested
</div>
<div class="col">
6-nested
</div>
</div>
</div>
<div class="col-4">
4-columns
</div>
<div class="col-2">
2-columns
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 2-15Nested Grid Inside Another
从前面的代码中可以看出,在带有类parent的row div中,我有一个col div(带有类col-6)。后者div内部有另一个row(带有类nested)来启动嵌套网格。
类parent和nested不是 Twitter 引导类。它们是我的自定义 CSS 类,帮助用存在于index.css(清单 2-16 )中的规则设计页面。
* {
color: white;
}
.row {
background-color: darkblue;
}
.row.parent {
background-color: #367390;
}
.row.nested {
background-color: #31907c;
}
Listing 2-16index.css for Listing 2-15
看看嵌套的row div如何使用row-cols-*类来指定不同断点上的列数。例如,如果您将浏览器窗口缩小到 780px,这是一个中等大小的设备,您将看到嵌套网格有三列布局,这是由于类row-cols-3。见图 2-12 。

图 2-12
嵌套网格在中型设备上有三列
Twitter 引导默认设置
在我结束这一章之前,我想带你快速浏览一下最重要的默认设置(表 2-2 ),包括 Twitter Bootstrap,并与没有它的默认设置进行比较。
表 2-2
Twitter 引导默认与浏览器默认
| |Twitter 引导
|
没有 Twitter 引导
|
| --- | --- | --- |
| html 元素框大小 | 边框 | 内容盒 |
| html 元素字体系列 | 无衬线字体 | 英国泰晤士报(1785 年创刊) |
| html 元素字体大小 | 16px | 16px |
| 正文元素字体系列 | -苹果系统、闪烁 MAC 系统字体、Segoe UI、Roboto、helvetica neue、Arial、noto sans、sans-serif、Apple Color Emoji、segoe e moji、Segoe UI Symbol、Noto Color Emoji | 英国泰晤士报(1785 年创刊) |
| 正文元素字体大小 | 16px | 16px |
| 正文元素行高 | 24px | 标准 |
| 主体元素颜色 | #212529 | #000 |
| 正文元素背景色 | #fff | rgba(0,0,0,0);因此是透明的 |
| 主体元素框尺寸 | 边框 | 内容盒 |
| 主体元素边距 | Zero | 8px |
如果你在本地电脑上下载了 Twitter Bootstrap,你可以阅读更多关于 Twitter Bootstrap 默认设置的内容。你可以访问 https://getbootstrap.com/docs/4.4/getting-started/download/ ,然后点击按钮下载。这将下载准备好的 CSS 非精简代码(寻找文件css/bootstrap.css)。
任务和测验
Task Details

图 2-13
任务:响应图像登记表页面
-
您需要实现一个包含图像名册的页面。
-
你需要使用 Twitter Bootstrap 工具来使其响应迅速。
-
这是页面在超大显示器(>= 1200 像素)上的外观(图 2-13 )。
如您所见,它在页面上均匀地放置了六个图像。

图 2-14
页面在中型和大型设备上的外观
- 在中型(> =768px)和大型(< 1200px)设备上,该页面应如图 2-14 所示。
如图 2-14 所示,现在,图像被排列成每行有三幅图像。因此,所有图像都显示在两行中。

图 2-15
小型和超小型设备页面
- 在小型和超小型设备(< 768px)上,该页面应如图 2-15 所示。
正如您在图 2-15 中看到的,现在每个图像都显示在它自己的行上。
-
标题是一个
h1元素。 -
img标签应该使用width和height 100%来设计样式,这样它们就可以占据所有给定的空间。
祝你好运!
关键要点
以下是你学到的一些重要东西:
-
如何实现垂直对齐
-
如何实现水平对齐
-
如何将一个网格嵌套在另一个网格中
在下一章中,你将通过实现一个真实的项目来学习 Bootstrap。它将有一个响应的导航栏,它将根据显示器的宽度改变它的外观。
三、目标项目 1
在前一章中,您已经了解了 Twitter Bootstrap 网格系统。在这一章中,你将开发一个顶部固定有导航栏的网页,如图 3-1 所示。

图 3-1
带有顶部导航栏的基本模板
这个导航条是响应性的,这意味着它可以在小显示设备上同样显示。在这些情况下,菜单隐藏在汉堡图标后面(图 3-2 )。

图 3-2
这是一个网站在移动设备上的外观
当用户点击汉堡图标时,菜单展开,如下图(图 3-3 )。

图 3-3
菜单选项出现在汉堡图标上点击
您将开发这个网页,但同时,您将理解 Twitter 引导类是如何工作的。
学习目标
-
学习一步一步地为你的网站建立一个导航栏。
-
让导航栏有反应。
-
了解如何创建一个汉堡包形状的按钮,以及如何使它展开菜单选项。
-
学习如何让一个段落的内容突出。
-
了解如何使您的主要内容区域不被导航栏隐藏。
介绍
这一章和接下来的章节将会教你框架的概念,同时尝试创建一个项目。让我们从我们的第一个项目开始。
假设我们要构建图 3-4 中的如下网站。

图 3-4
目标项目 1—带有顶部导航栏的基本模板
本项目具有以下特点:

图 3-5
这是一个网站在移动设备上的样子
- 它有一个导航栏。这个导航栏是有反应的。这意味着当你调整浏览器的大小来模拟手机的大小时,你会看到类似图 3-5 的东西。
正如你所看到的,菜单选项已经被折叠,变成了一个汉堡包图标。如果用户想要获得菜单选项列表,他们需要点击这个图标(图 3-6 )。

图 3-6
菜单选项出现在汉堡图标上点击
在这个网站上,你可以从 Twitter Bootstrap 免费获得其他功能。例如,当您将鼠标悬停在选项上时,您会看到选项的颜色和强度会发生变化。
让我们尝试使用 Twitter Bootstrap 从零开始建立这个网站。
从 HTML 开始
让我们从基本的 HTML 开始,它包括一个导航栏和一个将成为菜单选项的项目列表,如下所示(清单 3-1 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Listing 3-1</title>
</head>
<body>
<nav>
<ul>
<li ><a href="#">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</nav>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 3-1Starting with a nav Element and List of Menu Items
将前面的代码保存到文件index.html中,并在浏览器上加载页面。注意引用的stylesheets/main.css暂时不包含任何东西。但是创建这个文件以便您的页面可以找到它。
您将看到以下内容(图 3-7 )。

图 3-7
有导航栏和菜单项但没有样式的页面
我想这是意料之中的。body元素只包含一个块元素nav和一个带有菜单选项的ul。注意,我们使用语义 HTML5 元素nav,而不仅仅是一个div。
上课了nav
您将首先在保存菜单选项的ul元素上添加类nav。这将从列表中删除项目符号。进行以下更改。而不是<ul>,写<ul class="nav">。保存文件并重新加载页面。您将看到以下内容(图 3-8 )。

图 3-8
在ul元素上添加了类nav
导航项目和导航链接
现在让我们在菜单项周围留出一些空间,因为现在它们是一个紧挨着一个的。
为了实现这一点,您将在li元素上添加类nav-item,在锚a元素上添加类nav-link。阅读清单 3-2 ,看看你的 HTML 页面的当前状态应该是怎样的。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Listing 3-2</title>
</head>
<body>
<nav>
<ul class="nav">
<li class="nav-item">
<a class="nav-link" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
</ul>
</nav>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 3-2Menu Items on the Same Line, One Separate from the Other
如果您在浏览器上加载前面的页面,您将看到以下内容(图 3-9 )。

图 3-9
菜单项分开
折叠和展开
为了使菜单项列表可折叠,也就是说,在小设备上被替换为汉堡包图标,当点击时,将获得菜单选项,您需要在nav元素上添加一个特殊的类,并且您需要用特殊的类将可折叠/可展开的内容包装到一个div中,如清单 3-3 所示。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Listing 3-3</title>
</head>
<body>
<nav class="navbar-expand-lg">
<div class="collapse navbar-collapse">
<ul class="nav">
<li class="nav-item">
<a class="nav-link" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
</ul>
</div>
</nav>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 3-3Make Menu Options Collapse and Expand
为了使菜单选项折叠和展开,您所做的工作如下:
-
您已经在
nav元素上添加了类navbar-expand-lg。这指示浏览器在lg断点处展开内容,即显示大于或等于 992 像素的内容。显然,如果您希望菜单扩展为宽度为> =768px 的显示,您可以使用另一个断点,例如md断点。 -
您已经用类
collapse和navbar-collapse将ul元素包装成了一个div元素。这使得浏览器知道它需要折叠和展开哪些内容。
如果你将新的 HTML 内容加载到你的浏览器中,并将像素宽度设置为 991px,那么你会看到一个如下图所示的空白页(图 3-10 )。

图 3-10
宽度小于 992 像素的空白页
但是,如果您扩展到 992px,那么您会看到菜单选项再次出现(图 3-11 )。

图 3-11
菜单选项出现在 992px 上
品牌链接
如果你回过头再看最后的结果,你会看到有带文本John Woo的链接,当页面缩小到移动大小时没有隐藏。它总是可见的,它应该是一个将用户带到网站主页的链接。它不是菜单项列表的一部分。
让我们把它放在可折叠的div之上,但是仍然在nav元素之内(列表 3-4 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Listing 3-4</title>
</head>
<body>
<nav class="navbar-expand-lg">
<a href="#">John Woo</a>
<div class="collapse navbar-collapse">
<ul class="nav">
<li class="nav-item">
<a class="nav-link" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
</ul>
</div>
</nav>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 3-4Add the Link That Would Take the User to the Home Page
如果您保存前面的代码并重新加载您的页面,您将在左侧看到John Woo链接,如果您缩小页面,它仍然可见,不会像菜单选项一样消失(图 3-12 )。

图 3-12
品牌链接独立于菜单选项
让品牌链接突出
左上角的品牌链接需要和菜单在同一层;它需要突出一点。让我们这样做吧
-
将类
navbar添加到nav包装元素 -
将类
navbar-brand添加到锚元素
Caution
nav包装元素上的navbar类对于导航栏的整体风格至关重要,而不仅仅是品牌链接。
清单 3-5 是你需要在你的 HTML 页面中拥有的,以使这个工作。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Listing 3-5</title>
</head>
<body>
<nav class="navbar navbar-expand-lg">
<a class="navbar-brand" href="#">John Woo</a>
<div class="collapse navbar-collapse">
<ul class="nav">
<li class="nav-item">
<a class="nav-link" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
</ul>
</div>
</nav>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 3-5Brand Link on the Same Line and Standing Out
如果您在浏览器上加载前面的 HTML 页面,您将看到图 3-13 所示的内容。

图 3-13
左侧突出的品牌链接
给你的导航条添加一些颜色
让我们给你的导航条添加一些颜色。为了做到这一点,你必须
-
在
nav元素中使用navbar-dark或navbar-light类之一。 -
将它与背景颜色实用程序类结合起来。
前者主要处理字体颜色,而后者处理背景颜色。通常你想将*-dark类与深色背景色结合,将*-light类与浅色背景色结合。
背景颜色实用程序在图 3-14 中列出。

图 3-14
背景颜色实用程序类
Caution
颜色类navbar-dark和navbar-light被设计成期望ul元素拥有类navbar-nav。所以我们也要加上这个。
在清单 3-6 中,我们应用了bg-dark背景颜色工具类,结合了导航栏的navbar-dark配色方案。我们还将类navbar-nav添加到ul元素中。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Listing 3-6</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">John Woo</a>
<div class="collapse navbar-collapse">
<ul class="navbar-nav nav">
<li class="nav-item">
<a class="nav-link" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
</ul>
</div>
</nav>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 3-6Coloring the Navigation Bar
如果您在浏览器上加载前面的 HTML 页面,您将看到图 3-15 所示的内容。

图 3-15
给导航栏着色
另外,将鼠标指针悬停在菜单选项上。你会看到链接变得越来越轻。
在小型设备上添加按钮以展开菜单选项
让我们添加一个按钮。这将被点击以展开小型设备上的菜单选项。参见清单 3-7 。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Listing 3-7</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">John Woo</a>
<button type="button">
</button>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
</ul>
</div>
</nav>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 3-7Add a Button That Will Toggle the Menu On and Off on Small Devices
您已经将按钮添加为品牌锚的同级,但是在它之后。如果您在浏览器上加载该 HTML 页面,您将看到以下内容(图 3-16 )。

图 3-16
打开和关闭菜单的非样式按钮
这太糟糕了。确实如此。但这是一个开始。
使按钮只出现在小型设备上
目前,按钮的问题是它总是出现。您希望它只出现在宽度小于您在nav元素上设置的扩展断点的设备上。您设置的断点是lg,这意味着您希望按钮出现在宽度为< 992px 的显示器上。
为了做到这一点,您可以添加类navbar-toggler。就这么办吧。参见清单 3-8 。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Listing 3-8</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">John Woo</a>
<button type="button" class="navbar-toggler">
</button>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
</ul>
</div>
</nav>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 3-8Make the Button Appear Only on Widths Below the Expanded Breakpoint
现在,当您的显示器> =992px 时,该按钮不会出现(图 3-17 )。

图 3-17
菜单可见;用于切换的按钮不可见(> =992px)
当你缩小 1 个像素,到 991px,那么你会看到菜单消失,按钮出现(图 3-18 )。

图 3-18
菜单隐藏,但按钮存在(< 992 像素)
按钮以一种很难看到的方式出现。这是固定的下一步。
创建汉堡图标
这个按钮在小设备上看起来不太好,这是因为它里面没有实际的内容。为了创建汉堡的视觉图标,Twitter Bootstrap 为您提供了类navbar-toggler-icon。您需要将它应用到button元素中的span元素上。参见清单 3-9 。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Listing 3-9</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">John Woo</a>
<button type="button" class="navbar-toggler">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
</ul>
</div>
</nav>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 3-9Creating the Hamburger Icon
如果在宽度为 991 像素的显示器上加载前面的 HTML 页面,您将看到以下内容(图 3-19 )。

图 3-19
汉堡图标现在出现
向按钮添加行为
如果你试着点击汉堡包按钮,什么也不会发生。您现在需要向按钮添加行为。单击该按钮时,菜单选项会展开。您将通过向button元素添加两个data-*属性来实现这一点:
-
data-toggle="collapse",它告诉 Twitter Bootstrap 这个按钮用于折叠/展开 HTML 文档的特定区域 -
data-target="#navbar",它告诉 Twitter Bootstrap 需要折叠/展开的特定区域是用 CSS 选择器#navbar选择的区域。当然,由于在您的 HTML 文档中没有这样的元素(id 为navbar),但是您想要折叠/展开的元素是保存菜单项列表的容器,您将向这个特定的div添加值为navbar的id属性。让我们这样做(清单 3-10 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Listing 3-10</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">John Woo</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
</ul>
</div>
</nav>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 3-10Make the Button Toggle the Menu
如果您保存前面的内容并在浏览器上加载页面,您现在将会看到该按钮可以打开和关闭菜单。在图 3-20 中,我展示了菜单展开后的样子。

图 3-20
单击按钮后展开的菜单
对我们的导航栏的最后润色
-
fixed-toponnav元素将固定导航栏在页面顶部的位置。 -
您还将添加一些元素和属性,以使整个导航栏准备好用于辅助技术,例如,屏幕阅读器。
-
您还将把类
active添加到第一个菜单项中,以表明您位于该链接所对应的页面上。
这是你的页面的最终版本,导航栏已经准备好了(清单 3-11 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Listing 3-11</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<a class="navbar-brand" href="#">John Woo</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar"
aria-controls="navbar"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
</ul>
</div>
</nav>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 3-11Final HTML Page
如果保存前面的内容并在 992 像素宽的显示器上加载页面,您将看到图 3-21 。

图 3-21
992px 上带有导航栏的最终页面
你的导航栏工作得很好,你没有写一行 CSS 或 JavaScript 代码。是不是很神奇?这都要感谢 Twitter Bootstrap。
添加主要内容
您已经添加/创建了导航栏。现在让我们添加页面的主要内容(清单 3-12 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Listing 3-12</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<a class="navbar-brand" href="#">John Woo</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar"
aria-controls="navbar"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
</ul>
</div>
</nav>
<div class="container">
<h1>John Woo Portfolio</h1>
<p>Full-Stack Web Developer that can turn your ideas to fantastic responsive Web applications</p>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 3-12We Add the Main Content
您已经在nav元素下面添加了一个带有类container的div。在这个新的div中,您添加了一个h1和一个p元素,其中包含一些内容。
让我们保存内容并在浏览器上加载页面。您将看到以下内容(图 3-22 )。

图 3-22
隐藏在顶部导航栏后面的主要内容
我猜你能看出问题所在。h1标题隐藏在顶部导航栏的后面。
为了解决这个问题,我们必须添加一些自定义的 CSS。你将不得不要求body把它的实际内容放在顶部以下很多像素的位置,就像导航条的高度一样。图 3-23 描述了如何在开发者工具的帮助下找出顶部导航栏的高度。

图 3-23
计算顶部导航栏的高度
从开发者工具中可以看到,顶部导航栏的高度是 56px,通过添加顶部和底部填充和内容高度计算得出。
有了 56px,让我们在stylesheets/main.css文件中添加一些内容(列出 3-13 )。
body {
padding-top: 56px;
}
Listing 3-13Content of the main.css File
现在,如果你再次加载你的页面(确保它引用了stylesheets/main.css),它将看起来如下(图 3-24 )。

图 3-24
h1 现在可见
突出段落内容
与原网站有一些小的不同。一种是段落内容是普通的、正常大小的文本。你想让它突出。您将为此使用类lead(再次由 Twitter Bootstrap 提供给我们)。
让p元素拥有那个类(清单 3-14 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Listing 3-14</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<a class="navbar-brand" href="#">John Woo</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar"
aria-controls="navbar"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
</ul>
</div>
</nav>
<div class="container">
<h1>John Woo Portfolio</h1>
<p class="lead">Full-Stack Web Developer that can turn your ideas to fantastic responsive Web applications</p>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 3-14Make the Paragraph Stand Out
如果您保存并再次加载您的页面,您将会看到图 3-25 。

图 3-25
段落突出
将导航栏内容与主页内容对齐
到目前为止,一切顺利,但是还有一个问题需要解决。导航栏的内容与页面的主要内容不一致。见图 3-26 中的问题。

图 3-26
导航栏内容与主页内容不对齐
您可以通过用类container将导航栏内容包装到一个div中来解决这个问题,就像您对页面主要内容所做的那样(清单 3-15 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Listing 3-15</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand" href="#">John Woo</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar"
aria-controls="navbar"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<h1>John Woo Portfolio</h1>
<p class="lead">Full-Stack Web Developer that can turn your ideas to fantastic responsive Web applications</p>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 3-15Wrap Nav Bar Content into a Container
如果您在浏览器上保存并加载该页面,您将看到以下内容(图 3-27 )。

图 3-27
导航栏内容与页面主要内容对齐
干得好!这与您想要构建的原始页面相匹配。
结束语
您已经创建了一个具有响应导航栏的网站,而没有编写任何 CSS 代码。Twitter Bootstrap 为你提供了一切。您只需要使用正确的类(在一种情况下,使用两个data-*属性)。
任务和测验
TASK DETAILS
-
请注意以下事项:
-
主要内容要居中。
-
主要内容上方和导航栏下方有大量空白。确保你的页面上有相同的内容。
-
导航栏应该有反应,当你在小显示器上加载你的页面时,菜单项应该是隐藏的。在它们的位置,应该显示一个汉堡包图标。单击图标时,将展开带有菜单选项的列表。
-
-
You need to implement a web page with a responsive navigation bar, like the following (Figure 3-28).
![img/497763_1_En_3_Fig28_HTML.jpg]()
图 3-28
带有导航栏的任务项目
祝你好运!
关键要点
恭喜你!现在,您知道了如何实现一个响应式导航栏。以下是你学到的一些重要东西:
-
如何实现一个带有菜单选项的导航栏,这些菜单选项在小型设备上是隐藏的,在大型设备上是可见的。
-
对于小型设备,您实现了一个按钮,单击该按钮可以打开/关闭带有选项的菜单。
-
您还了解了如何给导航栏着色以及如何定位它。
-
您已经学习了如何将内容放在主页上,而不被顶部导航栏隐藏。
-
你已经学会了如何让一个段落引人注目。
在下一章,你将会熟悉最流行的 Twitter 引导组件,比如按钮、徽章、标签等等。
四、主题参考:第一部分
在前一章中,您已经创建了一个小型的 Twitter Bootstrap 项目。现在,您将创建一个引用一些最常用的 Twitter 引导组件的页面。
在这个主题参考项目的第一部分,你将学习如何在导航栏中创建下拉菜单(图 4-1 )。

图 4-1
导航栏中的下拉菜单
您将学习如何创建突出的文本区域,称为大屏幕(图 4-2 )。

图 4-2
大屏幕示例
你将学习如何快速创建好看的按钮,如下所示(图 4-3

图 4-3
按钮示例
以及如图 4-4 所示的表格。

图 4-4
表格示例
您还将学习如何创建好看的标签和标记(图 4-5

图 4-5
标签示例
以及徽章(图 4-6 )。

图 4-6
徽章示例
在主题参考项目的第二部分中,您将学习如何在选项卡下对信息进行分组(图 4-7 )。

图 4-7
制表符示例
您将学习如何创建警报(图 4-8

图 4-8
警报示例
还有好看的进度条(图 4-9 )。

图 4-9
进度条示例
您将学习如何创建具有突出标题和独立正文的卡片(图 4-10 )。

图 4-10
卡片示例
最后,您将学习如何创建令人印象深刻的图像旋转木马。
在第二部分结束时,您将被要求创建一个页面,该页面要求您使用前面的大部分组件(图 4-11 )。

图 4-11
包含各种元素的 Twitter 引导示例页面
学习目标
这是您将在第一部分学习的内容列表:
-
了解如何在导航栏中添加下拉菜单。
-
了解各种下拉菜单组件和类。
-
了解一下大屏幕。
-
了解页眉。
-
了解按钮样式。
-
了解如何设置表格样式。
-
了解如何创建标签和标记。
介绍
您将继续处理 Twitter Bootstrap 项目,现在您将构建一个项目,作为对各种 Twitter Bootstrap 组件的引用。
我们开始吧。
带有导航栏的基本引导页面
您从带有导航栏的基本引导页面开始,就像我们在上一章中构建的那样。参见清单 4-1 。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Twitter Bootstrap Reference Page</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand" href="#">Bootstrap Ref. Page</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar"
aria-controls="navbar"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 4-1Start with a Navigation Bar
确保您的stylesheets/main.css文件包含必要的主体填充,这将允许页面的主要内容显示在导航栏下方(清单 4-2 )。
body {
padding-top: 56px;
}
Listing 4-2stylesheets/main.css for Listing 4-1
如果您保存前面的内容并在浏览器上加载页面,您将看到以下内容(图 4-12 )。

图 4-12
起始页
添加下拉菜单
现在你将学习如何添加一个下拉菜单,如下所示(图 4-13 )。

图 4-13
带有下拉菜单的页面
这很容易。必须在菜单项目列表中添加额外的li项目。这个新的li项目需要包含另一个列表,这将是下拉菜单中的选项列表,如下所示(列表 4-3 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Twitter Bootstrap Reference Page</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand" href="#">Bootstrap Ref. Page</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar"
aria-controls="navbar"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
<!-- Drop down Menu -->
<li class="nav-item dropdown">
<a href="#"
class="nav-link dropdown-toggle"
data-toggle="dropdown">
Dropdown <span class="caret"></span>
</a>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Action</a>
<a href="#" class="dropdown-item">Another action</a>
<a href="#" class="dropdown-item">Something else here</a>
<div class="dropdown-divider"></div>
<div class="dropdown-header">Nav header</div>
<a href="#" class="dropdown-item">Separated link</a>
<a href="#" class="dropdown-item">One more separated link</a>
</div>
</li>
</ul>
</div>
</div>
</nav>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 4-3Dropdown Menu in the Navigation Bar
如果您保存前面的代码并在浏览器上加载页面,您将在最右边看到新的下拉菜单。
让我们对用于构建下拉菜单的代码做一些说明(清单 4-4 )。
-
将作为下拉菜单的列表项(
li)需要有类dropdown。 -
下拉列表项文本,在我们的例子中是
Dropdown,需要被包装到一个锚<a>HTML 元素中。这将使指针改变,当用户悬停在它上面。请注意,锚点需要具有与dropdown相等的dropdown-toggle类和data-toggle属性。 -
下拉菜单的选项列表可以在
div中给出。 -
div需要有类dropdown-menu。 -
每个菜单选项都有一个锚
a,锚的类别是dropdown-item。 -
如果你想在菜单项之间创建一条线作为分隔线,你可以在类
divider中使用一个特殊的空div。 -
你也可以使用另一个特殊的
div作为子菜单标题,它实际上并不是用户选项的一部分,也就是说,不能点击和选择。如果 div 有类dropdown-header,就可以做到这一点。
<!-- Drop down Menu -->
<li class="nav-item dropdown">
<a href="#"
class="nav-link dropdown-toggle"
data-toggle="dropdown">
Dropdown
</a>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Action</a>
<a href="#" class="dropdown-item">Another action</a>
<a href="#" class="dropdown-item">Something else here</a>
<div class="dropdown-divider"></div>
<div class="dropdown-header">Nav header</div>
<a href="#" class="dropdown-item">Separated link</a>
<a href="#" class="dropdown-item">One more separated link</a>
</div>
</li>
Listing 4-4Looking into the Details of the Dropdown Menu
(电视机的)超大屏幕
Twitter Bootstrap 允许你创建超大屏幕,用很大的字体显示信息、标题或两者。让我们这样做:
-
在
nav之后,您将创建一个.container div来包含页面的内容。 -
您创建的第一个东西是一个带有类
.jumbotron的 div。
让我们来看看清单 4-5 中带有大屏幕的页面。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Twitter Bootstrap Reference Page</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand" href="#">Bootstrap Ref. Page</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar"
aria-controls="navbar"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
<!-- Drop down Menu -->
<li class="nav-item dropdown">
<a href="#"
class="nav-link dropdown-toggle"
data-toggle="dropdown">
Dropdown
</a>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Action</a>
<a href="#" class="dropdown-item">Another action</a>
<a href="#" class="dropdown-item">Something else here</a>
<div class="dropdown-divider"></div>
<div class="dropdown-header">Nav header</div>
<a href="#" class="dropdown-item">Separated link</a>
<a href="#" class="dropdown-item">One more separated link</a>
</div>
</li>
</ul>
</div>
</div>
</nav>
<!-- main content container -->
<div class="container">
<div class="jumbotron">
<h1>Jumbotron</h1>
<p class="lead">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
</div>
<!-- end of main content container -->
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 4-5Page with Jumbotron
在您将该页面保存并加载到浏览器之前,请确保您的stylesheets/main.css文件包含以下内容(列表 4-6 )。
body {
padding-top: 70px;
padding-bottom: 70px;
}
Listing 4-6CSS File for Listing 4-5
如果您这样做并保存您的页面,您将在浏览器上看到以下内容(图 4-14 )。

图 4-14
带有标题和引导段落的大屏幕
请注意,导航栏底部和大屏幕顶部之间的空间是由main.css文件中的padding-top规则创建的。
这里的方法非常简单。我们使用类jumbotron来表示div。我们也使用标题h1作为大屏幕内的标题文本。
最后,在前一章中,我们已经看到了应用在p元素上的类lead使文本突出。
带水平线的页眉:页眉
有时候你想创建一个标题,也就是一段像标题一样突出的文本,例如h1或h2,在它下面是一条水平线。
您可以在您的h1元素下面的hr元素的帮助下快速完成这项工作。添加以下内容作为主内容容器中的最后一个元素(清单 4-7 )。
<h1>Page Header</h1>
<hr class="my-4">
Listing 4-7How to Have a Header with a Horizontal Line Below It
如果你保存并重新加载你的页面,你应该会得到如下的结果(图 4-15 )。

图 4-15
带水平线的页眉
您已经在类my-4中使用了hr元素。这门课是怎么回事?这是 Bootstrap 调用的实用程序类之一。这个特殊的元素属于间距类别,它与它所附着的元素的边距和填充有关。特别
-
前缀
m代表边距。因此,在您的示例中,您对hr元素应用了一些边距。 -
y指的是垂直 y 轴。本质上,它是关于元素的顶部和底部。因此,在您的示例中,您对hr元素应用了一些顶部和底部边距。 -
数字
4是尺寸。尺寸可以是一个-
0:将边距或填充的大小设置为 0
-
1:将尺寸设置为
0.25乘以$spacer尺寸($spacer * 0.25) -
2:将尺寸设置为
0.5乘以$spacer尺寸($spacer * 0.5) -
3:将尺寸设置为等于
$spacer尺寸 -
4:将尺寸设置为
1.5乘以$spacer尺寸($spacer * 1.5) -
5:将尺寸设置为
3乘以$spacer尺寸($spacer * 3) -
Auto:自动设置尺寸(仅适用于页边距)
-
好的!坚持住。什么是$spacer?$spacer是一个 Sass(语法超棒的样式表)变量。注意 Bootstrap 是用 Sass 编写的,然后被编译成实际的 CSS。$spacer变量的默认值是1rem。
如果这太复杂,除了玩和尝试之外,没有其他方法来澄清它。还有,你最好的朋友是你浏览器的开发者工具。
例如,在大屏幕页面上打开开发者工具,找到元素hr。看看上边距和下边距是如何设置的,这要感谢附加在它上面的my-4类(图 4-16 )。

图 4-16
24px 的利润顶部和底部,感谢my-4
为什么是24px?这是因为my-4上的4被解释为$spacer * 1.5,又因为$spacer是1rem,我们最后得到1.5rem。您还可以看到,如果您将开发人员工具的选定选项卡切换到样式,而不是计算的(图 4-17 )。

图 4-18
根元素的字体大小为 16px

图 4-17
my-4 提供 1.5 雷姆的顶部和底部边距
还有为什么1.5rem计算出来是24px?rem是一个 CSS 单元,它计算一个元素相对于页面根元素的font-size的大小,即html元素的大小。如果您使用开发工具检查html元素的font-size属性,您将看到它的大小等于16px(图 4-18 )。
因此,16px * 1.5计算为24px。
Note
我做了一个小小的偏离来讨论 CSS 单元以及它们如何在 HTML 文档中使用。这不是 Twitter Bootstrap 的一部分。你可以在我的书掌握 HTML & CSS 中了解更多关于 HTML 和 CSS 的知识。
小跟班
现在,您将学习如何创建按钮:
-
所有按钮都应该有类
btn。 -
然后,您可以应用一个处理按钮颜色的类:
-
btn-default -
btn-primary -
btn-secondary -
btn-success -
btn-danger -
btn-warning -
btn-info -
btn-light -
btn-dark
-
-
除了颜色,你还可以应用一个类来把一个按钮变成一个链接:
btn-link。 -
或者您可以在类名中插入
*-outline-*这个词,以便为透明的背景色按钮设计一个边框,例如btn-outline-primary。 -
然后,您可以使用相应的类来指定按钮的大小:
-
btn-lg对于大按钮。 -
不要为正常大小的按钮指定类。
-
btn-sm用于小按钮。 -
btn-block适用于跨越整个可用宽度的区块。
让我们看看实际情况。清单 4-8 是你的页面现在应该有的代码。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Twitter Bootstrap Reference Page</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand" href="#">Bootstrap Ref. Page</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar"
aria-controls="navbar"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
<!-- Drop down Menu -->
<li class="nav-item dropdown">
<a href="#"
class="nav-link dropdown-toggle"
data-toggle="dropdown">
Dropdown
</a>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Action</a>
<a href="#" class="dropdown-item">Another action</a>
<a href="#" class="dropdown-item">Something else here</a>
<div class="dropdown-divider"></div>
<div class="dropdown-header">Nav header</div>
<a href="#" class="dropdown-item">Separated link</a>
<a href="#" class="dropdown-item">One more separated link</a>
</div>
</li>
</ul>
</div>
</div>
</nav>
<!-- main content container -->
<div class="container">
<div class="jumbotron">
<p class="lead">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
<h1>Buttons</h1>
<hr class="my-4">
<h2>Small Sizes</h2>
<p>
<button type="button" class="btn btn-sm btn-primary">btn btn-sm btn-primary</button>
<button type="button" class="btn btn-sm btn-secondary">btn btn-sm btn-secondary</button>
<button type="button" class="btn btn-sm btn-success">btn btn-sm btn-success</button>
<button type="button" class="btn btn-sm btn-danger">btn btn-sm btn-danger</button>
<button type="button" class="btn btn-sm btn-warning">btn btn-sm btn-warning</button>
<button type="button" class="btn btn-sm btn-info">btn btn-sm btn-info</button>
<button type="button" class="btn btn-sm btn-light">btn btn-sm btn-light</button>
<button type="button" class="btn btn-sm btn-dark">btn btn-sm btn-dark</button>
<button type="button" class="btn btn-sm btn-link">btn btn-sm btn-link</button>
</p>
<h2>Normal Sizes</h2>
<p>
<button type="button" class="btn btn-primary">btn btn-primary</button>
<button type="button" class="btn btn-secondary">btn btn-secondary</button>
<button type="button" class="btn btn-success">btn btn-success</button>
<button type="button" class="btn btn-danger">btn btn-danger</button>
<button type="button" class="btn btn-warning">btn btn-warning</button>
<button type="button" class="btn btn-info">btn btn-info</button>
<button type="button" class="btn btn-light">btn btn-light</button>
<button type="button" class="btn btn-dark">btn btn-dark</button>
<button type="button" class="btn btn-link">btn btn-link</button>
</p>
<h2>Large Sizes</h2>
<p>
<button type="button" class="btn btn-lg btn-primary">btn btn-lg btn-primary</button>
<button type="button" class="btn btn-lg btn-secondary">btn btn-lg btn-secondary</button>
<button type="button" class="btn btn-lg btn-success">btn btn-lg btn-success</button>
<button type="button" class="btn btn-lg btn-danger">btn btn-lg btn-danger</button>
<button type="button" class="btn btn-lg btn-warning">btn btn-lg btn-warning</button>
<button type="button" class="btn btn-lg btn-info">btn btn-lg btn-info</button>
<button type="button" class="btn btn-lg btn-light">btn btn-lg btn-light</button>
<button type="button" class="btn btn-lg btn-dark">btn btn-lg btn-dark</button>
<button type="button" class="btn btn-lg btn-link">btn btn-lg btn-link</button>
</p>
<h2>Block Sizes</h2>
<p>
<button type="button" class="btn btn-block btn-primary">btn btn-block btn-primary</button>
<button type="button" class="btn btn-block btn-secondary">btn btn-block btn-secondary</button>
<button type="button" class="btn btn-block btn-success">btn btn-block btn-success</button>
<button type="button" class="btn btn-block btn-danger">btn btn-block btn-danger</button>
<button type="button" class="btn btn-block btn-warning">btn btn-block btn-warning</button>
<button type="button" class="btn btn-block btn-info">btn btn-block btn-info</button>
<button type="button" class="btn btn-block btn-light">btn btn-block btn-light</button>
<button type="button" class="btn btn-block btn-dark">btn btn-block btn-dark</button>
<button type="button" class="btn btn-block btn-link">btn btn-block btn-link</button>
</p>
<h2>Outline buttons (Normal Sizes)</h2>
<p>
<button type="button" class="btn btn-outline-primary">btn btn-outline-primary</button>
<button type="button" class="btn btn-outline-secondary">btn btn-outline-secondary</button>
<button type="button" class="btn btn-outline-success">btn btn-outline-success</button>
<button type="button" class="btn btn-outline-danger">btn btn-outline-danger</button>
<button type="button" class="btn btn-outline-warning">btn btn-outline-warning</button>
<button type="button" class="btn btn-outline-info">btn btn-outline-info</button>
<button type="button" class="btn btn-outline-light">btn btn-outline-light</button>
<button type="button" class="btn btn-outline-dark">btn btn-outline-dark</button>
<button type="button" class="btn btn-outline-link">btn btn-outline-link</button>
</p>
</div>
<!-- end of main content container -->
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 4-8Page Demonstrating Buttons
正如您在前面的代码中看到的,这是一系列 header h2和p元素,它们适用于我前面谈到的所有类的组合。
保存文件并在浏览器上重新加载页面。你会看到类似下面的东西(图 4-19 )。

图 4-19
页面演示按钮
在这个页面上,您可以看到每个按钮是如何根据您应用的 Twitter Bootstrap 按钮类显示的。这真的令人印象深刻,因为没有一行 CSS 代码,你就可以免费获得如此多的功能。你只需要学习各种 Twitter 引导类。
桌子
你已经学习了表格以及如何用它们来显示表格数据(从我的【HTML 大师& CSS 的书中)。Twitter Bootstrap 附带了一些关于如何设计表格样式的有用类。让我们看看怎么做。
基本引导表
让我们从一个没有应用任何 Twitter 引导类的表开始。所以它只有默认的样式。
您继续在主容器的末尾追加内容。然而,清单 4-9 有完整的 HTML 代码。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Twitter Bootstrap Reference Page</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand" href="#">Bootstrap Ref. Page</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar"
aria-controls="navbar"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
<!-- Drop down Menu -->
<li class="nav-item dropdown">
<a href="#"
class="nav-link dropdown-toggle"
data-toggle="dropdown">
Dropdown
</a>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Action</a>
<a href="#" class="dropdown-item">Another action</a>
<a href="#" class="dropdown-item">Something else here</a>
<div class="dropdown-divider"></div>
<div class="dropdown-header">Nav header</div>
<a href="#" class="dropdown-item">Separated link</a>
<a href="#" class="dropdown-item">One more separated link</a>
</div>
</li>
</ul>
</div>
</div>
</nav>
<!-- main content container -->
<div class="container">
<div class="jumbotron">
<p class="lead">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
<h1>Buttons</h1>
<hr class="my-4">
<h2>Small Sizes</h2>
<p>
<button type="button" class="btn btn-sm btn-primary">btn btn-sm btn-primary</button>
<button type="button" class="btn btn-sm btn-secondary">btn btn-sm btn-secondary</button>
<button type="button" class="btn btn-sm btn-success">btn btn-sm btn-success</button>
<button type="button" class="btn btn-sm btn-danger">btn btn-sm btn-danger</button>
<button type="button" class="btn btn-sm btn-warning">btn btn-sm btn-warning</button>
<button type="button" class="btn btn-sm btn-info">btn btn-sm btn-info</button>
<button type="button" class="btn btn-sm btn-light">btn btn-sm btn-light</button>
<button type="button" class="btn btn-sm btn-dark">btn btn-sm btn-dark</button>
<button type="button" class="btn btn-sm btn-link">btn btn-sm btn-link</button>
</p>
<h2>Normal Sizes</h2>
<p>
<button type="button" class="btn btn-primary">btn btn-primary</button>
<button type="button" class="btn btn-secondary">btn btn-secondary</button>
<button type="button" class="btn btn-success">btn btn-success</button>
<button type="button" class="btn btn-danger">btn btn-danger</button>
<button type="button" class="btn btn-warning">btn btn-warning</button>
<button type="button" class="btn btn-info">btn btn-info</button>
<button type="button" class="btn btn-light">btn btn-light</button>
<button type="button" class="btn btn-dark">btn btn-dark</button>
<button type="button" class="btn btn-link">btn btn-link</button>
</p>
<h2>Large Sizes</h2>
<p>
<button type="button" class="btn btn-lg btn-primary">btn btn-lg btn-primary</button>
<button type="button" class="btn btn-lg btn-secondary">btn btn-lg btn-secondary</button>
<button type="button" class="btn btn-lg btn-success">btn btn-lg btn-success</button>
<button type="button" class="btn btn-lg btn-danger">btn btn-lg btn-danger</button>
<button type="button" class="btn btn-lg btn-warning">btn btn-lg btn-warning</button>
<button type="button" class="btn btn-lg btn-info">btn btn-lg btn-info</button>
<button type="button" class="btn btn-lg btn-light">btn btn-lg btn-light</button>
<button type="button" class="btn btn-lg btn-dark">btn btn-lg btn-dark</button>
<button type="button" class="btn btn-lg btn-link">btn btn-lg btn-link</button>
</p>
<h2>Block Sizes</h2>
<p>
<button type="button" class="btn btn-block btn-primary">btn btn-block btn-primary</button>
<button type="button" class="btn btn-block btn-secondary">btn btn-block btn-secondary</button>
<button type="button" class="btn btn-block btn-success">btn btn-block btn-success</button>
<button type="button" class="btn btn-block btn-danger">btn btn-block btn-danger</button>
<button type="button" class="btn btn-block btn-warning">btn btn-block btn-warning</button>
<button type="button" class="btn btn-block btn-info">btn btn-block btn-info</button>
<button type="button" class="btn btn-block btn-light">btn btn-block btn-light</button>
<button type="button" class="btn btn-block btn-dark">btn btn-block btn-dark</button>
<button type="button" class="btn btn-block btn-link">btn btn-block btn-link</button>
</p>
<h2>Outline buttons (Normal Sizes)</h2>
<p>
<button type="button" class="btn btn-outline-primary">btn btn-outline-primary</button>
<button type="button" class="btn btn-outline-secondary">btn btn-outline-secondary</button>
<button type="button" class="btn btn-outline-success">btn btn-outline-success</button>
<button type="button" class="btn btn-outline-danger">btn btn-outline-danger</button>
<button type="button" class="btn btn-outline-warning">btn btn-outline-warning</button>
<button type="button" class="btn btn-outline-info">btn btn-outline-info</button>
<button type="button" class="btn btn-outline-light">btn btn-outline-light</button>
<button type="button" class="btn btn-outline-dark">btn btn-outline-dark</button>
<button type="button" class="btn btn-outline-link">btn btn-outline-link</button>
</p>
<h1>Tables</h1>
<hr class="my-4">
<h2>Shopping List</h2>
<table>
<tr><th colspan="2">Shopping List</th></tr>
<tr><th>Item</th><th>Qt</th></tr>
<tr><td>Cheese</td><td>1 kgr</td></tr>
<tr><td>Rice</td><td>1.5 kgr</td></tr>
<tr><td>Coffee</td><td>0.5 kgr</td></tr>
<tr><td>Milk</td><td>1 ltr</td></tr>
<tr><td>Wine</td><td>1 btl</td></tr>
</table>
<h2>Travel Plan</h2>
<table>
<tr><th colspan="2">Travel Plan</th></tr>
<tr><th>Action</th><th>Due</th></tr>
<tr><td>Book Ticket</td><td>Feb 20th</td></tr>
<tr><td>Book Hotel</td><td>March 26th</td></tr>
<tr><td>Buy Suitcase</td><td>April 20th</td></tr>
<tr><td>Get Passport</td><td>April 30th</td></tr>
</table>
</div>
<!-- end of main content container -->
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 4-9Full HTML Code, Includes a New Table Demo
正如您在前面的代码中看到的,您只添加了两个简单的table元素。如果您保存它并重新加载页面,您将会看到以下内容(图 4-20 )。

图 4-20
没有任何额外造型的桌子
样式引导表
让我们尝试应用一些 Twitter 引导类来设计它。如果您只将类table应用于table元素,那么您不用太费力就能得到一个不错的例子。就这么办吧。而不只是
<table>
写
<table class="table">
如果你在浏览器上重新加载页面,你会看到表格显示得非常好(图 4-21 )。

图 4-21
仅包含“table”类的表
Pretty cool! Eh?
除了table类,您还可以在表上尝试更多的类。尝试将类table-striped附加到第一个表上,将类table-bordered附加到第二个表上。所以不要
<table class="table">
转到
<table class="table table-striped">
对于第一个表和
<table class="table table-bordered">
第二桌。
如果您保存并重新加载您的页面,您将看到以下内容(图 4-22 )。

图 4-22
条纹和镶边的桌子
类使表格有条纹,一行是深色背景,下一行是亮色背景。table-bordered类给表格添加边框。
你绝对可以组合表类。例如,尝试第二个表的table table-striped table-bordered。您将得到以下结果(图 4-23 )。

图 4-23
表格同时带有边框和条纹
另一个不错的表格类是类table-hover,它将突出显示鼠标悬停的行。让我们试试那个。将第一个表的类值设置为
<table class="table table-hover">
如果您在浏览器上保存并加载页面,您将只看到带有table类的表格。但是,如果您尝试将鼠标指针移到这些行上,您会看到当鼠标移到这些行上时,这些行是如何突出显示的。
另一个有用的类是table-sm,它将确保行具有相当小的高度。在第二个表和它已经拥有的其他表类上尝试一下:
<table class="table table-striped table-bordered table-sm">
如果您在浏览器上重新加载页面,您将看到以下内容(图 4-24 )。

图 4-24
小个子跟table-sm一类
如图 4-24 所示,与第一个表格的行高相比,第二个表格的精简样式的行高要小得多。
给表格行着色
此外,Twitter Bootstrap 提供了一系列对应于特定颜色的语义类。当您应用这些类时,您可以快速设置相应行(tr)或相应单元格(td或th)的背景颜色。
这些类别是
-
table-active -
table-primary -
table-secondary -
table-success -
table-danger -
table-warning -
table-info -
table-light -
table-dark
让我们将其中一些应用到页面上第二个表格的行中。所以第二个表格 HTML 片段变成如下(清单 4-10 )。
<table class="table table-bordered table-striped table-sm">
<tr><th colspan="2">Travel Plan</th></tr>
<tr class="table-active"><th>(active) Action</th><th>Due</th></tr>
<tr class="table-success"><td>(success) Book Ticket</td><td>Feb 20th</td></tr>
<tr class="table-info"><td>(info) Book Hotel</td><td>March 26th</td></tr>
<tr class="table-warning"><td>(warning) Buy Suitcase</td><td>April 20th</td></tr>
<tr class="table-danger"><td>(danger) Get Passport</td><td>April 30th</td></tr>
</table>
Listing 4-10Second Table with Various Classes at Row Level
如果您保存前面的代码并在浏览器上重新加载页面,您将看到以下内容(图 4-25 )。

图 4-25
在行级别具有不同类的表
标签和徽章
Bootstrap 允许您非常容易地创建标签和徽章。
标签
有时候你想创建某种视觉标签,一个标记,如下所示(图 4-26 )。

图 4-26
标签示例
这很容易通过 Twitter Bootstrap 实现。您只需将内容放在一个span元素中,并应用类badge加上一个用于标签颜色的类(以下任何一个badge-*类):
-
badge-primary -
badge-secondary -
badge-success -
badge-danger -
badge-warning -
badge-info -
badge-light -
badge-dark
让我们在主内容容器的末尾添加以下内容(清单 4-11 )。
<h1>Labels & Badges</h1>
<hr class="my-4">
<h4>
<span class="badge badge-primary">€20.00 - Primary</span>
<span class="badge badge-secondary">€20.00 - Secondary</span>
<span class="badge badge-success">€20.00 - Success</span>
<span class="badge badge-danger">€20.00 - Danger</span>
<span class="badge badge-warning">€20.00 - Warning</span>
<span class="badge badge-info">€20.00 - Info</span>
<span class="badge badge-light">€20.00 - Light</span>
<span class="badge badge-dark">€20.00 - Dark</span>
</h4>
Listing 4-11HTML Fragment That Creates Labels
保存全部内容,并在浏览器上重新加载页面。您将看到图 4-27 中描述的内容。

图 4-27
标签演示
很清楚。请注意,您将跨度包含在一个h4元素中只是为了让它们稍微大一点。
徽章
但是徽章呢?通常,你想显示一个小的或大的徽章,比如一个圆圈内的数字,来指示未读消息的数量,如图 4-28 所示。

图 4-28
徽章示例
这些与我们之前创建的标签没有什么不同。唯一的区别是它们更圆润。您可以通过在其他badge-*类旁边添加类badge-pill来实现这一点。
清单 4-12 是一个创建带有徽章的按钮的 HTML 片段。想象一个按钮,允许用户点击并进入他们的收件箱。该按钮将显示未读邮件的数量。
<button class="btn btn-light">Inbox <span class="badge badge-primary badge-pill">1</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-secondary badge-pill">2</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-success badge-pill">3</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-danger badge-pill">4</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-warning badge-pill">5</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-info badge-pill">6</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-light badge-pill">7</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-dark badge-pill">8</span></button>
Listing 4-12Buttons with Badges
将这个 HTML 片段添加到主容器的底部,然后在浏览器上重新加载页面。您将看到带有徽章的按钮显示如下(图 4-29 )。

图 4-29
带徽章的纽扣
关键要点
-
带有下拉菜单列表的导航栏
-
各种尺寸和颜色的按钮
-
不同风格的桌子
-
标签和徽章
主题参考项目的第一部分到此结束。在下一章,项目的第二部分,您将继续学习更多关于 Twitter Bootstrap 组件的知识。
五、主题参考:第二部分
在第四章“主题参考:第一部分”中,你已经了解了一些最重要的 Twitter Bootstrap 组件,并且你已经开始为它们创建一个参考页面。在本章的第二部分中,您将在同一个参考项目中继续学习更多的组件。
特别是,我承诺向大家展示的其余组件是
-
选项卡,用于对信息进行分组
-
警报,用于显示突出的消息
-
进度条,用于直观地向用户显示一个正在进行的工作已经完成的百分比
-
卡片,美丽的矩形区域,内容丰富,能吸引观众的注意力
-
Carousel,一个像图像或其他丰富内容幻灯片一样工作的组件
最后,您将被要求创建一个页面,该页面要求您使用前面的大部分组件(图 5-1 )。

图 5-1
包含各种元素的 Twitter 引导示例页面
学习目标
-
了解如何创建选项卡。
-
了解如何创建通知。
-
了解如何创建进度条。
-
了解如何制作卡片。
-
了解如何创建旋转木马。
介绍
您将继续您在前一章中开始的 Twitter Bootstrap 主题参考项目。让我们开始添加更多的组件。
制表符
有时,您希望使用选项卡来组织页面上的信息。选项卡很好,因为它们将部分信息组合在一个标题下,并且不会同时显示所有信息。用户通过点击相应的标签标题来选择要查看/阅读的信息组。
例如,参见图 5-2 中的一些选项卡。

图 5-2
选项卡示例
显示的信息根据所单击的选项卡标题而变化。
让我们看看如何实现前面的选项卡示例。
首先,您需要理解标签功能的 HTML 实现有两个部分:
-
标签标题
-
与实际信息不同的内容
标签标题
选项卡标题是一个未排序的列表ul,带有类别nav nav-tabs。列表中的每个元素(li)对应于一个选项卡标题,并且它必须具有类nav-item。每个li的内容是具有类nav-link的锚和具有值tab的数据属性data-toggle。同样,每个锚都有一个指向相应信息容器的href值。当这个锚被点击时,那个信息容器将被显示给用户。注意,对应于应该显示给用户的信息容器的li也需要有类active。
下面是上一个例子中标签头的 HTML 片段(清单 5-1 )。
<ul class="nav nav-tabs">
<li class="nav-item">
<a class="nav-link active" href="#dashboard" data-toggle="tab">Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#payments" data-toggle="tab">Payments</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#invoices" data-toggle="tab">Invoices</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#settings" data-toggle="tab">Settings</a>
</li>
</ul>
Listing 5-1The ul HTML Fragment for the Tabs Example
让我们使用前面的片段来更改您的主 HTML 页面。把它放在容器的底部。在这个ul列表之前,像添加其他标题一样添加标签的标题(列表 5-2 )。
<h1>Tabs</h1>
<hr class="my-4">
Listing 5-2Tabs Header
如果保存页面并将其加载到浏览器中,选项卡部分将如图 5-3 所示。

图 5-3
内容为空的选项卡
这是很好的一步。你可以看到标签是如何被很好地放置在页面上的。您甚至可以单击标题,以查看活动选项卡如何根据您单击的选项卡而变化。
现在缺少的是应该附在每个标签上的信息。
标签信息
您将选项卡信息放在带有类tab-content的div中。在其中,我们为每个信息组/选项卡标题创建一个div。这个div需要有一个tab-pane类。此外,它需要有正确的id,每个选项卡信息面板不同,并对应于相应选项卡的href值。
让我们将下面这段 HTML 代码(清单 5-3 )添加到主内容容器的末尾,在我们为选项卡标题创建的未排序列表之后。
<div class="tab-content">
<div id="dashboard" class="tab-pane active">
<p>
<strong>Dashboard:</strong> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
<div id="payments" class="tab-pane">
<p>
<strong>Payments:</strong> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
<div id="invoices" class="tab-pane">
<p>
<strong>Invoices:</strong> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
<div id="settings" class="tab-pane">
<p>
<strong>Settings:</strong> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
</div>
Listing 5-3HTML Fragment for Tab Content
正如您在前面的代码中看到的
-
您有一个包含所有其他 div 的
div。 -
这个父级
div具有类tab-content。 -
每个
div的id值等于相应选项卡标题锚点的href。 -
每个
div都有一个类tab-pane。 -
第一个
div也有类active,因为这是为第一个选项卡标题显示的第一个信息框,最初也是active。
如果保存前面的信息并重新加载页面,您将看到以下内容(图 5-4 )。

图 5-4
带内容的选项卡
如您所见,选项卡信息清楚地显示在选项卡标题下方。此外,如果您尝试单击不同的选项卡标题,您将看到以下信息如何相应地变化。
但是有一个问题是内容太靠近标签头了(图 5-5 )。

图 5-5
标签内容太靠近标签标题的问题
为了解决这个问题,在包含标题的ul上需要一些底部空白。您可以通过向ul元素添加实用程序类mb-3来实现这一点。
现在,如果您在浏览器上加载页面,您将看到以下内容(图 5-6 )。

图 5-6
选项卡内容上方现在有一些空闲空间
Note
Twitter Bootstrap 鼓励作者让他们的内容与辅助技术兼容,比如屏幕阅读器。这意味着,除了使用样式类之外,您可能还必须添加一些专门为此目的设计的额外 HTML 属性。例如,带有选项卡列表的ul元素的 role HTML 属性需要有值tablist。如果你想了解如何创建可访问的富互联网应用程序,你必须阅读并应用这里给出的实践: WAI-ARIA 创作实践。
检查站
你在这一页做了很多工作。在继续之前,让我们确保它包含清单 5-4 中的内容。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Twitter Bootstrap Reference Page</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand" href="#">Bootstrap Ref. Page</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar"
aria-controls="navbar"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
<!-- Drop down Menu -->
<li class="nav-item dropdown">
<a href="#"
class="nav-link dropdown-toggle"
data-toggle="dropdown">
Dropdown
</a>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Action</a>
<a href="#" class="dropdown-item">Another action</a>
<a href="#" class="dropdown-item">Something else here</a>
<div class="dropdown-divider"></div>
<div class="dropdown-header">Nav header</div>
<a href="#" class="dropdown-item">Separated link</a>
<a href="#" class="dropdown-item">One more separated link</a>
</div>
</li>
</ul>
</div>
</div>
</nav>
<!-- main content container -->
<div class="container">
<div class="jumbotron">
<p class="lead">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
<h1>Buttons</h1>
<hr class="my-4">
<h2>Small Sizes</h2>
<p>
<button type="button" class="btn btn-sm btn-primary">btn btn-sm btn-primary</button>
<button type="button" class="btn btn-sm btn-secondary">btn btn-sm btn-secondary</button>
<button type="button" class="btn btn-sm btn-success">btn btn-sm btn-success</button>
<button type="button" class="btn btn-sm btn-danger">btn btn-sm btn-danger</button>
<button type="button" class="btn btn-sm btn-warning">btn btn-sm btn-warning</button>
<button type="button" class="btn btn-sm btn-info">btn btn-sm btn-info</button>
<button type="button" class="btn btn-sm btn-light">btn btn-sm btn-light</button>
<button type="button" class="btn btn-sm btn-dark">btn btn-sm btn-dark</button>
<button type="button" class="btn btn-sm btn-link">btn btn-sm btn-link</button>
</p>
<h2>Normal Sizes</h2>
<p>
<button type="button" class="btn btn-primary">btn btn-primary</button>
<button type="button" class="btn btn-secondary">btn btn-secondary</button>
<button type="button" class="btn btn-success">btn btn-success</button>
<button type="button" class="btn btn-danger">btn btn-danger</button>
<button type="button" class="btn btn-warning">btn btn-warning</button>
<button type="button" class="btn btn-info">btn btn-info</button>
<button type="button" class="btn btn-light">btn btn-light</button>
<button type="button" class="btn btn-dark">btn btn-dark</button>
<button type="button" class="btn btn-link">btn btn-link</button>
</p>
<h2>Large Sizes</h2>
<p>
<button type="button" class="btn btn-lg btn-primary">btn btn-lg btn-primary</button>
<button type="button" class="btn btn-lg btn-secondary">btn btn-lg btn-secondary</button>
<button type="button" class="btn btn-lg btn-success">btn btn-lg btn-success</button>
<button type="button" class="btn btn-lg btn-danger">btn btn-lg btn-danger</button>
<button type="button" class="btn btn-lg btn-warning">btn btn-lg btn-warning</button>
<button type="button" class="btn btn-lg btn-info">btn btn-lg btn-info</button>
<button type="button" class="btn btn-lg btn-light">btn btn-lg btn-light</button>
<button type="button" class="btn btn-lg btn-dark">btn btn-lg btn-dark</button>
<button type="button" class="btn btn-lg btn-link">btn btn-lg btn-link</button>
</p>
<h2>Block Sizes</h2>
<p>
<button type="button" class="btn btn-block btn-primary">btn btn-block btn-primary</button>
<button type="button" class="btn btn-block btn-secondary">btn btn-block btn-secondary</button>
<button type="button" class="btn btn-block btn-success">btn btn-block btn-success</button>
<button type="button" class="btn btn-block btn-danger">btn btn-block btn-danger</button>
<button type="button" class="btn btn-block btn-warning">btn btn-block btn-warning</button>
<button type="button" class="btn btn-block btn-info">btn btn-block btn-info</button>
<button type="button" class="btn btn-block btn-light">btn btn-block btn-light</button>
<button type="button" class="btn btn-block btn-dark">btn btn-block btn-dark</button>
<button type="button" class="btn btn-block btn-link">btn btn-block btn-link</button>
</p>
<h2>Outline buttons (Normal Sizes)</h2>
<p>
<button type="button" class="btn btn-outline-primary">btn btn-outline-primary</button>
<button type="button" class="btn btn-outline-secondary">btn btn-outline-secondary</button>
<button type="button" class="btn btn-outline-success">btn btn-outline-success</button>
<button type="button" class="btn btn-outline-danger">btn btn-outline-danger</button>
<button type="button" class="btn btn-outline-warning">btn btn-outline-warning</button>
<button type="button" class="btn btn-outline-info">btn btn-outline-info</button>
<button type="button" class="btn btn-outline-light">btn btn-outline-light</button>
<button type="button" class="btn btn-outline-dark">btn btn-outline-dark</button>
<button type="button" class="btn btn-outline-link">btn btn-outline-link</button>
</p>
<h1>Tables</h1>
<hr class="my-4">
<h2>Shopping List</h2>
<table class="table">
<tr><th colspan="2">Shopping List</th></tr>
<tr><th>Item</th><th>Qt</th></tr>
<tr><td>Cheese</td><td>1 kgr</td></tr>
<tr><td>Rice</td><td>1.5 kgr</td></tr>
<tr><td>Coffee</td><td>0.5 kgr</td></tr>
<tr><td>Milk</td><td>1 ltr</td></tr>
<tr><td>Wine</td><td>1 btl</td></tr>
</table>
<h2>Travel Plan</h2>
<table class="table table-bordered table-striped table-sm">
<tr><th colspan="2">Travel Plan</th></tr>
<tr class="table-active"><th>(active) Action</th><th>Due</th></tr>
<tr class="table-success"><td>(success) Book Ticket</td><td>Feb 20th</td></tr>
<tr class="table-info"><td>(info) Book Hotel</td><td>March 26th</td></tr>
<tr class="table-warning"><td>(warning) Buy Suitcase</td><td>April 20th</td></tr>
<tr class="table-danger"><td>(danger) Get Passport</td><td>April 30th</td></tr>
</table>
<h1>Labels & Badges</h1>
<hr class="my-4">
<h4>
<span class="badge badge-primary">€20.00 - Primary</span>
<span class="badge badge-secondary">€20.00 - Secondary</span>
<span class="badge badge-success">€20.00 - Success</span>
<span class="badge badge-danger">€20.00 - Danger</span>
<span class="badge badge-warning">€20.00 - Warning</span>
<span class="badge badge-info">€20.00 - Info</span>
<span class="badge badge-light">€20.00 - Light</span>
<span class="badge badge-dark">€20.00 - Dark</span>
</h4>
<button class="btn btn-light">Inbox <span class="badge badge-primary badge-pill">1</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-secondary badge-pill">2</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-success badge-pill">3</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-danger badge-pill">4</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-warning badge-pill">5</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-info badge-pill">6</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-light badge-pill">7</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-dark badge-pill">8</span></button>
<h1>Tabs</h1>
<hr class="my-4">
<ul class="nav nav-tabs mb-4">
<li class="nav-item"><a class="nav-link active" href="#dashboard" data-toggle="tab">Dashboard</a></li>
<li class="nav-item"><a class="nav-link" href="#payments" data-toggle="tab">Payments</a></li>
<li class="nav-item"><a class="nav-link" href="#invoices" data-toggle="tab">Invoices</a></li>
<li class="nav-item"><a class="nav-link" href="#settings" data-toggle="tab">Settings</a></li>
</ul>
<div class="tab-content">
<div id="dashboard" class="tab-pane active">
<p>
<strong>Dashboard:</strong> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
<div id="payments" class="tab-pane">
<p>
<strong>Payments:</strong> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
<div id="invoices" class="tab-pane">
<p>
<strong>Invoices:</strong> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
<div id="settings" class="tab-pane">
<p>
<strong>Settings:</strong> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
</div>
</div>
<!-- end of main content container -->
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 5-4Twitter Bootstrap Reference Page Checkpoint
警报
有时,您希望显示一条消息来吸引用户的注意。这些被称为警报。下面是一个例子(图 5-7 )。

图 5-7
警报示例
这些消息通常显示在页面的顶部,但不一定只显示在那里。
Twitter Bootstrap 给出了应该在 block 元素(如div)上使用的类alert,以便将它变成一个警告块。除此之外,您还需要指定一个为警告着色的类,以便更好地向用户传达消息。因此,对于表示警告的消息,可以使用alert-warning类和alert类。
与警报相关的颜色类别有
-
alert-primary -
alert-secondary -
alert-success -
alert-danger -
alert-warning -
alert-info -
alert-light -
alert-dark
让我们看看这些警报的实际效果。将下面的 HTML 片段添加到主内容容器的末尾之前(清单 5-5 )。
<h1>Alerts</h1>
<hr class="my-4">
<div class="alert alert-primary">
A simple primary alert.
</div>
<div class="alert alert-secondary">
A simple secondary alert.
</div>
<div class="alert alert-success">
A simple success alert.
</div>
<div class="alert alert-danger">
A simple danger alert.
</div>
<div class="alert alert-warning">
A simple warning alert.
</div>
<div class="alert alert-info">
A simple info alert.
</div>
<div class="alert alert-light">
A simple light alert.
</div>
<div class="alert alert-dark">
A simple dark alert.
</div>
Listing 5-5HTML Fragment for Alerts Demo
如果您保存前面的代码并在浏览器上重新加载您的页面,您将在页面的 Alerts 部分看到以下内容(图 5-8 )。

图 5-8
警报演示
在您的警报中,您可以有任何有效的 HTML 内容。例如,您可以有一个到另一个页面的链接。让我们添加下面的 HTML 片段(清单 5-6 )。
<div class="alert alert-info">
<strong>London</strong> Read more about London from <a href="https://en.wikipedia.org/wiki/London">Wikipedia London Link</a>.
</div>
Listing 5-6Add an Alert with HTML Inside
如果您重新加载您的 HTML 页面,新的警告将显示如下(图 5-9 )。

图 5-9
内部带有超链接的警报
这里有一个小的样式问题,与警报内部链接的颜色有关。就是不好看。Bootstrap 建议您在锚a上使用类alert-link。这将根据警报的背景提供匹配的颜色。让我们像清单 5-7 那样添加它。
<div class="alert alert-info">
<strong>London</strong> Read more about London from <a class="alert-link" href="https://en.wikipedia.org/wiki/London">Wikipedia London Link</a>.
</div>
Listing 5-7Use the alert-link Class
如果您保存 HTML 内容并在浏览器上重新加载页面,您将会看到显示超链接的警告,如图 5-10 所示。

图 5-10
与alert-link的造型链接
进度条
进度条指示给定任务已经完成了多少,还有多少工作要做。例如,参见图 5-11 。

图 5-11
进度条示例
正如你在图 5-11 中看到的,进度条有一个颜色和一个文本指示,表明多少流程已经完成,还有多少流程有待完成。
Twitter Bootstrap 有两个与这个工具相关的类,progress和progress-bar。让我们通过将下面的 HTML 内容附加到主内容容器的末尾来看看应该如何使用它们(清单 5-8 )。
<h1>Progress Bars</h1>
<hr class="my-4">
<div class="progress">
<div class="progress-bar" style="width: 60%;">60% Complete</div>
</div>
Listing 5-8HTML Fragment to Add a Progress Bar
从前面的片段中可以看出,进度条非常容易构建。一个div有类progress;,另一个div,在第一个里面,有类progress-bar。孩子div显示的文本给出了当前进度的文本信息。这段文字是不必要的。它可能是空的。这里重要的部分是您正确地设置了子节点div的width属性的值,这样它就可以指示实际的进度。一个好的方法是在这里使用百分比,因为百分比会使子宽度成为父宽度的百分比。父类div上的progress类确保父类div占据页面的所有可用宽度,而子类div上的style="width: 60%"确保子类div恰好占据父类div的60%,因此这两个div元素合二为一,给出了进度条的视觉效果。
如果保存 HTML 页面并在浏览器上重新加载,您将看到以下内容(图 5-12 )。

图 5-12
标准进度条
进度条高度
如果你觉得这个条太短,那么你可以调整父级div的高度,这个父级有一个类progress。让我们添加样式属性如下(清单 5-9 )。
<div class="progress" style="height: 1.8rem;">
<div class="progress-bar" style="width: 60%;">60% Complete</div>
</div>
Listing 5-9Adjust the Height of the Progress Bar
如果您保存前面的内容并在浏览器上重新加载页面,您将看到以下内容(图 5-13 )。

图 5-13
调整进度条的高度
进度条颜色
除了你在图 5-13 中看到的普通进度条之外,你可以使用引导背景颜色工具类来改变进度条的颜色。这些类别是
-
bg-primary -
bg-secondary -
bg-success -
bg-danger -
bg-warning -
bg-info -
bg-light -
bg-dark
您需要在内部的div上设置这个类,与progress-bar类并排。让我们将 HTML 页面中的进度条演示代码修改如下(清单 5-10 )。
<h1>Progress Bars</h1>
<hr class="my-4">
<div class="progress mb-1 h-4">
<div class="progress-bar bg-primary" style="width: 60%;">60% Complete - primary</div>
</div>
<div class="progress mb-1 h-4">
<div class="progress-bar bg-secondary" style="width: 60%;">60% Complete - secondary</div>
</div>
<div class="progress mb-1 h-4">
<div class="progress-bar bg-success" style="width: 60%;">60% Complete - success</div>
</div>
<div class="progress mb-1 h-4">
<div class="progress-bar bg-danger" style="width: 60%;">60% Complete - danger</div>
</div>
<div class="progress mb-1 h-4">
<div class="progress-bar bg-warning" style="width: 60%;">60% Complete - warning</div>
</div>
<div class="progress mb-1 h-4">
<div class="progress-bar bg-info" style="width: 60%;">60% Complete - info</div>
</div>
<div class="progress mb-1 h-4">
<div class="progress-bar bg-light" style="width: 60%;">60% Complete - light</div>
</div>
<div class="progress mb-1 h-4">
<div class="progress-bar bg-dark" style="width: 60%;">60% Complete - dark</div>
</div>
Listing 5-10Progress Bar Demo Code Fragment
同样,确保你的stylesheets/main.css文件有如下的类定义(清单 5-11 )。
.h-4 {
height: 1.5rem;
}
Listing 5-11Class h-4 Which Is Used in Listing 5-10
如果保存 HTML 页面并在浏览器上重新加载,您将看到以下内容(图 5-14 )。

图 5-14
各种颜色的进度条
多色进度条
最后,你可以用进度条做另一个小把戏。你可以在同一个进度条上使用不同的颜色。可以创建如下效果(图 5-15 )。

图 5-15
多色进度条
这很容易通过在progress-bar类中包含多个子div来实现。为了看到这一点,在主内容容器的末尾添加以下 HTML 片段(清单 5-12 )。
<div class="progress mb-1 h-4">
<div class="progress-bar bg-primary" style="width: 30%;">30% primary</div>
<div class="progress-bar bg-success" style="width: 50%;">50% success</div>
<div class="progress-bar bg-warning" style="width: 10%;">10% warning</div>
</div>
Listing 5-12Multicolored Progress Bar HTML Fragment
正如您在前面的代码中看到的,所有三种不同的颜色divs都在父div中。Twitter Bootstrap 足够聪明,可以在正确的位置画出每一个进度条,给定进度条的颜色,用正确的颜色画出它们。
信用卡
卡片是一个容器,它有一些特定的结构来创建非常吸引人的内容,有页眉和页脚。在图 5-16 中,你可以看到一张卡的例子。

图 5-16
卡片示例
卡片通常有图像、标题和正文。但是它也可以包含页眉和页脚。
三卡布局
让我们尝试在您的 Twitter 引导参考页面中创建以下内容(图 5-17 )。

图 5-17
Twitter 引导参考页面中的卡片
-
你要加三张牌。
-
您将选择的布局是响应式的:
-
对于高达 767px 的显示器,每行将显示一张卡片。
-
对于高达 991 像素的显示器,每行将显示两张卡片。
-
对于宽度> = 992 像素的显示器,它将在同一行显示三张卡片。
-
清单 5-13 包含了你必须添加到页面主容器底部的 HTML 代码。
<h1>Cards</h1>
<hr class="my-4">
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3">
<div class="col">
<div class="card">
<h5 class="card-header">Voted #1</h5>
<img src="https://live.staticflickr.com/3869/14437071224_43fb23705b_h.jpg" class="card-img-top" alt="lion sitting and looking around" style="height: 220px"/>
<div class="card-body">
<h5 class="card-title">Lions</h5>
<h6 class="card-subtitle">Lions Are Amazing</h6>
<p class="card-text">
The lion (Panthera leo) is a large mammal of the Felidae (cat) family. Some large males weigh over 250 kg (550 lb).
Today, wild lions live in sub-Saharan Africa and in Asia. Lions are adapted for life in grasslands and mixed areas
with trees and grass. The relatively small females are fast runners over short distances, and coordinate their hunting of herd animals.
</p>
<a href="https://simple.wikipedia.org/wiki/Lion" class="btn btn-primary">Learn more</a>
</div>
<div class="card-footer">
from Wikipedia
</div>
</div>
</div>
<div class="col">
<div class="card">
<h5 class="card-header">Voted #2</h5>
<img src="http://www.felineworlds.com/wp-content/uploads/Cheetah_Looking_Around_600.jpg" class="card-img-top" alt="cheetah looking around" style="height: 220px"/>
<div class="card-body">
<h5 class="card-title">Cheetahs</h5>
<h6 class="card-subtitle">Cheetahs Are Really Fast</h6>
<p class="card-text">
The cheetah (Acinonyx jubatus; /ˈtʃiːtə/) is a large cat of the subfamily Felinae that occurs in North, Southern and East Africa, and a few localities in Iran.
It inhabits a variety of mostly arid habitats like dry forests, scrub forests, and savannahs. The species is IUCN Red Listed as Vulnerable, as it suffered a
substantial decline in its historic range in the 20th century...
</p>
<a href="https://en.wikipedia.org/wiki/Cheetah" class="btn btn-primary">Learn more</a>
</div>
<div class="card-footer">
from Wikipedia
</div>
</div>
</div>
<div class="col">
<div class="card">
<h5 class="card-header">Voted #3</h5>
<img src="https://cdn.thinglink.me/api/image/601481335449583616/1240/10/scaletowidth" class="card-img-top" alt="panther looking around" style="height: 220px"/>
<div class="card-body">
<h5 class="card-title">Black Panthers</h5>
<h6 class="card-subtitle">Black Panthers Are Really Scary</h6>
<p class="card-text">
A black panther is the melanistic colour variant of any Panthera, particularly of the leopard (P. pardus) in Asia and Africa, and the jaguar (P. onca) in the Americas.
</p>
<a href="https://en.wikipedia.org/wiki/Black_panther" class="btn btn-primary">Learn more</a>
</div>
<div class="card-footer">
from Wikipedia
</div>
</div>
</div>
</div>
Listing 5-13Three Cards
布局
布局很简单。这是通过这个div实现的:
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3">
row-cols-*是为了在期望的断点上布置一列、两列或三列所需要的。
然后每张牌都被包含在一个col div 中:
<div class="col">
所有这些都是必需的,以便您可以实现所需的响应性布局。
每张卡片的 HTML
每张卡片都有类似如下的 HTML 代码:
-
整张卡被封装在一个带有类
card的div中。 -
每张卡都有一个头,它是一个带有类
card-header的h*元素。 -
这个图像是用一个标准的
img元素构造的,这个元素有一个类card-img-top。您还指定了一个特定的高度,这样所有卡片的所有图像都显示在一个特定的高度上,但是占用了所有可用的宽度。 -
然后,卡片的主要内容,也就是图像后面的内容,被放在一个带有类
card-body的 div 中。 -
在主体内部,您通常可以放入任何您想要的 HTML 代码。我们已经把
-
使用一个
h*和一个类别card-title的卡片标题。 -
使用一个
h*和一个card-subtitle类的卡片字幕。 -
有正文的段落。这个有类
card-text。 -
一个包含类
card-link和一些额外类的超链接,使它看起来像一个按钮。
-
-
在主体之后,我们用类
card-footer附加一个div。这是用来创建卡的页脚。
就这样。如果您保存 HTML 页面并将其加载到您的浏览器上,您将会看到您已经在图 5-17 中看到的卡片。
旋转木马
你将用一个叫做旋转木马的非常酷的功能来关闭这个长长的 Twitter 引导参考页面。Twitter Bootstrap 允许你创建图像和视频传送带。旋转木马是页面中逐个显示一系列图像(和/或视频)的区域。每个图像在被下一个图像替换之前会保持可见一段时间(大约 5 秒钟)。
典型的转盘由以下部分组成:
-
小指示器通常显示在底部(图 5-18
![img/497763_1_En_5_Fig18_HTML.jpg]()
图 5-18
旋转指示器
指示器的数量等于转盘中物品的数量。在前面的示例中,有一个包含三个项目的转盘。因此,您可以看到三个条形。用白色填充的表示当前显示的项目。您也可以点按栏以在相应位置快速显示项目。
-
下一个和上一个控件(图 5-19
![img/497763_1_En_5_Fig19_HTML.jpg]()
图 5-19
旋转下一个和上一个控件
下一个和上一个按钮,像箭头一样,允许你从一个项目到另一个项目,向左或向右导航、滑动。
-
物品(图 5-20
![img/497763_1_En_5_Fig20_HTML.jpg]()
图 5-20
轮播项目和标题
传送带有一个项目列表,每个项目都引用一个图像并有一个标题。
说了这么多,很容易识别和理解下面的 HTML 片段,它实现了前面的 carousel。将它修改为主内容容器中 HTML 代码的最后一部分(清单 5-14 )。
<div class="page-header">
<h1>Carousels</h1>
</div>
<div id="carousel-example-generic" class="carousel slide carousel-fade" data-ride="carousel">
<!-- Indicators -->
<ol class="carousel-indicators">
<li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li>
<li data-target="#carousel-example-generic" data-slide-to="1"></li>
<li data-target="#carousel-example-generic" data-slide-to="2"></li>
</ol>
<!-- Wrapper for slides -->
<div class="carousel-inner" role="listbox">
<div class="carousel-item active">
<img src="https://tclf.org/sites/default/files/styles/crop_2000x700/public/thumbnails/image/GovernorsIsland_hero_CharlesABirnbaum_2016_0.jpg"
alt="New York Landscape Image"
class="d-block w-100"
style="height: 500px;">
<div class="carousel-caption d-none d-md-block">
New York
</div>
</div>
<div class="carousel-item">
<img src="https://1920x1080hdwallpapers.com/image/201502/city/338/tokyo-night-landscape-top-view.jpg"
alt="Tokyo Landscape Image"
class="d-block w-100"
style="height: 500px;">
<div class="carousel-caption d-none d-md-block">
Tokyo
</div>
</div>
<div class="carousel-item">
<img src="https://thumbor.forbes.com/thumbor/960x0/https%3A%2F%2Fspecials-images.forbesimg.com%2Fdam%2Fimageserve%2F1154977741%2F960x0.jpg"
alt="Athens Landscape Image"
class="d-block w-100"
style="height: 500px;">
<div class="carousel-caption d-none d-md-block">
Athens
</div>
</div>
</div>
<!-- Controls -->
<a class="carousel-control-prev" href="#carousel-example-generic" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#carousel-example-generic" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
Listing 5-14HTML Fragment for the Carousel
下面是在创建 Twitter 引导轮播时需要注意的一些事项:
-
传送带需要用类别
carousel和slide包含在div中。如果你也想用淡入淡出效果从一张幻灯片过渡到下一张幻灯片,那么你也必须添加类carousel-fade。 -
main
div需要有一个id,就像我们在前面的 HTML 片段(carousel-example-generic)中看到的那样。这是必要的,因为它会被指示器和控件引用。如果在同一个页面上有多个轮播,这个需求就变得更加重要。 -
对于指标
-
它们需要是一个带有类
carousel-indicators的有序列表(ol)。 -
每个项目(
li)都是一个指标,你需要有和你的项目数量一样多的指标。如果你有三个图像,那么你就得有三个指标,也就是li项。 -
每个指示器需要有一个带有转盘 id 的
data-target属性。此外,它需要有一个值等于它所对应的项目的索引/位置的data-slide-to属性。注意,分度/定位从0开始。也就是说,第一个传送带项目用索引0引用,然后第二个用索引1,引用,依此类推。 -
第一个指示器需要有类
active。
-
-
所有的传送带项目都需要用类
carousel-inner包装在一个div中。 -
对于传送带项目
-
每一个都是拥有类
carousel-item的div。 -
第一个需要有类
active;否则,将不会显示转盘。 -
注意,carousel 的图像需要有处理它们的高度和显示属性的类和样式。特别
-
类
d-block和w-100:第一个(d-block)设置图像display属性block的值。第二个(w-100)设置图像宽度为100%。因此,图像将占据整个可用宽度。请注意,这些是显示和调整引导实用程序类。 -
将所有图像的高度设置为相同的样式。在示例中,它被设置为
500px。
-
-
最后,轮播项目可以有一个带有类
carousel-caption的div,作为项目的标题。请注意,您已经在标题上设置了两个额外的显示实用程序类:-
d-none,隐藏字幕。 -
d-md-block,显示中等显示和更宽显示的标题。换句话说,您希望字幕显示在宽度> =768px 的设备上。否则,它们将不会显示。
-
-
-
在 carousel 的内部内容(带有类
carousel-inner的div)下面,您为控件设置 HTML 内容,这是两个锚a元素:-
第一个有类
carousel-control-prev,,它用于导航到前一张/左边的幻灯片。 -
第二个包含类
carousel-control-next,,用于导航到下一张/右边的幻灯片。 -
两者都具有指向传送带 id (
#carousel-example-generic)的属性href。 -
两者都有一个子/内容是
span。此span用于显示左(第一个控件)和右(第二个控件)箭头。对于第一个控件,span 需要有类carousel-control-prev-icon,以便它显示左箭头。对于第二个控件,span 需要有类carousel-control-next-icon,以便它显示右箭头。
-
最终检查站
为了您的方便和复查,这里是您创建的页面的完整内容(清单 5-15 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Twitter Bootstrap Reference Page</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand" href="#">Bootstrap Ref. Page</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar"
aria-controls="navbar"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
<!-- Drop down Menu -->
<li class="nav-item dropdown">
<a href="#"
class="nav-link dropdown-toggle"
data-toggle="dropdown">
Dropdown
</a>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Action</a>
<a href="#" class="dropdown-item">Another action</a>
<a href="#" class="dropdown-item">Something else here</a>
<div class="dropdown-divider"></div>
<div class="dropdown-header">Nav header</div>
<a href="#" class="dropdown-item">Separated link</a>
<a href="#" class="dropdown-item">One more separated link</a>
</div>
</li>
</ul>
</div>
</div>
</nav>
<!-- main content container -->
<div class="container">
<div class="jumbotron">
<p class="lead">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
<h1>Buttons</h1>
<hr class="my-4">
<h2>Small Sizes</h2>
<p>
<button type="button" class="btn btn-sm btn-primary">btn btn-sm btn-primary</button>
<button type="button" class="btn btn-sm btn-secondary">btn btn-sm btn-secondary</button>
<button type="button" class="btn btn-sm btn-success">btn btn-sm btn-success</button>
<button type="button" class="btn btn-sm btn-danger">btn btn-sm btn-danger</button>
<button type="button" class="btn btn-sm btn-warning">btn btn-sm btn-warning</button>
<button type="button" class="btn btn-sm btn-info">btn btn-sm btn-info</button>
<button type="button" class="btn btn-sm btn-light">btn btn-sm btn-light</button>
<button type="button" class="btn btn-sm btn-dark">btn btn-sm btn-dark</button>
<button type="button" class="btn btn-sm btn-link">btn btn-sm btn-link</button>
</p>
<h2>Normal Sizes</h2>
<p>
<button type="button" class="btn btn-primary">btn btn-primary</button>
<button type="button" class="btn btn-secondary">btn btn-secondary</button>
<button type="button" class="btn btn-success">btn btn-success</button>
<button type="button" class="btn btn-danger">btn btn-danger</button>
<button type="button" class="btn btn-warning">btn btn-warning</button>
<button type="button" class="btn btn-info">btn btn-info</button>
<button type="button" class="btn btn-light">btn btn-light</button>
<button type="button" class="btn btn-dark">btn btn-dark</button>
<button type="button" class="btn btn-link">btn btn-link</button>
</p>
<h2>Large Sizes</h2>
<p>
<button type="button" class="btn btn-lg btn-primary">btn btn-lg btn-primary</button>
<button type="button" class="btn btn-lg btn-secondary">btn btn-lg btn-secondary</button>
<button type="button" class="btn btn-lg btn-success">btn btn-lg btn-success</button>
<button type="button" class="btn btn-lg btn-danger">btn btn-lg btn-danger</button>
<button type="button" class="btn btn-lg btn-warning">btn btn-lg btn-warning</button>
<button type="button" class="btn btn-lg btn-info">btn btn-lg btn-info</button>
<button type="button" class="btn btn-lg btn-light">btn btn-lg btn-light</button>
<button type="button" class="btn btn-lg btn-dark">btn btn-lg btn-dark</button>
<button type="button" class="btn btn-lg btn-link">btn btn-lg btn-link</button>
</p>
<h2>Block Sizes</h2>
<p>
<button type="button" class="btn btn-block btn-primary">btn btn-block btn-primary</button>
<button type="button" class="btn btn-block btn-secondary">btn btn-block btn-secondary</button>
<button type="button" class="btn btn-block btn-success">btn btn-block btn-success</button>
<button type="button" class="btn btn-block btn-danger">btn btn-block btn-danger</button>
<button type="button" class="btn btn-block btn-warning">btn btn-block btn-warning</button>
<button type="button" class="btn btn-block btn-info">btn btn-block btn-info</button>
<button type="button" class="btn btn-block btn-light">btn btn-block btn-light</button>
<button type="button" class="btn btn-block btn-dark">btn btn-block btn-dark</button>
<button type="button" class="btn btn-block btn-link">btn btn-block btn-link</button>
</p>
<h2>Outline buttons (Normal Sizes)</h2>
<p>
<button type="button" class="btn btn-outline-primary">btn btn-outline-primary</button>
<button type="button" class="btn btn-outline-secondary">btn btn-outline-secondary</button>
<button type="button" class="btn btn-outline-success">btn btn-outline-success</button>
<button type="button" class="btn btn-outline-danger">btn btn-outline-danger</button>
<button type="button" class="btn btn-outline-warning">btn btn-outline-warning</button>
<button type="button" class="btn btn-outline-info">btn btn-outline-info</button>
<button type="button" class="btn btn-outline-light">btn btn-outline-light</button>
<button type="button" class="btn btn-outline-dark">btn btn-outline-dark</button>
<button type="button" class="btn btn-outline-link">btn btn-outline-link</button>
</p>
<h1>Tables</h1>
<hr class="my-4">
<h2>Shopping List</h2>
<table class="table">
<tr><th colspan="2">Shopping List</th></tr>
<tr><th>Item</th><th>Qt</th></tr>
<tr><td>Cheese</td><td>1 kgr</td></tr>
<tr><td>Rice</td><td>1.5 kgr</td></tr>
<tr><td>Coffee</td><td>0.5 kgr</td></tr>
<tr><td>Milk</td><td>1 ltr</td></tr>
<tr><td>Wine</td><td>1 btl</td></tr>
</table>
<h2>Travel Plan</h2>
<table class="table table-bordered table-striped table-sm">
<tr><th colspan="2">Travel Plan</th></tr>
<tr class="table-active"><th>(active) Action</th><th>Due</th></tr>
<tr class="table-success"><td>(success) Book Ticket</td><td>Feb 20th</td></tr>
<tr class="table-info"><td>(info) Book Hotel</td><td>March 26th</td></tr>
<tr class="table-warning"><td>(warning) Buy Suitcase</td><td>April 20th</td></tr>
<tr class="table-danger"><td>(danger) Get Passport</td><td>April 30th</td></tr>
</table>
<h1>Labels & Badges</h1>
<hr class="my-4">
<h4>
<span class="badge badge-primary">€20.00 - Primary</span>
<span class="badge badge-secondary">€20.00 - Secondary</span>
<span class="badge badge-success">€20.00 - Success</span>
<span class="badge badge-danger">€20.00 - Danger</span>
<span class="badge badge-warning">€20.00 - Warning</span>
<span class="badge badge-info">€20.00 - Info</span>
<span class="badge badge-light">€20.00 - Light</span>
<span class="badge badge-dark">€20.00 - Dark</span>
</h4>
<button class="btn btn-light">Inbox <span class="badge badge-primary badge-pill">1</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-secondary badge-pill">2</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-success badge-pill">3</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-danger badge-pill">4</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-warning badge-pill">5</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-info badge-pill">6</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-light badge-pill">7</span></button>
<button class="btn btn-light">Inbox <span class="badge badge-dark badge-pill">8</span></button>
<h1>Tabs</h1>
<hr class="my-4">
<ul class="nav nav-tabs mb-4">
<li class="nav-item"><a class="nav-link active" href="#dashboard" data-toggle="tab">Dashboard</a></li>
<li class="nav-item"><a class="nav-link" href="#payments" data-toggle="tab">Payments</a></li>
<li class="nav-item"><a class="nav-link" href="#invoices" data-toggle="tab">Invoices</a></li>
<li class="nav-item"><a class="nav-link" href="#settings" data-toggle="tab">Settings</a></li>
</ul>
<div class="tab-content">
<div id="dashboard" class="tab-pane active">
<p>
<strong>Dashboard:</strong> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
<div id="payments" class="tab-pane">
<p>
<strong>Payments:</strong> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
<div id="invoices" class="tab-pane">
<p>
<strong>Invoices:</strong> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
<div id="settings" class="tab-pane">
<p>
<strong>Settings:</strong> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
</div>
<h1>Alerts</h1>
<hr class="my-4">
<div class="alert alert-primary">
A simple primary alert.
</div>
<div class="alert alert-secondary">
A simple secondary alert.
</div>
<div class="alert alert-success">
A simple success alert.
</div>
<div class="alert alert-danger">
A simple danger alert.
</div>
<div class="alert alert-warning">
A simple warning alert.
</div>
<div class="alert alert-info">
A simple info alert.
</div>
<div class="alert alert-light">
A simple light alert.
</div>
<div class="alert alert-dark">
A simple dark alert.
</div>
<div class="alert alert-info">
<strong>London</strong> Read more about London from <a class="alert-link" href="https://en.wikipedia.org/wiki/London">Wikipedia London Link</a>.
</div>
<h1>Progress Bars</h1>
<hr class="my-4">
<div class="progress mb-1 h-4">
<div class="progress-bar bg-primary" style="width: 60%;">60% Complete - primary</div>
</div>
<div class="progress mb-1 h-4">
<div class="progress-bar bg-secondary" style="width: 60%;">60% Complete - secondary</div>
</div>
<div class="progress mb-1 h-4">
<div class="progress-bar bg-success" style="width: 60%;">60% Complete - success</div>
</div>
<div class="progress mb-1 h-4">
<div class="progress-bar bg-danger" style="width: 60%;">60% Complete - danger</div>
</div>
<div class="progress mb-1 h-4">
<div class="progress-bar bg-warning" style="width: 60%;">60% Complete - warning</div>
</div>
<div class="progress mb-1 h-4">
<div class="progress-bar bg-info" style="width: 60%;">60% Complete - info</div>
</div>
<div class="progress mb-1 h-4">
<div class="progress-bar bg-light" style="width: 60%;">60% Complete - light</div>
</div>
<div class="progress mb-1 h-4">
<div class="progress-bar bg-dark" style="width: 60%;">60% Complete - dark</div>
</div>
<div class="progress mb-1 h-4">
<div class="progress-bar bg-primary" style="width: 30%;">30% primary</div>
<div class="progress-bar bg-success" style="width: 50%;">50% success</div>
<div class="progress-bar bg-warning" style="width: 10%;">10% warning</div>
</div>
<h1>Cards</h1>
<hr class="my-4">
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3">
<div class="col">
<div class="card">
<h5 class="card-header">Voted #1</h5>
<img src="https://live.staticflickr.com/3869/14437071224_43fb23705b_h.jpg" class="card-img-top" alt="lion sitting and looking around" style="height: 220px"/>
<div class="card-body">
<h5 class="card-title">Lions</h5>
<h6 class="card-subtitle">Lions Are Amazing</h6>
<p class="card-text">
The lion (Panthera leo) is a large mammal of the Felidae (cat) family. Some large males weigh over 250 kg (550 lb).
Today, wild lions live in sub-Saharan Africa and in Asia. Lions are adapted for life in grasslands and mixed areas
with trees and grass. The relatively small females are fast runners over short distances, and coordinate their hunting of herd animals.
</p>
<a href="https://simple.wikipedia.org/wiki/Lion" class="btn btn-primary">Learn more</a>
</div>
<div class="card-footer">
from Wikipedia
</div>
</div>
</div>
<div class="col">
<div class="card">
<h5 class="card-header">Voted #2</h5>
<img src="http://www.felineworlds.com/wp-content/uploads/Cheetah_Looking_Around_600.jpg" class="card-img-top" alt="cheetah looking around" style="height: 220px"/>
<div class="card-body">
<h5 class="card-title">Cheetahs</h5>
<h6 class="card-subtitle">Cheetahs Are Really Fast</h6>
<p class="card-text">
The cheetah (Acinonyx jubatus; /ˈtʃiːtə/) is a large cat of the subfamily Felinae that occurs in North, Southern and East Africa, and a few localities in Iran.
It inhabits a variety of mostly arid habitats like dry forests, scrub forests, and savannahs. The species is IUCN Red Listed as Vulnerable, as it suffered a
substantial decline in its historic range in the 20th century...
</p>
<a href="https://en.wikipedia.org/wiki/Cheetah" class="btn btn-primary">Learn more</a>
</div>
<div class="card-footer">
from Wikipedia
</div>
</div>
</div>
<div class="col">
<div class="card">
<h5 class="card-header">Voted #3</h5>
<img src="https://cdn.thinglink.me/api/image/601481335449583616/1240/10/scaletowidth" class="card-img-top" alt="panther looking around" style="height: 220px"/>
<div class="card-body">
<h5 class="card-title">Black Panthers</h5>
<h6 class="card-subtitle">Black Panthers Are Really Scary</h6>
<p class="card-text">
A black panther is the melanistic colour variant of any Panthera, particularly of the leopard (P. pardus) in Asia and Africa, and the jaguar (P. onca) in the Americas.
</p>
<a href="https://en.wikipedia.org/wiki/Black_panther" class="btn btn-primary">Learn more</a>
</div>
<div class="card-footer">
from Wikipedia
</div>
</div>
</div>
</div>
<div class="page-header">
<h1>Carousels</h1>
</div>
<div id="carousel-example-generic" class="carousel slide carousel-fade" data-ride="carousel">
<!-- Indicators -->
<ol class="carousel-indicators">
<li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li>
<li data-target="#carousel-example-generic" data-slide-to="1"></li>
<li data-target="#carousel-example-generic" data-slide-to="2"></li>
</ol>
<!-- Wrapper for slides -->
<div class="carousel-inner" role="listbox">
<div class="carousel-item active">
<img src="https://tclf.org/sites/default/files/styles/crop_2000x700/public/thumbnails/image/GovernorsIsland_hero_CharlesABirnbaum_2016_0.jpg"
alt="New York Landscape Image"
class="d-block w-100"
style="height: 500px;">
<div class="carousel-caption d-none d-md-block">
New York
</div>
</div>
<div class="carousel-item">
<img src="https://1920x1080hdwallpapers.com/image/201502/city/338/tokyo-night-landscape-top-view.jpg"
alt="Tokyo Landscape Image"
class="d-block w-100"
style="height: 500px;">
<div class="carousel-caption d-none d-md-block">
Tokyo
</div>
</div>
<div class="carousel-item">
<img src="https://thumbor.forbes.com/thumbor/960x0/https%3A%2F%2Fspecials-images.forbesimg.com%2Fdam%2Fimageserve%2F1154977741%2F960x0.jpg"
alt="Athens Landscape Image"
class="d-block w-100"
style="height: 500px;">
<div class="carousel-caption d-none d-md-block">
Athens
</div>
</div>
</div>
<!-- Controls -->
<a class="carousel-control-prev" href="#carousel-example-generic" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#carousel-example-generic" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
</div>
<!-- end of main content container -->
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 5-15Twitter Bootstrap Reference Page
结束语
这结束了与 Twitter Bootstrap 的长期接触。您已经创建了一个包含大量 Twitter 引导特性的页面,可以用作最常用特性的参考。
然而,Twitter Bootstrap 上还有更多的内容要介绍。这将在下一章中完成。
任务和测验
Task Details

图 5-21
任务页面
- 创建如下所示的网页(图 5-21 )。

图 5-22
任务页面的元素
- 这是一个包含以下元素的页面(图 5-22 )。
关键要点
-
制表符
-
警报
-
进度条
-
信用卡
-
旋转木马
在下一章中,你将学习 Twitter Bootstrap 如何帮助你创建一个背景被图片覆盖的页面。
六、封面项目
这一章教你如何设计导航条的样式,以及如何用一个背景图片来覆盖你网站的整个页面。此外,它还教你一种技术,无论内容的高度如何,都可以垂直对齐。
您将创建如下所示的页面(图 6-1 )。

图 6-1
封面项目
学习目标
-
了解如何将导航栏的非品牌选项拉到右边。
-
了解如何使用
table/table-cell技术使内容垂直和水平居中。
介绍
这一章将教你如何创建另一个好看的 Twitter 引导项目。我称之为封面项目,因为它包含了覆盖整个浏览器页面的大背景图像。所有内容都显示在这一页的顶部。
这个练习的目的是将一些 Twitter Bootstrap 知识与你在《掌握 HTML & CSS 这本书里学到的一些技巧结合起来,这些技巧并不是 Twitter Bootstrap 特有的。
这是您将要构建的页面(图 6-2 )。

图 6-2
您将构建的页面
本页值得注意的事情
-
有一个背景图片覆盖了整个页面。
-
无论页面大小如何,图像都会覆盖页面。
-
虽然原始图像很亮,但页面上显示的图像亮度降低了。这有助于覆盖图像的文本具有更好的对比度,并且更容易阅读。
-
顶部导航栏类似于我们之前构建的导航栏。但是,选项的非品牌部分向右对齐。
-
此页面的主要内容垂直和水平居中。
-
页面底部有一个固定的页脚,文本水平居中对齐。
空的 Twitter 引导页面
让我们从空的 Twitter 引导页面开始(清单 6-1 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Cover Page Project</title>
</head>
<body>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 6-1Empty Twitter Bootstrap Page
将前面的文件另存为index.html,并创建一个空文件stylesheets/main.css。如果你在浏览器上加载这个页面,你会看到一个空页面,但是加载了 Twitter 引导。
背景图像
你应该已经知道如何应用背景图片了(如果没有,请看我之前的书 Master HTML & CSS ,其中有第 22 章题为“图片背景”)。我们将在该页面的body元素上这样做。将以下规则添加到您的stylesheets/main.css文件中(清单 6-2 )。
html {
height: 100%;
background-color: White;
}
body {
min-height: 100%;
background-color: #2b542c;
background-image: url("img/prague-czech-republic.jpg");
background-repeat: no-repeat;
background-attachment: fixed;
background-position: left top;
background-size: 100% 100%;
}
Listing 6-2CSS File Contents
这很标准。
如果您保存并重新加载页面,您将看到以下内容(图 6-3 )。

图 6-3
应用于 Body 元素的背景图像
如图 6-3 所示,图像显示清晰。它覆盖了整个浏览器窗口,如果您尝试调整窗口大小,您会看到它会自动调整以覆盖新的窗口大小。
图像亮度
让我们看看如何降低图像的亮度。我们绝对可以使用 GIMP 或 Adobe Photoshop 这样的图像编辑软件来改变图像的亮度。但是,如果你不知道如何做到这一点,或者如果你不想改变原来的形象,你可以随时做以下技巧。
您将一个div元素定义为body元素的子元素。这个div将被绝对定位在页面的左上角,并将覆盖其父body元素的整个宽度和高度。让我们称之为div cover分部。cover div需要有一个黑色的背景色,但是要有一些透明度,这样它后面的一些图像颜色就可以被看到。你可以试试rgba(0, 0, 0, 0.5)。
就这么办吧。
添加cover div:
<body>
<div id="cover"></div>
</body>
然后添加以下 CSS 规则:
body {
position: relative;
}
#cover {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.5);
}
正如您在前面的代码中看到的那样,#cover上的position: absolute;正确工作的先决条件是其父元素body具有非静态定位。这就是为什么我们将position: relative;设置为body元素。
如果保存前面的代码并在浏览器上重新加载页面,您将看到图 6-4 。

图 6-4
应用了透明度的黑色封面
这正是你想要达到的结果。背景图像现在有点暗,所以你在背景图像上叠加的任何文字都很容易阅读。
导航栏
我们现在要附加一个导航栏,就像我们在前面的章节中所做的那样。
在cover div后增加以下内容(清单 6-3 )。
<nav id="navigation-bar-container" class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<a class="navbar-brand" href="#">Cover</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="navbar-toggler-icon"></span>
</button>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="nav-item"><a class="nav-link" href="#">Home</a></li>
<li class="nav-item"><a class="nav-link" href="#about">About</a></li>
<li class="nav-item"><a class="nav-link" href="#contact">Contact</a></li>
</ul>
</div>
</nav>
Listing 6-3HTML Fragment for the Navigation Bar
如果您保存页面的 HTML 内容并在浏览器上重新加载,您将看到以下内容(图 6-5 )。

图 6-5
增加了标准引导导航栏
如果你注意清单 6-3 中的代码,你会看到在 toggler 按钮之前定义了品牌链接(见图 6-6 )。

图 6-6
Toggler 按钮前的品牌链接
这将使 toggler 按钮出现在最右边。尝试缩短显示器的宽度,您将看到以下内容(图 6-7 )。

图 6-7
托格勒出现在最右边
尝试切换 HTML 片段的位置,首先是按钮,然后是品牌链接,如清单 6-4 所示。
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="#">Cover</a>
Listing 6-4First, the Toggler Button and Then the Brand Link
这将使品牌链接出现在导航栏的最右边,toggler 出现在最左边。参见图 6-8 。

图 6-8
托格勒左,品牌链接右
到目前为止,一切都很好,但是如果你仔细看你想要实现的页面,你会注意到
-
导航栏的左右两边都有一些边距。它不会占据页面的整个宽度。
-
此外,它上面还有一些空白。
-
最后,它的边框有圆角。
在您实际实现前面的需求之前,您还将再设置一个。对于超小型和小型设备,您希望导航条是全宽的,但是对于所有其他情况,导航条只有页面宽度的 50%。
以下 CSS 规则将满足这些要求(清单 6-5 )。
#navigation-bar-container {
margin: 10px auto;
border-radius: 10px;
}
@media (min-width: 768px) {
#navigation-bar-container {
width: 50%;
}
}
Listing 6-5CSS Rules for Navigation Bar Requirements
从前面的代码中可以看出,导航栏的默认宽度是100%,,因为它是一个 div。您正在使用一个@media查询规则,以便为更大的设备将其转换为50%。
在样式表/main.css 中添加上述规则,并在浏览器中重新加载页面。您将看到图 6-9 中描述的内容(假设您有一个宽度为> =768px 的显示器)。

图 6-9
在大型设备上显示的导航栏
如果你将浏览器窗口缩小到 768px 以下,你会看到导航条占据了整个宽度(图 6-10 )。

图 6-10
在< 768px 的设备上,导航栏占据了整个页面宽度
进一步在导航栏上工作,你现在要实现的是把菜单的非品牌选项拉到右边。这可以用需要应用到持有这些选项的ul的ml-auto Twitter Bootstrap 实用程序类轻松完成。
让我们加上ml-auto。而不只是
<ul class="nav navbar-nav">
写
<ul class="nav navbar-nav ml-auto">
ml-auto翻译成页边距左自动。换句话说,ul元素的左边距将自动设置为最大可用值。
如果您保存前面的代码并在浏览器上重新加载页面,您将看到以下内容(图 6-11 )。

图 6-11
选项移至右侧
您尚未使用完导航栏。如果将当前版本与原始版本进行比较,您会发现字体大小和颜色有所不同。
让我们就此对 CSS 规则做如下修改(清单 6-6 )。
#navigation-bar-container a.navbar-brand,
#navbar ul a {
font-weight: 900;
}
#navigation-bar-container a.navbar-brand {
font-size: 3.2rem;
}
#navbar ul a {
font-size: 1.8rem;
}
Listing 6-6CSS Amendments for Font and Color of the Nav Bar
如果您保存前面的代码并在浏览器上重新加载页面,您将看到以下内容(图 6-12 )。

图 6-12
具有所需字体大小和颜色的导航栏
这些是必需的字体大小和颜色属性。这样,你就完成了导航条的工作。
页面中央的内容
您继续尝试实现以下内容(图 6-13 )。

图 6-13
页面中央的内容
有一些 HTML 内容出现在页面的中央,水平和垂直都有。首先,让我们添加 HTML 内容(清单 6-7 )。
<div id="center-content">
<h1>Cover your page.</h1>
<p class="lead">This content will always be vertically and horizontally aligned</p>
<p class="lead">
<a href="#" class="btn btn-lg btn-success">Learn more</a>
</p>
</div>
Listing 6-7Content on the Center of the Page
将前面的代码添加到nav元素的下面,在body元素的结尾之前。这都是非常简单的 HTML 代码。在前面的章节中,你已经了解了这一点。
让我们保存并在您的浏览器上重新加载页面。您将看到以下内容(图 6-14 )。

图 6-14
内容放在左上方—不容易阅读
如您所见,内容已经放在左上方。而且不容易读懂。这就是我们必须介绍我们的z-index技能的地方,因为看起来#cover div是在我们刚才放进去的内容之后画出来的。
但是等等!为什么我们在导航栏上没有同样的问题?这是因为导航栏已经有了带有正整数z-index的position: fixed(等于1030——你只需要用开发工具检查一下就可以确认),而我们的#center-content div有了position static。因此#center-content是第一个未定位的元素:
-
body被定位,因为它有position relative。 -
#cover被定位,因为它有position absolute。 -
#navigation-bar-container被定位,因为它有position fixed。
如果你读了我上一本书 Master HTML & CSS 的第 23 章“元素定位”,你就会知道,如果你控制了定位元素和非定位元素所属的堆栈上下文,它们会玩得很好。每当您使用值不同于auto的z-index属性时,就会启动一个新的堆栈上下文。
换句话说,您将通过将z-index: 0设置为body元素来开始一个新的堆栈上下文。然后,#cover将有一个等于-1的 z-index,因为您希望它位于 body 元素中每个非定位元素的后面。同样,确保你阅读了我上一本书中第 23 章“定位”的最后一部分,其中我解释了浏览器绘制事物的顺序。
说到这里,请继续对body和#cover CSS 规则进行以下修改:
body {
...
z-index: 0;
}
#cover {
...
z-index: -1;
}
如果您在浏览器上保存并加载页面,您将看到以下内容(图 6-15 )。

图 6-15
前景上的内容,但仍然难以阅读文本
从按钮的颜色可以看出,内容现在绘制在前景上。但是,你仍然不能轻松地阅读文本,尽管这只是文本颜色的问题。
先换个颜色吧。您将确保任何文本元素的颜色都是white。将color: white;添加到 CSS 文件中的body元素中。
如果您这样做并重新加载页面,您将看到以下内容(图 6-16 )。

图 6-16
内容现在具有正确的颜色
那很好。内容颜色看起来不错。现在,你需要确定位置。
为了固定位置,您将使用table/table-cell技术:
-
您将告诉浏览器假设包含主要内容的
div是一个表格单元格。您可以通过为这个元素设置display: table-cell;来实现。 -
您将告诉浏览器假设父元素,也称为
body,是一个表。你可以通过为body元素设置display: table;来实现。 -
您希望表格(
body)占据由其父表格(html)定义的所有可用空间。出于这个原因,您将为body元素定义width:100%; height: 100%;。 -
您希望文档根目录占据浏览器窗口给定的所有可用空间。因此,您也将为
html元素设置width: 100%; height: 100%;。 -
您将告诉表格单元格(
center-content div)将其内容水平居中(text-align: center;)和垂直居中(vertical-align: middle;)。
以下是规则(列出 6-8 )。
html {
width: 100%;
height: 100%;
}
body {
display: table;
width: 100%;
height: 100%;
}
#center-content {
display: table-cell;
text-align: center;
vertical-align: middle;
}
Listing 6-8CSS Rules to Make Content Vertically and Horizontally Centered
如果您将前面的规则保存在 CSS 文件中,并在浏览器上重新加载页面,您将看到以下内容(图 6-17 )。

图 6-17
内容正确地放置在页面中央
Note
还有其他技术可以用来垂直居中内容。这种技术和table/table-cell一起确保了即使你改变了实际的内容,顶部和底部的边距也会自动调整。
页脚
现在剩下的就是创建页脚了。这非常简单。让我们先添加footer元素:
<footer id="footer-content">
<small>Copyright © Panos M.</small>
</footer>
在关闭正文之前,添加前面的代码。保存内容并在浏览器上重新加载页面。您将看到以下内容(图 6-18 )。

图 6-18
添加了页脚,但布局被破坏
布局已经被破坏了。但这很容易解决。您需要指定页脚的位置属性:
#footer-content {
position: absolute;
bottom: 20px;
left: 0;
width: 100%;
text-align: center;
}
您需要将上述代码添加到 CSS 规则中。页脚需要有position absolute。保存 CSS 文件并在浏览器上重新加载页面。您将看到以下内容(图 6-19 )。

图 6-19
更正页脚位置后,页面就准备好了
更正页脚位置后,页面就准备好了。
结束语
您已经看到了如何将导航栏选项放在导航栏的右侧。您还了解了垂直和水平居中内容的技巧。
任务和测验
Task Details

图 6-20
任务,封面-游览雅典
-
创建如下所示的网页(图 6-20 )。
-
它类似于您在章节中构建的页面。但是在导航栏上还是有区别的。你能看到吗?
关键要点
-
如何设计导航条的样式并将链接放在右边
-
如何显示背景图像
-
如何在页面中央显示内容
-
如何在页面底部放置页脚
在下一章中,您将学习如何创建一个管理仪表板页面。
七、管理仪表板
在本章中,我们将努力构建一个 Twitter 引导管理仪表板,如下所示(图 7-1 )。

图 7-1
基本管理仪表板
类似图 7-1 中的站点有一个固定位置的侧边栏。侧边栏在超小型设备上消失,仪表板根据设备显示宽度改变其布局。
此外,该表反应灵敏,可以在大型和小型显示器上同样良好地显示。
您还将学习各种其他新概念,比如如何以圆形显示图像,或者如何使用特定于文本颜色的类来改变文本颜色。
学习目标
-
了解如何在导航栏中使用
container或container-fluid元素。 -
了解如何在导航栏中附加搜索表单。
-
了解如何将导航栏搜索表单向右移动。
-
了解如何定义导航栏搜索表单的正确垂直位置。
-
学习如何用
form-control类快速设计输入控件的样式。 -
了解如何在左侧创建边栏。
-
了解如何使侧边栏扩展到全高。
-
了解如何使侧边栏保持在同一位置,即使用户滚动页面的主要内容。
-
了解如何使用可见性类根据显示宽度显示和隐藏页面的各个部分。
-
了解如何在 div 的一侧添加边框。
-
了解如何让一个 div 占据 100%的可用高度。
-
了解如何让一个
ul元素的内容占据整个可用宽度。 -
了解如何创建底部有水平线的漂亮页眉。
-
了解如何以圆形显示图像。
-
了解文本对齐类。
-
学习如何使用响应式图像。
-
了解影响文本颜色的类。
-
了解如何创建响应式表格。
-
了解如何应用多种 Twitter 引导技术来创建一个类似管理员的布局。
介绍
在本章中,您将使用 Twitter Bootstrap 工具创建一个基本的管理仪表板页面。
Note
这是一个很长的章节,有很多新的东西需要你去学习。但是,在你做了一些额外的工作后,你会得到最终结果的回报。
图 7-2 可以看到最后一页。

图 7-2
基本管理仪表板
该页面的特征如下:

图 7-3
超小型设备上的管理仪表板
-
它有一个导航栏,其内容扩展了整个页面的宽度。
-
导航栏非品牌选项靠右对齐。
-
导航栏内有一个搜索表单。
-
有一个带有导航选项的左侧栏。我们称之为左侧导航栏。
-
超小型设备上不显示左侧导航栏(图 7-3 )。
空的 Twitter 引导页面
让我们从空的 Twitter 引导页面开始(清单 7-1 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Admin Dashboard</title>
</head>
<body>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 7-1Empty Twitter Bootstrap Page
导航栏
您将添加和使用的第一个东西是导航栏。
标准导航栏内容
让我们添加标准的导航栏。清单 7-2 包含了导航栏的 HTML 片段,您必须将它添加为body元素的第一个子元素。
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar"
aria-controls="navbar"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="#">Dashboard <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#settings">Settings</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#profile">Profile</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#help">Help</a>
</li>
</ul>
</div>
</nav>
Listing 7-2Navigation Bar
如果您保存并重新加载您的页面,您将看到以下内容(图 7-4 )。

图 7-4
添加导航栏
向右对齐
导航栏的主要选项靠左对齐。你需要把他们带到右边。您已经通过使用ml-auto类学会了如何做到这一点。让我们将ml-auto类添加到保存主要导航选项的ul中(列出 7-3 )。
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar"
aria-controls="navbar"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link active" href="#">Dashboard <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#settings">Settings</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#profile">Profile</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#help">Help</a>
</li>
</ul>
</div>
</nav>
Listing 7-3Adding the ml-auto Class to the ul Element
保存更改并在浏览器上重新加载页面。您将看到以下内容(图 7-5 )。

图 7-5
导航选项向右拉
添加搜索表单
您希望在顶部导航栏中添加一个搜索表单。这不会是选项列表的一部分,但它需要是切换到小设备时折叠的div的一部分,也就是说,是#navbar div 的一部分。
让我们将下面的代码放在#navbar div 中,但是在带有导航选项的ul之前:
<form>
<input type="text" placeholder="Search...">
</form>
因此,nav元素需要如下所示(清单 7-4 )。
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar"
aria-controls="navbar"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
<div class="collapse navbar-collapse" id="navbar">
<form>
<input type="text" placeholder="Search...">
</form>
<ul class="nav navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link active" href="#">Dashboard <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#settings">Settings</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#profile">Profile</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#help">Help</a>
</li>
</ul>
</div>
</nav>
Listing 7-4Navigation Bar with Search Form
如果您保存前面的代码并重新加载页面,您将看到以下内容(图 7-6 )。

图 7-6
导航栏中的搜索表单
搜索表单已经放在了导航栏里面。但是我们想把它移到右边。如果你在表单上添加了ml-auto类,你会得到如下结果(图 7-7 )。

图 7-7
ml-auto搜索表单上的类别
搜索表单不在最右边,而是在选项的左边,因为您需要从ul中移除ml-auto类。你不能同时在搜索表单和ul元素上。
继续将ml-auto从ul元件上移除。如果您保存并重新加载页面,您将看到以下内容(图 7-8 )。

图 7-8
位于右侧的搜索表单
有两个类可以应用于搜索表单,这将使它看起来更好。我将在下一章讨论这些类,但是没有什么可以阻止你现在使用它们来设计搜索表单:
-
在表单 HTML 元素上使用类
form-inline。 -
在输入 HTML 元素上使用类
form-control。
因此,表单标记应该如下所示:
<form class="form-inline ml-auto">
<input type="text" placeholder="Search..." class="form-control">
</form>
如果您在浏览器上保存并重新加载页面,您将看到以下内容(图 7-9 )。

图 7-9
带有样式类的搜索表单
您已经完成了顶部导航栏。既然您已经在其中引入了搜索表单,那么最好检查一下当页面在小型设备上显示时,这个搜索表单是如何显示的(图 7-10 )。

图 7-10
小型设备上的搜索表单和菜单选项
前面布局中的搜索表单有问题。它上面没有任何边距。如果有一些像下面这样的上边距就更好了(图 7-11 )。

图 7-11
带有上边距的搜索表单
为了实现这一点,您可以使用一个 sizing Bootstrap 实用程序类,例如mt-3,它添加了一个大小为 3 的上边距。将表单标记更改如下:
<form class="form-inline ml-auto mt-3">
<input type="text" placeholder="Search..." class="form-control">
</form>
并在浏览器上重新加载页面。切换到小显示器(如 iPhone X)设备。当你打开菜单时,你会看到顶部空白的搜索表单看起来更好,如图 7-11 所示。
但是,如果您切换回大显示设备,您将看到以下内容(图 7-12 )。

图 7-12
在大显示器上搜索表单上边距
正如你所看到的,因为mt-3的存在,导航栏的布局已经被破坏了。换句话说
-
当菜单选项折叠时,您只希望在小设备上使用
mt-3。 -
当菜单选项展开时,你不想要
mt-3。
您知道您的菜单在lg断点上展开(感谢navbar-expand-lg类)。因此,当你在lg断点之上时,为了否定mt-3类的效果,你将添加mt-lg-0类。因此,表单标记应该是
<form class="form-inline ml-auto mt-3 mt-lg-0">
<input type="text" placeholder="Search..." class="form-control">
</form>
同样,前面的标记在显示小于lg断点的设备上保留了mt-3,并在显示大于lg断点的设备上使用了类mt-lg-0。
如果您保存前面的代码并在浏览器上重新加载页面,您将看到导航栏恢复了正确的样式。而缩小到一个小显示屏上,依然能按预期工作。
使用 Flex 实用程序类对齐
您已经使用 margin 实用程序类将导航栏的项目向右对齐。但是 Twitter Bootstrap 严重依赖于 flexbox 。它提供了可以用来相应地对齐内容的类。
例如,您可以使用类flex-row-reverse并让您的 HTML 标记逆序排列。这样做,您不需要在表单元素上使用ml-auto。见下文我的意思(列表 7-5 )。
-
您已经在
ul标记之后编写了form标记。 -
您已经在包含菜单选项和搜索表单的
div上添加了类flex-row-reverse。 -
您已经从
form标记中移除了边距类。
<div class="collapse navbar-collapse flex-row-reverse" id="navbar">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="#">Dashboard <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#settings">Settings</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#profile">Profile</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#help">Help</a>
</li>
</ul>
<form class="form-inline">
<input type="text" placeholder="Search..." class="form-control">
</form>
</div>
Listing 7-5Using flex-row-reverse
如果您保存前面的代码并在浏览器上加载页面,您将看到以下内容(图 7-13 )。

图 7-13
使用 flex-row-reverse 在右侧绘制项目
如您所见,flex-row-reverse div的直接子元素是以相反的顺序绘制的,也就是说,首先是搜索form,然后是ul元素。
请注意,我们将form移到了div的底部,这使得小设备看起来也更好。搜索表单显示在底部。flex-row-reverse对这些设备没有任何影响,因为菜单选项是从上到下显示的(图 7-14 )。

图 7-14
搜索表单出现在底部
一切都好!现在,让我们移到左侧导航栏。
左侧导航栏
我们现在开始构建左侧导航栏(图 7-15 )。

图 7-15
左侧导航栏属性
如图 7-15 所示,左侧导航栏应该有一些属性:
-
它的背景色不是白色;它更像是灰色的。
-
活动菜单项具有白色和蓝色背景色。
-
有三组菜单项,也就是三个不同的列表。
-
它占据了页面的特定宽度。让我们假设中型、大型和超大型设备的宽度为六分之一(即 12 列中的两列),小型设备的宽度为四分之一(即 12 列中的三列)。在超小型设备上,侧边栏将不可见。
布局
先说第四个属性。因为我们希望侧边栏占据页面宽度的一部分,所以我们将使用正确的网格类。在nav元素下添加以下内容(清单 7-6 )。
<div id="main-container" class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2">
<!-- Left Sidebar Content will go here -->
</div>
<div id="main-content-container" class="col-sm-9 col-md-10">
<!-- Main Content will go here -->
</div>
</div>
</div>
Listing 7-6Layout Markup
正如你在前面的代码中看到的,我们有一个侧边栏的div,它使用网格类col-sm-3用于小型设备,因此占据了 12 列中的 3 列,使用类col-md-2用于中型、大型和超大型设备,因此占据了 12 列中的 2 列。
主要内容将放在第二个div中,它也使用网格类col-sm-9和col-md-10,因此它占据了剩余的可用宽度。对于小型设备,它将占据 12 列中的 9 列;对于中型、大型和超大型设备,它将占据 12 列中的 10 列。
保存前面的内容。如果您在浏览器上再次加载该页面,您将看不到任何区别,因为侧边栏和主内容中没有任何实际内容。
侧边栏中的列表
您已经在左侧导航栏中确定了三个列表。让我们像往常一样用ul元素创建它们(列出 7-7 )。
<div id="main-container" class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2">
<!-- Left Sidebar Content will go here -->
<ul>
<li class="active"><a href="#">Overview</a></li>
<li><a href="#">Reports</a></li>
<li><a href="#">Analytics</a></li>
<li><a href="#">Export</a></li>
</ul>
<ul>
<li><a href="#">Nav item</a></li>
<li><a href="#">Nav item again</a></li>
<li><a href="#">One more nav</a></li>
<li><a href="#">Another nav item</a></li>
<li><a href="#">More navigation</a></li>
</ul>
<ul>
<li><a href="#">Nav item again</a></li>
<li><a href="#">One more nav</a></li>
<li><a href="#">Another nav item</a></li>
</ul>
</div>
<div id="main-content-container" class="col-sm-9 col-md-10">
<!-- Main Content will go here -->
</div>
</div>
</div>
Listing 7-7HTML with ul Elements for the Lists
如果您保存前面的代码并在浏览器上重新加载页面,您将看到以下内容(图 7-16 )。

图 7-16
左侧栏—添加了列表
你现在看到的一个问题是顶部列表被导航栏隐藏了。这是你过去曾经面临过的问题。您需要给正文内容一些顶部填充,至少等于导航栏的高度。你就给56px。
在stylesheets/main.css文件中,添加以下规则:
body {
padding-top: 56px;
}
在浏览器上保存并重新加载页面。您将看到以下内容(图 7-17 )。

图 7-17
导航栏不会隐藏列表
这是一个进步。现在,您将在列表上应用类nav。正如您在前面章节中所记得的,ul元素上的nav类删除了列表项上显示的默认项目符号。
继续将类nav添加到左侧导航栏的所有ul元素中。然后在浏览器上加载页面。您将看到以下内容(图 7-18 )。

图 7-18
应用于 ul 元素的类别nav
类nav已经从列表的元素中移除了项目符号。但它也做了其他事情。它把ul元素变成了display flex,flex-wrap等于wrap。这就是为什么你会看到li元素一个挨着一个。
因为您希望列表从上到下排列,所以您可以添加类flex-column,它将使所有的直接子元素都绘制在一列中。
继续,在nav类的旁边,也添加flex-column类。在浏览器上保存并加载页面。您将看到以下内容(图 7-19 )。

图 7-19
flex-column应用的类别
左边栏开始看起来好多了。然而,它还没有完成。
隐藏超小型设备上的侧边栏
您想要隐藏超小型设备上的侧边栏,只为小型、中型、大型和超大型设备显示侧边栏。您可以使用显示实用程序类来实现这一点:
-
类
d-none将隐藏元素。 -
类
d-sm-block将在sm断点之上显示任何显示的元素。
让我们将它应用于保存左侧导航栏列表的容器div。清单 7-8 给出了 HTML 标记片段。
<div class="col-sm-3 col-md-2 d-none d-sm-block">
<!-- Left Sidebar Content will go here -->
<ul class="nav flex-column">
<li class="active"><a href="#">Overview</a></li>
<li><a href="#">Reports</a></li>
<li><a href="#">Analytics</a></li>
<li><a href="#">Export</a></li>
</ul>
<ul class="nav flex-column">
<li><a href="#">Nav item</a></li>
<li><a href="#">Nav item again</a></li>
<li><a href="#">One more nav</a></li>
<li><a href="#">Another nav item</a></li>
<li><a href="#">More navigation</a></li>
</ul>
<ul class="nav flex-column">
<li><a href="#">Nav item again</a></li>
<li><a href="#">One more nav</a></li>
<li><a href="#">Another nav item</a></li>
</ul>
</div>
Listing 7-8HTML Fragment for the Container of the Left-Side Navigation Bar
如果您在浏览器上保存并重新加载页面,您将会看到左侧导航栏隐藏在宽度为 575px 的显示屏上(图 7-20 )。

图 7-20
575px 显示屏上隐藏的左侧栏
但是,它在 576px 显示器上是可见的(图 7-21 )。

图 7-21
576px 显示器上可见的侧边栏
侧边栏的进一步样式
现在,您将进一步设计侧栏的样式。为了做到这一点,您将在保存三个列表的div容器上应用类sidebar,然后您将为这个特定的类编写一些 CSS 规则。以下是规则(列出 7-9 )。
.sidebar {
padding-top: 10px;
padding-bottom: 10px;
background-color: #f5f5f5;
border-right: 1px solid #eee;
}
Listing 7-9First Styling Rules for the Left Sidebar
不要忘记将类sidebar添加到包含三个ul元素和左侧导航栏选项的div中。
然后,保存并在浏览器上重新加载页面。您将看到以下内容(图 7-22 )。

图 7-22
侧边栏上的一些样式
前面的样式设置了侧边栏右侧的背景颜色和边框,以及顶部和底部的一些填充。
现在,您需要确保侧边栏的高度占据了整个可用高度。为此,您需要在row div及其所有祖先元素上指定height: 100%。
确保stylesheets/main.css文件包含以下内容(列表 7-10 )。
html {
height: 100%;
}
body {
padding-top: 56px;
height: 100%;
}
#main-container,
#main-container .row{
height: 100%;
}
.sidebar {
padding-top: 10px;
padding-bottom: 10px;
background-color: #f5f5f5;
border-right: 1px solid #eee;
}
Listing 7-10stylesheets/main.css File Content
注意,#main-container指的是保存页面主要内容的容器的 id,正好在nav元素之后。为了帮助您,#main-container的 HTML 片段应该如清单 7-11 所示。
<div id="main-container" class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 d-none d-sm-block sidebar">
<!-- Left Sidebar Content will go here -->
<ul class="nav flex-column">
<li class="active"><a href="#">Overview</a></li>
<li><a href="#">Reports</a></li>
<li><a href="#">Analytics</a></li>
<li><a href="#">Export</a></li>
</ul>
<ul class="nav flex-column">
<li><a href="#">Nav item</a></li>
<li><a href="#">Nav item again</a></li>
<li><a href="#">One more nav</a></li>
<li><a href="#">Another nav item</a></li>
<li><a href="#">More navigation</a></li>
</ul>
<ul class="nav flex-column">
<li><a href="#">Nav item again</a></li>
<li><a href="#">One more nav</a></li>
<li><a href="#">Another nav item</a></li>
</ul>
</div>
<div id="main-content-container" class="col-sm-9 col-md-10">
<!-- Main Content will go here -->
</div>
</div>
</div>
Listing 7-11#main-container HTML Content
如果您保存前面的代码并在浏览器上重新加载页面,您将看到以下内容(图 7-23 )。

图 7-23
侧边栏占据了整个高度
您将继续侧边栏的样式:
-
您将确保用户能够区分一组选项和下一组选项。您将在侧边栏的
ul元素上应用底部边距。 -
您将增加列表中元素的高度,以便选项非常明显,并且从一个到下一个有一些垂直空间。
-
您希望列表占据所有可用的宽度。因此当鼠标指针移动到任何元素上时,突出显示从左到右进行。为了实现这一点,您将从侧边栏容器中移除左右填充。
-
但是,您希望每个列表项都有一些填充,这样文本就不会从栏的左边缘开始。
这里是您必须应用的更改上带有蓝色的stylesheets/main.css的内容(列表 7-12 )。
html {
height: 100%;
}
body {
padding-top: 56px;
height: 100%;
}
#main-container,
#main-container .row{
height: 100%;
}
.sidebar {
padding: 10px 0;
background-color: #f5f5f5;
border-right: 1px solid #eee;
}
.sidebar ul {
margin-bottom: 20px;
}
.sidebar ul li {
padding-left: 10px;
min-height: 2.2rem;
}
Listing 7-12Further Styling of the Sidebar
如果您在浏览器上保存并重新加载页面,您将看到以下内容(图 7-24 )。

图 7-24
左侧栏的进一步样式化
你继续在侧边栏菜单的选项上应用一些背景和前景色。以下是您需要应用的额外 CSS 规则(清单 7-13 )。
.sidebar ul li a {
text-decoration: none;
}
/* Active <li> and <a>, and for hover over NON-active <li> and <a> */
.sidebar ul li.active,
.sidebar ul li.active a,
.sidebar ul li:hover,
.sidebar ul li:hover a,
.sidebar ul li a:hover {
background-color: #428BCA;
color: White;
}
.sidebar ul li:hover {
cursor: pointer;
}
Listing 7-13Extra CSS Rules for Left Sidebar Options
如果您在浏览器上保存并加载页面,您将看到以下内容(图 7-25 )。

图 7-25
颜色选项
如果您将鼠标移动到左侧导航栏的选项上,您会看到它们获得了不同的背景颜色和文本颜色。此外,光标正在变成鼠标指针(图 7-26 )。

图 7-26
悬停在非活动选项上
主要内容区域
您停止样式化侧边栏,并继续构建主要内容区域。您将从仪表板顶部区域开始,在该区域中,您应该呈现一系列图表(图 7-27 )。

图 7-27
仪表板—带图表的顶部区域
请注意以下关于目标的内容:

图 7-28
在超小型设备上—每行两个信息容器
-
底部有一个带横线的
Dashboard表头。你可以用你在前面章节看到的hr和my-4类来创建这个效果。 -
您可以看到四个信息容器(图形图像+文本)。
-
在超大显示屏上,一行显示四个信息容器。大中型设备也是如此。在小型和超小型设备上,我们每行显示两个信息容器(图 7-28 )。
-
您将为图形图像使用一些占位符图像。
我们开始吧。
仪表板标题
首先,添加Dashboard标题:
<h1>Dashboard</h1>
<hr class=my-4>
添加前面的代码作为#main-content-container的第一个子元素。在浏览器上保存并重新加载页面。您将看到以下内容(图 7-29 )。

图 7-29
添加了仪表板页面标题
这很简单,你过去也这么做过。现在,在元素hr和类my-4的帮助下,您可以看到样式为页眉的Dashboard。
信息容器
信息容器是 HTML 代码块,包含
-
一个图像,一个
img元素 -
一个小标签,在一个
h4元素里面 -
标签下方显示一些文本的范围
<img src="https://via.placeholder.com/200" width="200" height="200"
alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span>Something else</span>
每一个容器——我们有四个——我们需要用正确的 Twitter 引导网格类包含在一个div中:
<div class="col-6 col-md-3">
<img src="https://via.placeholder.com/200" width="200" height="200"
alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span>Something else</span>
</div>
div有网格类col-6和col-md-3。在超小型和小型设备上,每个信息容器块将占用一半的可用宽度(12 列中的 6 列)。因此,每行将有两个这样的列。在较大的设备上,它将占据可用宽度的四分之一(12 列中的三列)。因此,每行将有四个这样的列。
您需要再重复三次,并用类row将整组div列封装到一个div(清单 7-14 )。
<div class="row">
<div class="col-6 col-md-3">
<img src="https://via.placeholder.com/200" width="200" height="200"
alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span>Something else</span>
</div>
<div class="col-6 col-md-3">
<img src="https://via.placeholder.com/200" width="200" height="200"
alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span>Something else</span>
</div>
<div class="col-6 col-md-3">
<img src="https://via.placeholder.com/200" width="200" height="200"
alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span>Something else</span>
</div>
<div class="col-6 col-md-3">
<img src="https://via.placeholder.com/200" width="200" height="200"
alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span>Something else</span>
</div>
</div>
Listing 7-14HTML Fragment with Information Blocks
将前面的代码放在Dashboard div容器的正下方。保存文件并在浏览器上重新加载页面。您将看到以下内容(图 7-30 )。

图 7-30
仪表板—放在页面上的信息容器
现在,信息容器已经成功地放置在页面上,在页面标题的下面。但是您需要做一些风格调整,以达到预期的效果。
让我们首先确保图像显示为圆形。这很容易做到。您只需在img元素上添加类rounded-circle。
如果您这样做了,保存并在浏览器上重新加载页面,您将看到以下内容(图 7-31 )。

图 7-31
信息容器具有圆形的图像
接下来,您要做的是确保信息容器的图像和文本都居中对齐。您将使用类text-center来包装图像和文本的所有div元素。
text-center是 Twitter Bootstrap 提供的一个类。它实际上将 CSS 样式text-align: center;应用到它所附加的元素上。Twitter Bootstrap 提供了更多与对齐相关的类。完整列表如下:
-
text-left:对应text-align: left; -
text-right:对应text-align: right; -
text-center:对应text-align: center; -
text-justify:对应text-align: justify;
此外,您可以使用这些类及其特定于断点的变体。例如,您可以使用 t ext-md-center类,它将使内容居中,但仅适用于中等或更宽的显示。
继续在所有信息容器上应用类text-center,然后在浏览器上重新加载页面。您将看到以下内容(图 7-32 )。

图 7-32
内容居中对齐
虽然图 7-32 看起来好像你已经完成了信息容器,但是如果你在一个宽度较短的设备上看到你的页面,有一个小问题变得很明显。例如,使用您的开发工具尝试 iPad 模拟。您将看到以下内容(图 7-33 )。

图 7-33
图像在 iPad 上显示不正常
如果您将类img-fluid应用于img元素,就可以解决这个问题。就这么办吧。然后在浏览器上重新加载页面。您将看到以下内容(图 7-34 )。

图 7-34
使用img-fluid类时,图像显示正常
img-fluid类做两件事:
-
它将
max-width设置为100%。这意味着图像宽度不能比图像所在的父块宽。 -
它将
height设置为auto。这意味着高度将根据宽度自动计算,以便图像具有正确的纵横比。
有了这些限制,图像最终可以在任何显示尺寸下正确绘制。
剩下要做的就是改变文本Something else的颜色。它需要是浅灰色的(见图 7-35 )。

图 7-35
“其他东西”短语的颜色
只需应用其中一个 Twitter Bootstrap 颜色实用程序类,就可以快速轻松地对文本元素的颜色进行更改。这些类别是
-
text-primary -
text-secondary -
text-success -
text-danger -
text-warning -
text-info -
text-light -
text-dark -
text-body -
text-muted -
text-white -
text-black-50 -
text-white-50
你可以在图 7-36 中看到它们的颜色等价物。

图 7-36
引导文本颜色实用程序类
让我们在保存Something else文本的 span 上应用类text-black-50。在浏览器上保存并加载页面。您将看到以下内容(图 7-37 )。

图 7-37
应用了 text-black-50 类的“其他内容”短语
在我们结束关于信息容器的这一部分之前,我将在这里给出应该存在于#main-content-container div中的 HTML 片段,因为它直到现在都是由仪表板标题和信息块组成的。参见清单 7-15 。
<div id="main-content-container" class="col-sm-9 col-md-10">
<!-- Main Content will go here -->
<h1>Dashboard</h1>
<hr class="my-4">
<div class="row">
<div class="col-6 col-md-3 text-center">
<img src="https://via.placeholder.com/200" width="200" height="200"
class="rounded-circle img-fluid"
alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span class="text-black-50">Something else</span>
</div>
<div class="col-6 col-md-3 text-center">
<img src="https://via.placeholder.com/200" width="200" height="200"
class="rounded-circle img-fluid"
alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span class="text-black-50">Something else</span>
</div>
<div class="col-6 col-md-3 text-center">
<img src="https://via.placeholder.com/200" width="200" height="200"
class="rounded-circle img-fluid"
alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span class="text-black-50">Something else</span>
</div>
<div class="col-6 col-md-3 text-center">
<img src="https://via.placeholder.com/200" width="200" height="200"
class="rounded-circle img-fluid"
alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span class="text-black-50">Something else</span>
</div>
</div>
</div>
Listing 7-15Main Container Content
仪表板表
管理页面的下一部分是仪表板表。您已经学习了如何使用 Twitter Bootstrap 设计表格。所以这不会是一个困难的练习。
节标题
您可以使用下面这段 HTML 代码添加节标题:
<h2>Section title</h2>
<hr class="my-4">
将它放在包含您之前实现的信息容器的结束row div之后。如果您保存代码并在浏览器上重新加载页面,您将看到以下内容(图 7-38 )。

图 7-38
不显示部分标题
如您所见,没有显示部分标题。这是为什么呢?事实上,如果您向下滚动,您可以看到该部分的标题。它位于页面底部,如图 7-39 所示。

图 7-39
页面底部的部分标题
为什么会这样?这是因为你已经将100% height应用到了#main-container .row CSS 选择器中(参见你的stylesheets/main.css文件)。这条规则是为了让侧边栏占据整个高度。但是,从我们添加一个额外的row div元素(保存信息块的元素)开始,这条规则也适用于那个div。这最后一个应用程序在您看到的位置推送了部分标题(图 7-40 )。

图 7-40
嵌套 Div 100%高度如何影响布局
您真正想要的是这个 100% height CSS 语句只应用于#main-container div 中的第一级嵌套div。为了做到这一点,规则
#main-container,
#main-container .row {
height: 100%
}
需要更改为
#main-container,
#main-container > .row {
height: 100%
}
>是直接子选择器。前面的 CSS 规则选择了#main-container以及它的第一级直接子元素.row。
为了确保你的代码是对齐的,我在这里给你你的页面应该使用的整个stylesheets/main.css文件(清单 7-16 )。
html {
height: 100%;
}
body {
padding-top: 56px;
height: 100%;
}
#main-container,
#main-container > .row {
height: 100%
}
.sidebar {
padding: 10px 0;
background-color: #f5f5f5;
border-right: 1px solid #eee;
}
.sidebar ul {
margin-bottom: 20px;
}
.sidebar ul li {
padding-left: 10px;
padding-top: 5px;
min-height: 2.2rem;
}
.sidebar ul li a {
text-decoration: none;
}
/* Active <li> and <a>, and for hover over NON-active <li> and <a> */
.sidebar ul li.active,
.sidebar ul li.active a,
.sidebar ul li:hover,
.sidebar ul li:hover a,
.sidebar ul li a:hover {
background-color: #428BCA;
color: White;
}
.sidebar ul li:hover {
cursor: pointer;
}
Listing 7-16stylesheets/main.css Content
如果您保存前面的代码并在浏览器上重新加载页面,您将看到以下内容(图 7-41 )。

图 7-41
部分标题在正确的位置
我在这个布局上看到的一个问题是,部分标题在顶部需要一些空间。您可以通过将类mt-4添加到部分的 h2 来添加一些顶部边距:
<h2 class="mt-4">Section title</h2>
如果你保存了这个更改,并在浏览器上重新加载页面,你会看到如下(图 7-42 ),这就好多了。

图 7-42
有一些上边距的部分
桌子
现在让我们在部分标题下添加表格(清单 7-17 )。
<p>Sales table is compiled from data retrieved from the main database</p>
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
<th>Header 4</th>
<th>Header 5</th>
<th>Header 6</th>
<th>Header 7</th>
<th>Header 8</th>
</tr>
</thead>
<tbody>
<tr>
<td>1,001</td>
<td>Lorem</td>
<td>ipsum</td>
<td>dolor</td>
<td>sit</td>
<td>Lorem</td>
<td>ipsum</td>
<td>dolor</td>
<td>sit</td>
</tr>
<tr>
<td>1,002</td>
<td>amet</td>
<td>consectetur</td>
<td>adipiscing</td>
<td>elit</td>
<td>amet</td>
<td>consectetur</td>
<td>adipiscing</td>
<td>elit</td>
</tr>
<tr>
<td>1,003</td>
<td>Integer</td>
<td>nec</td>
<td>odio</td>
<td>Praesent</td>
<td>Integer</td>
<td>nec</td>
<td>odio</td>
<td>Praesent</td>
</tr>
<tr>
<td>1,003</td>
<td>libero</td>
<td>Sed</td>
<td>cursus</td>
<td>ante</td>
<td>libero</td>
<td>Sed</td>
<td>cursus</td>
<td>ante</td>
</tr>
<tr>
<td>1,004</td>
<td>dapibus</td>
<td>diam</td>
<td>Sed</td>
<td>nisi</td>
<td>dapibus</td>
<td>diam</td>
<td>Sed</td>
<td>nisi</td>
</tr>
<tr>
<td>1,005</td>
<td>Nulla</td>
<td>quis</td>
<td>sem</td>
<td>at</td>
<td>Nulla</td>
<td>quis</td>
<td>sem</td>
<td>at</td>
</tr>
<tr>
<td>1,006</td>
<td>nibh</td>
<td>elementum</td>
<td>imperdiet</td>
<td>Duis</td>
<td>nibh</td>
<td>elementum</td>
<td>imperdiet</td>
<td>Duis</td>
</tr>
<tr>
<td>1,007</td>
<td>sagittis</td>
<td>ipsum</td>
<td>Praesent</td>
<td>mauris</td>
<td>sagittis</td>
<td>ipsum</td>
<td>Praesent</td>
<td>mauris</td>
</tr>
<tr>
<td>1,008</td>
<td>Fusce</td>
<td>nec</td>
<td>tellus</td>
<td>sed</td>
<td>Fusce</td>
<td>nec</td>
<td>tellus</td>
<td>sed</td>
</tr>
<tr>
<td>1,009</td>
<td>augue</td>
<td>semper</td>
<td>porta</td>
<td>Mauris</td>
<td>augue</td>
<td>semper</td>
<td>porta</td>
<td>Mauris</td>
</tr>
<tr>
<td>1,010</td>
<td>massa</td>
<td>Vestibulum</td>
<td>lacinia</td>
<td>arcu</td>
<td>massa</td>
<td>Vestibulum</td>
<td>lacinia</td>
<td>arcu</td>
</tr>
<tr>
<td>1,011</td>
<td>eget</td>
<td>nulla</td>
<td>Class</td>
<td>aptent</td>
<td>eget</td>
<td>nulla</td>
<td>Class</td>
<td>aptent</td>
</tr>
<tr>
<td>1,012</td>
<td>taciti</td>
<td>sociosqu</td>
<td>ad</td>
<td>litora</td>
<td>taciti</td>
<td>sociosqu</td>
<td>ad</td>
<td>litora</td>
</tr>
<tr>
<td>1,013</td>
<td>torquent</td>
<td>per</td>
<td>conubia</td>
<td>nostra</td>
<td>torquent</td>
<td>per</td>
<td>conubia</td>
<td>nostra</td>
</tr>
<tr>
<td>1,014</td>
<td>per</td>
<td>inceptos</td>
<td>himenaeos</td>
<td>Curabitur</td>
<td>per</td>
<td>inceptos</td>
<td>himenaeos</td>
<td>Curabitur</td>
</tr>
<tr>
<td>1,015</td>
<td>sodales</td>
<td>ligula</td>
<td>in</td>
<td>libero</td>
<td>sodales</td>
<td>ligula</td>
<td>in</td>
<td>libero</td>
</tr>
</tbody>
</table>
Listing 7-17
Table HTML Fragment
如果您保存前面的代码并在浏览器上重新加载页面,您将看到以下内容(图 7-43 )。

图 7-43
表格显示正确
但是,在小型设备上查看页面时有一个小问题。尝试 iPhone X 仿真。您将看到该表被截断。实际上,页面是水平扩展的,以便显示整个表数据。如果用户滚动是为了显示隐藏的其余表格数据,那么图像图形也会向左滚动,最终体验非常糟糕。见图 7-44 中的问题截图。

图 7-44
移动设备上的表格样式不佳
有一个非常简单的方法可以解决这个问题。你可以使用 Twitter 引导类table-responsive。您需要将这个类交给table元素。事实上,只为超小型、小型和中型设备设置它可能是一个更好的主意。对于大型和超大型设备,您可以让该表默认运行。
因此,继续将类table-responsive-lg附加到表中。该类执行以下操作:从lg断点开始,表将正常运行。但是在这个断点之下,也就是说,对于 displays < 992px,它将自动获得一个overflow-x: auto;,而不需要您将它添加到您的 CSS 规则中,这将允许用户水平滚动以查看表格的全部内容。
为 iPhone X 模拟器保存并重新加载浏览器上的页面。您将看到以下内容(图 7-45 )。

图 7-45
表格在 iPhone X 上显示正确
如果水平滚动,您会看到页面的其余部分仍然正确显示。
一些最后的调整
您已经设法使页面看起来与您最初作为目标的页面一模一样。有一个小的改进,我想和你一起努力。
当浏览器高度较低时,用户在主仪表板区域上滚动,以便访问/查看不可见的表格内容。例如,在下面的示例中,您可以看到当用户滚动到页面底部以显示表格底部时所看到的内容(图 7-46 )。

图 7-46
左侧导航栏有问题
如您所见,左侧导航栏有问题。随着侧边栏内容与主内容的其余部分一起滚动,选项消失了。您希望所有的侧边栏选项在任何时候都是可访问和可见的,这样无论主内容的实际滚动位置如何,用户都可以点击它们。
为了让一个div always可见,不管浏览器窗口的滚动位置如何,你需要固定它的位置。让我们在 CSS 文件中添加以下内容:
/* fix the position of the sidebar */
position: fixed;
left: 0;
top: 56px;
在sidebar CSS 选择器块中添加前面的 CSS 属性。保存前面的代码,并在浏览器上加载页面。你会看到类似图 7-47 的东西。

图 7-47
位置固定的侧边栏—主要内容有问题
相对于固定位置的侧边栏,这是一个改进。尽量滚动主要内容;你会看到边栏上的所有选项都是可见的。
另一方面,它将主要内容部分带到了左侧,与侧边栏内容重叠。这是因为侧边栏div不是普通页面元素流的一部分。您已经用网格类col-sm-3和col-md-2指定了侧边栏div的宽度,但是实际位置是固定的,因此,当浏览器定位#main-content-container div时,不会考虑这个元素。
你如何解决这个问题?有一个非常简单的解决方案。你只需要对 Bootstrap 说,将容器行的内容向右对齐。在justify-content-*类的帮助下,尤其是在justify-content-end类的帮助下,您已经学会了如何做到这一点。
将类 justify-content-end 添加到所有内容的父行中:
<div id="main-container" class="container-fluid">
<div class="row justify-content-end">
<div class="col-sm-3 col-md-2 d-none d-sm-block sidebar">
<!-- Left Sidebar Content will go here -->
...
如果保存 HTML 内容并在浏览器上加载页面,您将看到以下内容(图 7-48 )。

图 7-48
主要内容两端对齐的仪表板
最后一个需要解决的问题是左侧导航栏没有延伸到窗口底部。这是意料之中的,因为您已经将sidebar div变成了一个位置固定的定位元素。定位的元素根据它们包含的内容扩展到必要的宽度和高度。
通过将min-height属性设置为 100%,可以很容易地改变sidebar div的高度。继续将这个 CSS 属性添加到你的stylesheets/main.css文件中。然后在浏览器上重新加载页面。你会看到图 7-49 。

图 7-49
全高左侧栏
完美!左侧边栏现在占据了整个高度。尝试滚动和更改显示宽度。你会看到一切都如预期的那样工作。
任务和测验
Task Details

图 7-51
任务—管理控制面板(页面底部)

图 7-50
任务—管理控制面板(页面顶部)
-
您需要实现如下所示的页面(图 7-50 和图 7-51 )。
-
When the page is displayed on medium devices, two information containers per row should be displayed (Figure 7-53).
![img/497763_1_En_7_Fig53_HTML.jpg]()
图 7-53
中型设备上每行两个信息容器
-
你需要注意的事情如下:
-
你需要使用字体系列
Anonymous Pro。看看谷歌字体。 -
侧栏
-
不应将其高度扩展到等于可用的最大高度
-
应该有透明的背景色
-
应该有一个彩色的
#eee边框,纯色,周围 1px -
它的边界半径应该是 2px
-
即使我们滚动主要内容区域,它的位置也应该是固定的
-
位置应该是左 10px,上 70px
-
应该让仪表板区域由 300 × 300 的图像占位符组成
注:如果您想生成此类占位符,请访问
https://placehold.it,了解如何生成占位符。例如,您可以访问https://placehold.it/450x450,您将获得一个具有所请求的 450px × 450px 尺寸的图像占位符。您可以右键单击并选择Save Image,以便将其作为图像文件保存在您的计算机中,供以后在您的站点中使用。 -
When the page is displayed on extrasmall and small devices, only one information container per row should be displayed (Figure 7-52).
![img/497763_1_En_7_Fig52_HTML.jpg]()
图 7-52
超小型设备上每行一个信息容器
-
-
-
When the page is displayed on large and extralarge devices, three information containers per row should be displayed (Figure 7-54).
![img/497763_1_En_7_Fig54_HTML.jpg]()
图 7-54
大型设备上每行三个信息容器
除此之外,该练习与本章中描述的工作类似。
关键要点
-
如何在顶部导航栏中放置一个搜索表单
-
你怎么能有一个粘性的侧边导航栏
-
如何在小型设备上隐藏部分页面
-
如何创建圆形图像
-
如何对齐内容并制作管理仪表板
-
如何创建响应表
-
许多其他的细节和技术来调整你的页面布局
在下一章中,你将使用 Twitter Bootstrap 构建令人惊叹的表单。
八、表单
您已经学习了 HTML 表单和每个表单控件。Twitter Bootstrap 以类的形式给了你一些额外的工具,这将允许你非常容易地设计你的表单。
你将能够构建一个如图 8-1 所示的基本表单

图 8-1
登录表单示例
或类似图 8-2 中的表单。

图 8-2
注册表单示例
您还可以非常直观地显示哪些字段已经成功填写,哪些字段没有填写(图 8-3 )。

图 8-3
有错误的注册表单
学习目标
-
了解如何实现 Twitter Bootstrap 基本表单。
-
了解 Twitter 引导水平表单。
-
了解水平表单如何使用网格类将标签和输入控件布置到不同的列,但在同一行上。
-
了解 Twitter Bootstrap 内嵌表单。
-
了解如何在输入控件下显示帮助文本。
-
了解只读控件。
-
了解如何使用 Twitter Bootstrap 显示选择框。
-
了解验证。
-
了解如何更改输入控件的大小。
-
了解如何将两个控件组合在一起并创建一个输入组。
介绍
Twitter Bootstrap 提供了一系列影响表单和表单控件样式的类。在这一章中,你将设计一个 Twitter Bootstrap 表单参考页面,其中你将展示 Twitter Bootstrap 为你提供的关于这个主题的所有主要工具。
我们开始吧。
空的 Twitter 引导页面
您将从标准的空 Twitter 引导页面开始(清单 8-1 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Twitter Bootstrap Forms Reference Page</title>
<link rel="stylesheet" href="stylesheets/main.css">
</head>
<body>
<div id="main-container" class="container">
<!-- Content will be inserted here -->
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 8-1Empty Bootstrap Page
将前面的 HTML 内容保存在index.html文件中。另外,准备一个空的stylesheets/main.css文件来存储你的 CSS 规则。如果您保存这些文件并在浏览器上加载页面,您将看不到任何内容,因为正文不包含任何内容。
目的是将页面的全部内容添加到一个container div中。这就是为什么你能在身体内部看到带有container类的div。
基本表单
您将从基本的 Twitter 引导表单开始。在main-container元素中添加以下内容(清单 8-2 )。
<div class="row">
<div class="col-12 col-lg-6">
<h3>Sign In</h3>
<p>Sign in today for better experience.</p>
<form>
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" placeholder="Enter email" class="form-control">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" placeholder="Password" class="form-control">
</div>
<div class="d-flex justify-content-between align-items-center">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="remember-me-checkbox">
<label class="form-check-label" for="remember-me-checkbox">Remember Me</label>
</div>
<button class="btn btn-sm btn-primary" type="submit">
<strong>Log in</strong>
</button>
</div>
</form>
</div> <!-- left column -->
<div class="col-12 col-lg-6">
</div> <!-- right column -->
</div> <!-- row inside main container -->
Listing 8-2Basic Form
正如您在前面的代码中所看到的,您将首先创建一个两列布局。右栏暂时是空的。左栏包含一个标题h3和一个小段落p。但是这里重要的东西是form元素。
这是一个简单的form元素,没有附加任何类。这是 Twitter Bootstrap 提供的基本表单样式。
这里需要指出的是:
-
标签和输入在
div中组合在一起。每个div都有一个form-group类。但是,与复选框相关的div有一个例外。它没有这个类。稍后我会解释原因。 -
每个输入控件都有类
form-control,除了checkbox输入,它有类form-check-input。 -
使用与 flexbox 相关的类
justify-content-between和align-items-center将复选框和登录按钮放在同一行。更多的解释将在下面提供。 -
类别
form-check用在包含复选框的div上。 -
类别
form-check-label用在复选框的标签上。
否则,前面代码中的任何其他内容都非常简单,不使用任何新内容。
如果您保存前面的代码并在浏览器上加载页面,您将看到以下内容(图 8-4 )。

图 8-4
在表单中签名
如您所见,在标准表单上增加一点 HTML,您会得到很多东西。查看输入获得焦点时是如何突出显示的。看看使用 flexbox 实用程序类左右移动东西是多么容易(图 8-5 )。

图 8-5。
当输入获得焦点时突出显示
现在,我将对您在前面的代码片段中使用的一些类进行更多的解释:
-
这个类
form-group做一些非常简单的事情。它增加了值1rem的底部边距。因此,如果您有一个垂直表单,就像示例中那样,输入和它们的标签在垂直方向上流动,这是很有用的。 -
类
form-check已经用于与复选框相关的输入和标签。这个类应用的最重要的规则是值1.25rem的左填充。这使得复选框在垂直方向上与表单的其他元素很好地左对齐。如果你愿意,你也可以应用form-group类,特别是当其他控件跟在你的第一个复选框下面的时候。 -
类
form-control对于附加到input元素非常重要。它负责宽度、高度、颜色、背景色、边框和其他样式属性。 -
然而,不要将这个类(
form-control)用于类型checkbox的输入。这些是完全不同的视觉方式。他们需要被赋予自己特别设计的名为form-check-input的职业。这个类将位置absolute赋予复选框输入,没有具体的坐标。因此,它是相对于其最近的定位的 1 祖先绘制的。因为您将输入放在一个带有类form-check的div中,所以它是相对于那个div绝对定位的。 -
Labels除了伴随checkbox输入的标签,不要选择任何特殊的类。这就需要有阶级form-check-label。它消除了底部空白。这使它更好地与实际输入保持一致。 -
附加在包含复选框和登录按钮的
div上的类d-flex将div转化为 flexbox 容器。这意味着它在行方向上布局其元素。如果您临时移除它,您将看到登录按钮出现在复选框输入的下方。 -
类
justify-content-between获取 flexboxdiv的两个子元素,并在行方向上对齐它们,以便它们之间有空白空间。因此,一个子对象左对齐,另一个子对象右对齐。 -
类
align-items-center对齐 flexdiv的子对象,但是在非主轴方向。默认主轴是行(x, horizontal)。因此,align-items-*类在列(y, vertical)轴方向对齐子元素。这个特别的把它们排列在中间。
水平表单
以前的表单有一行是标签,在标签下面有一行是输入控件。在这里,您可以选择实现一个水平表单。该表单的标签和输入控件在同一行,占据相邻的列。HTML 标记更加复杂,并且使用与网格相关的类。让我们看看怎么做。
在右栏div(列表 8-3 )中增加以下内容。
<div class="col-12 col-lg-6">
<h3>Sign In</h3>
<p>Sign in today for better experience.</p>
<form>
<div class="form-group row">
<label class="col-lg-2 col-form-label" for="email2">Email</label>
<div class="col-lg-10">
<input type="email" placeholder="Email" class="form-control" id="email2">
<small class="form-text text-muted">Example block-level help text here.</small>
</div>
</div>
<div class="form-group row">
<label class="col-lg-2 col-form-label" for="password2">Password</label>
<div class="col-lg-10">
<input type="password" placeholder="Password" class="form-control" id="password2">
</div>
</div>
<div class="form-group row justify-content-end">
<div class="col-lg-10">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="remember-me-checkbox-2">
<label class="form-check-label" for="remember-me-checkbox-2">Remember Me</label>
</div>
</div>
</div>
<div class="form-group row justify-content-end">
<div class="col-lg-10">
<button class="btn btn-sm btn-secondary" type="submit">Sign in</button>
</div>
</div>
</form>
</div> <!-- right column -->
Listing 8-3Right Column div with Horizontal Form
在我解释清单 8-3 的 HTML 标记之前,让我们保存 HTML 页面并将其加载到您的浏览器上。您应该看到以下内容(图 8-6 )。

图 8-6
右列上的水平窗体
如图 8-6 所示,水平表单将每一行分成两列,一列用于标签,一列用于输入控件本身。以下是您需要从代码中了解的内容:
-
每个表单组(
div和类form-group)现在都有一个额外的类row。这将允许我们使用 Bootstrap 的网格特性来布置每个组中的孩子。 -
电子邮件和密码这两个标签占据了两列的宽度。这就是为什么他们有
col-lg-2。注意,它们还需要有 c 类ol-form-label。这个类是专门设计来垂直对齐标签的。 -
电子邮件和密码这两个输入被打包到一个带有类
col-lg-10的div中,这使得它们占据了剩余的可用水平空间。 -
包含复选框的行占据 10 的列宽,右对齐。这是在类
justify-content-end和类col-lg-10的帮助下发生的,类justify-content-end使div的子元素位于 flex 容器的右侧,类div使div占据了十列。 -
最后,请注意我们如何在电子邮件输入下方创建帮助文本。这是通过一个拥有类
form-text和text-muted的small元素来完成的。
内嵌表单
有些情况下,您只有一行来显示表单的所有输入控件。下面是这种表单的一个例子(图 8-7 )。

图 8-7
内嵌表单示例
您将在这两个表单下面创建这样一个表单。使用清单 8-4 ,并将其添加为 id 为#main-container的div的最后一个子节点。
<div id="inline-form-container">
<hr class="m-4">
<form class="form-inline">
<div class="form-group mr-sm-2">
<label for="email3" class="mr-sm-2">Email address</label>
<input type="email" placeholder="Enter email" id="email3" class="form-control">
</div>
<div class="form-group mr-sm-2">
<label for="password3" class="mr-sm-2">Password</label>
<input type="password" placeholder="Password" id="password3" class="form-control">
</div>
<div class="form-check mr-sm-2">
<input type="checkbox" id="checkbox1" class="form-check-input">
<label for="checkbox1" class="form-check-label">
Remember me
</label>
</div>
<button class="btn btn-primary" type="submit">Sign in</button>
</form>
</div>
Listing 8-4Inline Form HTML Fragment
如果您保存前面的代码并在浏览器上重新加载页面,您将看到以下内容(图 8-8 )。

图 8-8
底部的自举内嵌表单
form标签需要有类form-inline。这就完全不同了。否则,除了您已经知道的类之外,不会添加任何与表单相关的类。你只使用了一些保证金实用程序类,如类mr-sm-2。这些类所做的唯一事情就是添加一些边距,以使表单的元素周围有一些自由空间。
帮助文本
很多时候,输入控件需要用户输入一条不常见的信息。用户界面需要确保用户理解他们必须输入的内容。标签有帮助。占位符也有帮助。但是有时候,为了提供更详细的解释,需要额外的帮助。在这种情况下,您可能想要使用名为Help Text的工具。
帮助文本通常出现在输入控件的下方;它是一个短语,向用户解释他们必须键入的内容。
让我们将下面这段 HTML 代码作为最后的元素添加到主容器 div 中(清单 8-5 )。
<h3 class="mt-4">Other Form Elements</h3>
<hr class="my-4">
<form>
<div>
<em>Help Text</em>
<hr class="my-3">
</div>
<div class="form-group row">
<label for="help-text" class="col-lg-2 col-form-label">VAT number</label>
<div class="col-lg-10">
<input type="text" class="form-control" id="help-text" placeholder="Key in your VAT number"/>
<small class="form-text text-muted">Give your company VAT number. Enter the VIES VAT number with the two char prefix indicating your country.</small>
</div>
</div>
</form>
Listing 8-5Page with Help Text
以下是对上述 HTML 片段的解释:
-
您添加了一个标题为
Other Form Elements的页眉。这基本上是通过一个带有顶部边距的h3元素(类mt-4)和一个带有垂直边距的hr元素(类my-4)来完成的。 -
您正在页面上引入一个新表单。这将是一个水平的表单,将用于封闭一系列的表单元素,我想跟你谈谈。
-
从
Help Text开始。这是用一个简单的small元素实现的,该元素有form-text和text-muted类。它正好位于它所伴随的输入控件之后。除此之外,前面这段代码没有什么特别之处。
如果您保存前面的代码并在浏览器上加载页面,您将看到以下内容(图 8-9 )。

图 8-9
页面的其他表单元素部分的开始
只读纯文本
纯文本输入控件用于表示标签旁边的只读信息。让我们添加下面的 HTML 片段作为最后一个表单的一部分(清单 8-6 )。
<div>
<em>Readonly Plain Text</em>
<hr class="my-3">
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="readonly-email">Email:</label>
<div class="col-sm-10">
<input type="text" readonly class="form-control-plaintext" id="readonly-email" value="foo@bar.com">
</div>
</div>
Listing 8-6Input Control as Read-Only Plain Text
如果保存前面的代码并在浏览器上加载页面,您将看到图 8-10 。

图 8-10
作为只读纯文本的输入控件
你看到了吗?值为 foo@bar.com 的电子邮件输入被设计成不同于普通的输入控件。这是在类form-control-plaintext的帮助下完成的。否则,所有剩下的 HTML 标记都是您所知道的。
选择框
选择框和 Twitter Bootstrap 没有什么特别的。您唯一要做的事情就是将类form-control附加到select元素上。让我们添加下面的 HTML 代码作为最后一个表单的一部分(清单 8-7 )。
<div>
<em>Select Boxes</em>
<hr class="my-3">
</div>
<div class="form-group row">
<label class="col-lg-2 col-form-label" for="select-1">Single</label>
<div class="col-lg-10">
<select class="form-control" name="account" id="select-1">
<option>option 1</option>
<option>option 2</option>
<option>option 3</option>
<option>option 4</option>
</select>
</div>
</div>
<div class="form-group row flex-justify-end">
<label class="col-lg-2 col-form-label" for="select-2">Multiple</label>
<div class="col-lg-10">
<select class="form-control" multiple="multiple" id="select-2">
<option>option 1</option>
<option>option 2</option>
<option>option 3</option>
<option>option 4</option>
</select>
</div>
</div>
Listing 8-7Single and Multiple Select Box
这很简单。除了select元素附加了类form-control之外,这里没有什么新的东西。如果您保存页面并在浏览器上重新加载,您将看到以下内容(图 8-11 )。

图 8-11
带有选择框的页面部件
类form-control设计选择框的样式,类似于其他输入控件用这个类得到的样式。
输入验证
很多时候,人们希望突出显示用户已经给出错误输入的输入控件。或者可能想要突出显示具有正确输入的那些。一种方法是对输入控件进行相应的着色,例如,用红色表示错误的输入。
Twitter Bootstrap 提供了一组专门用来处理这个问题的类。这些类别是
-
is-valid -
is-invalid -
valid-feedback -
invalid-feedback
您将类is-valid或is-invalid分别附加到您想要样式化为有效或无效的input上。
您将valid-feedback和invalid-feedback类附加到一个保存反馈消息的div上,分别用于有效和无效的情况。这个div需要存在于 input 元素的正下方,作为第一个直接兄弟。
让我们在您正在处理的表单的末尾添加以下 HTML 代码(清单 8-8 )。
<div>
<em>Input Validation</em>
<hr class="my-4">
</div>
<div class="form-group row">
<label class="col-lg-2 col-form-label" for="valid-input">Email</label>
<div class="col-lg-10">
<input type="email" class="form-control is-valid" id="valid-input" placeholder="Your username" value="foo@bar.com" required/>
<div class="valid-feedback">
Nice!
</div>
</div>
</div>
<div class="form-group row">
<label class="col-lg-2 col-form-label" for="invalid-input">Password</label>
<div class="col-lg-10">
<input type="password" class="form-control is-invalid" id="invalid-input" placeholder="Your password" required>
<div class="invalid-feedback">
You have to give your password
</div>
</div>
</div>
Listing 8-8Input Validation
如果您保存前面的代码并在浏览器上加载页面,您将看到以下内容(图 8-12 )。

图 8-12
输入验证
您看到有效和无效输入是如何设计的了吗?在一小部分类的帮助下,Bootstrap 允许你在样式上做惊人的工作。
输入控件的大小
Twitter Bootstrap 提供了一些非常方便的与输入控件大小相关的类。您可以使用大型控件,将类form-control-lg附加到输入控件。或者你可以使用小控件,用类form-control-sm代替。让我们在表单的末尾添加下面这段 HTML 代码(清单 8-9 )。
<div>
<em>Size of Input Controls</em>
<hr class="my-4">
</div>
<div class="form-group row">
<label class="col-lg-2 col-form-label" for="large-size-input">Large</label>
<div class="col-lg-10">
<input type="text" class="form-control form-control-lg" id="large-size-input"/>
</div>
</div>
<div class="form-group row">
<label class="col-lg-2 col-form-label" for="default-size-input">Default</label>
<div class="col-lg-10">
<input type="text" class="form-control" id="default-size-input"/>
</div>
</div>
<div class="form-group row">
<label class="col-lg-2 col-form-label" for="small-size-input">Small</label>
<div class="col-lg-10">
<input type="text" class="form-control form-control-sm" id="small-size-input"/>
</div>
</div>
Listing 8-9Different Input Control Sizes
如果您保存此文件并在浏览器上重新加载页面,您将看到以下内容(图 8-13 )。

图 8-13
不同的输入控件大小
如果你尝试添加一些输入,尺寸的差异会变得更加明显(图 8-14 )。

图 8-14
某些输入的不同输入控件大小
输入组
有时候你想制造出如下效果(图 8-15 )。

图 8-15
输入组示例
这是一个输入组示例。其他示例如下两个(图 8-16 和图 8-17 )。

图 8-17
美元和小数输入组示例

图 8-16
小数输入组示例
这里有一个小标签和一个文本输入控件的组合(图 8-18 )。

图 8-18
标签和输入控件组合在一起
将这两个(在第三个例子中是三个)控件组合成一个称为输入分组。
让我们在您的表单中添加以下代码(清单 8-10 )。
<div>
<em>Input Groups</em>
<hr class="my-4">
</div>
<div class="row justify-content-end" id="input-groups-container">
<div class="col-lg-10">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">@</span>
</div>
<input type="text" placeholder="Username" class="form-control"/>
</div>
<div class="input-group">
<input type="text" class="form-control"/>
<div class="input-group-append">
<span class="input-group-text">.00</span>
</div>
</div>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">$</span>
</div>
<input type="text" class="form-control">
<div class="input-group-append">
<span class="input-group-text">.00</span>
</div>
</div>
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text">
<input type="checkbox">
</div>
</div>
<input type="text" class="form-control">
</div>
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text">
<input type="radio">
</div>
</div>
<input type="text" class="form-control">
</div>
</div>
</div>
Listing 8-10Examples of Input Groups
另外,在stylesheets/main.css文件中添加以下 CSS 规则:
#input-groups-container .input-group {
margin-bottom: 1.2rem;
}
保存前面的所有代码,并在浏览器上重新加载页面。您将看到以下内容(图 8-19 )。

图 8-19
输入组
让我们看看 HTML 代码中的输入组是由什么组成的。我分析第一个输入组,它是:
-
input-group需要是一个带有类input-group的div。 -
div需要包含input元素。在我们的例子中,这是用户输入用户名的地方。 -
视觉装饰在实际
input之前。因此,input需要在前面加上一个具有类input-group-prepend的div。 -
这个
div,带input-group-prepend的,需要有一个带input-group-text的span里面的装饰。
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">@</span>
</div>
<input type="text" placeholder="Username" class="form-control"/>
</div>
非常容易!
那么你需要注意以下几点:
-
如果视觉装饰需要放在
input元素之后,那么它的div类需要写在input元素之后,它的类需要是input-group-append(而不是input-group-prepend)。 -
你可以有两个视觉装饰——一个在主
input控件之前,一个在主input控件之后。您只需在主input控件之前使用一个带有类input-group-prepend的div,在它之后使用另一个带有类input-group-append的div。 -
对组的 prepend 或 append 部分中的复选框和单选按钮进行特殊设置。它们不应该被包裹在一个
span里,而应该被包裹在一个div里。
前面分组的另一个变化是一个input控件和一个按钮的分组。在表单的末尾添加以下 HTML 代码(清单 8-11 )。
<div>
<em>Input & Button Groups</em>
<hr class="my-4">
</div>
<div class="row justify-content-end">
<div class="col-lg-10">
<div class="input-group">
<input type="text" class="form-control"/>
<div class="input-group-append">
<button type="button" class="btn btn-primary">Go!</button>
</div>
</div>
</div>
</div>
Listing 8-11Input Group with a Button
如果您保存前面的代码并在浏览器上重新加载页面,您将看到以下内容(图 8-20 )。

图 8-20
输入和按钮组
正如您在 HTML 代码中看到的,实现与前面的情况非常相似。唯一的区别是,你没有用类input-group-text将button包装在任何span或div中。您将button作为带有类input-group-prepend(或input-group-append)的div的直接且唯一的子元素。
任务和测验
TASK DETAILS

图 8-21
任务:登录表单
-
你需要创建一个 Twitter 引导页面,上面有三个表单。
-
第一个表单需要是如下表单中的一个标志(图 8-21 )。

图 8-22
任务:注册表单
-
在您的项目中导入/引用带有字体的 FontAwesome 库。FontAwesome 项目解释了如何做到这一点。
-
添加将表示图标的 HTML 片段。它可能是这样的:
<i class="fas fa-asterisk"></i> -
接下来需要第二个表单,即注册表单,如下所示(图 8-22 )。
-
这是一个基本的 Twitter 自举表单。您可能遇到的唯一困难是密码输入组中的符号。为了添加这些内容,您需要

图 8-23
任务:注册表单并进行验证
-
这里没有什么新东西。确保在密码和名称字段中使用正确的字体图标。
-
注意输入控件很大。
-
第三个表单与第二个表单相同,但是所有的输入字段都被标记为有效或无效。其实除了密码确认无效外都是有效的(图 8-23 )。
-
请注意,在第三个表单中,所有输入字段都填充了一个值。你必须这么做。提示:设置
inputHTML 元素的value属性。 -
此外,红色信息“它不匹配你的密码”是一个无效的反馈。这需要是一个
div元素,紧挨着它所伴随的输入控件,也就是密码确认输入控件。
关键要点
-
如何创造惊人的表单
-
如何水平和垂直布局表单输入
-
如何将标签和输入字段组合在一起并设计它们的样式
-
如何将输入与其他视觉装饰组合在一起
-
如何制作小型和大型输入控件
-
如何在输入控件下方显示帮助文本
-
如何显示验证成功和错误输入
-
如何给出验证反馈
-
如何设置只读输入控件的样式
在下一章中,我将介绍更多的动态页面。您将学习如何创建模态对话框。
九、模态对话框
在这一章中,您开始将 JavaScript 应用于 Twitter Bootstrap。您将看到 Bootstrap 如何提供非常有用的 JavaScript 库来帮助您尽可能轻松地向 web 应用程序添加动态行为。
你从模态开始,模态是试图吸引用户注意力的对话窗口,如图 9-1 所示。

图 9-1
模态对话框示例
然后我将解释如何将 Twitter Bootstrap JavaScript 库与您自己的 HTML 页面集成在一起。
您将了解模态 HTML 标记及其主要部分,以及如何使用图片创建令人印象深刻的模态,如下所示(图 9-2 )。

图 9-2
带图片的示例模型
最后,您学习了与模态相关的所有事件,并被要求构建一个处理相关事件的模态。您将构建一个如下所示的模型(图 9-3 )。

图 9-3
有两个城市可供选择
学习目标
-
学习情态动词。
-
了解如何引用 Twitter Bootstrap JavaScript 文件。
-
了解引入模态功能的最简单的 HTML 标记。
-
了解哪些 Twitter 引导类与模态功能有关。
-
了解 Twitter Bootstrap HTML 标记的主要部分。
-
了解如何使用数据属性来触发模式。
-
了解如何对按钮进行编程,使其在被单击时打开一个模态。
-
了解如何在模式的右上角有一个关闭按钮。
-
了解如何使用 FontAwesome 作为关闭按钮的图标。
-
了解如何在模态上显示图像。
-
了解如何在模型上显示 YouTube 视频。
-
了解如何在模态上显示其他/外部页面。
-
了解如何显示大模态和小模态。
-
了解如何在模型体内使用 Twitter Bootstrap 网格系统。
-
了解如何使用 JavaScript 激活模态。
-
了解如何通过使用 JavaScript 设置各种选项来自定义模态行为。
-
了解各种可用的模态方法。
-
了解可以挂接事件处理程序的各种模式事件。
介绍
情态动词是一种非常用户友好的向用户展示信息或要求提供信息的方式。模态是覆盖页面的窗口,不允许用户与页面的其他部分进行交互。换句话说,用户必须在返回主页之前关闭模态:
-
用户可以阅读信息,然后关闭模式。一个模态可以在右上角有一个
Close按钮或者一个[X]按钮来关闭它。 -
用户可以填写一些表单,然后单击表单的提交按钮。这通常会关闭模式并将用户返回到主页。
让我们来看一个实际的模态(图 9-4 )。

图 9-4
模态示例
Twitter Bootstrap 免费提供模态,作为 JavaScript 集成的一部分。让我们看看怎么做。
引导 JavaScript 文件
为了能够使用模态,您需要引用 Twitter 引导 JavaScript 文件。这些需要在 jQuery JavaScript 文件的后引用。
下面是一个引用 Twitter Bootstrap 和 jQuery 的最简单的 HTML 页面(清单 9-1 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<title>Modal Dialogs</title>
</head>
<body>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 9-1Empty Twitter Bootstrap Page with JavaScript
从前面的代码中可以看出,为了使用 Twitter Bootstrap JavaScript 库和组件,您必须加载三个外部文件。参见图 9-5 中装载它们的正确顺序。

图 9-5
加载外部 JavaScript 库的正确顺序
正如你在图 9-5 中看到的,我引用了 Twitter Bootstrap JavaScript 文件的 CDN 版本。我在 jQuery 和 Popper 文件之后加载它,因为 Twitter Bootstrap JavaScript 依赖于 jQuery 和 Popper。
请注意,如果您想要添加自定义的,也就是您自己的 JavaScript 文件,您必须将它们放在正确的位置。您自己的定制 JavaScript 文件需要放在第三方 JavaScript 文件之后,也就是 Twitter 引导 JavaScript 引用之后(图 9-6 )。

图 9-6
自定义 JavaScript 文件正确位置
模态标记
准备好最基本的 HTML 页面后,让我们在上面添加一些模态功能。将列表 9-2 的内容添加到页面的body中,作为body元素的第一个子元素。
<div class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">This is an h4 inside Modal Header</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<p>This is a paragraph inside Modal Body</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
Listing 9-2HTML Markup for a Modal
如果您在浏览器上保存并加载该页面,您将看到一个空白页。这是因为模态不应该被显示,除非用户选择这样做,或者他们执行了触发模态显示的动作。
使模态内容不可见的类是类modal和fade。modal加一个display:none;,fade加一个opacity: 0。
在下图中可以看到禁用这两个属性是如何让模态出现在页面上的(图 9-7 )。

图 9-7
禁用属性以显示模式
所有的模态都有相同的 HTML 标记。其主要零件如图 9-8 所示。

图 9-8
模态 HTML 标记的主要部分
-
在同一个嵌套级别中,有三个兄弟节点
div,它们都是具有类modal-content的 div 的子节点:-
类别为
modal-header的模态头的div -
A
div用于具有类别modal-body的模态体 -
一个
div用于带有类modal-footer的模态页脚
-
-
三个
div相互串联,它们包含了情态的实际内容:-
一个带有类
modal和fade的div -
一个
div在前一个modal fade在后一个modal-dialog -
一个
div在前一个modal-dialog在后一个modal-content
-
请注意,最后三个部分是可选的。同样,在它们里面,你可以放置(几乎)任何你喜欢的 HTML 标记。
触发模式
模态是隐藏的,直到用户采取行动显示它们,或者直到 web 应用程序决定必须显示它们。这种触发是如何发生的?
您将通过引入一个允许用户打开模式对话框的按钮来继续这个示例。让我们将 HTML 主体内容修改如下:
<button class="btn btn-lg btn-success" data-toggle="modal" data-target=".modal">Open Modal</button>
将前面的标记添加到模式开始标记div之前,开始标记<body>之下。
保存 HTML 页面并在浏览器上重新加载。您将看到以下内容(图 9-9 )。

图 9-9
带有打开模式按钮的页面
如果您点击按钮Open Modal,,您将看到以下内容(图 9-10 )。

图 9-10
单击按钮后显示的模式
完美!这就是模态。
让我们解释一下关于button标记的一些重要细节:
-
它具有值为
modal的属性data-toggle。这是必要的,以向 Bootstrap 表明这是一个按钮,单击它将打开一个模式对话框。 -
它有一个属性
data-target,该属性的值是一个 CSS 选择器,并且需要唯一地选择保存模式 HTML 标记的 HTML 元素。在您正在开发的模态中,您已经使用了值modal,因为这是唯一匹配保存您的模态标记的div的类。通常,在这里,您使用一个 CSS 选择器来表示一个 id,而不是一个类,以使标识唯一并避免歧义。
注意,通过这个小小的 HTML 标记和使用 Twitter Bootstrap 识别的数据属性,您已经成功地向页面添加了动态行为。您不必编写任何 JavaScript。所有这些模态 JavaScript 功能都由 Twitter Bootstrap JavaScript 库提供。
关于模态标记的更多信息
除了我之前谈到的标准 HTML 模态标记之外,上一个例子中还有一些其他元素值得你注意(图 9-11 )。
右上角的关闭[x]按钮

图 9-11
[x]按钮
用户可以单击右上角的[x]按钮来关闭模式对话框。它的标记被放在了modal-header div中,如下所示:
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
它是类close的button,数据属性data-dismiss等于modal,指示 Twitter Bootstrap 在被点击时关闭模态。出现在那里的真正图标是<span aria-hidden="true">×</span>。×实体元素是一个特殊字符,显示为十字[x]。
在button中,您可以使用任何适合的 HTML,它可以向用户指示关闭模态的能力。例如,你可以使用一个字体牛逼图标。让我们试着用其中的一个。将 HTML 标记<span aria-hidden="true">×</span>替换为
<i aria-hidden="true" class="fas fa-window-close"></i>.
此外,在页面底部,在引用 Bootstrap JavaScript 文件之前,添加一个对为您的帐户设计的 FontAwesome 特殊工具包的引用。应该是这样一行:
<script src="https://kit.fontawesome.com/<your-account-kid-id>.js" crossorigin="anonymous"></script>
保存,重新加载页面,并打开模式。您将看到以下内容(图 9-12 )。

图 9-12
FontAwesome 图标用作模式关闭按钮
Note
在 FontAwesome 上创建一个帐户非常简单。你访问页面 https://fontawesome.com ,然后注册。然后你需要创建一个工具包。该网站将指导您如何获取套件标识符,以便在您的 HTML 页面中引用/使用它。
底部的关闭[Close]按钮
modal-footer div里面有一个按钮,工作原理和右上角的那个一样。它关闭模式对话框。它的标记是
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
同样,重要的是它的数据属性data-dismiss等于modal,这使得它的功能相当于一个模态关闭按钮。
Note
Save changes是一个什么也不做的按钮。我没有给它附加任何功能。
添加图像
正如我前面说过的,您可以在模态中添加(几乎)任何 HTML 内容。让我们看看下面的 HTML 页面(清单 9-3 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Modal Dialogs</title>
</head>
<body>
<button class="btn btn-lg btn-success" data-toggle="modal" data-target=".modal">Open Modal</button>
<div class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Zakynthos - Shipwreck</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span>×</span>
</button>
</div>
<div class="modal-body">
<img src="img/zakynthos-shipwreck.jpg" alt="Zakynthos Shipwreck"/>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 9-3HTML for a Modal with Image
如果您阅读 HTML,您会看到modal-body div只包含一个img元素。
另外,请注意,有一个对名为stylesheets/main.css的外部定制样式表文件的引用。请在里面添加下面的 CSS 规则。它将在图像周围添加一个边框:
img {
border: 1px solid Darkblue;
}
如果您在浏览器上保存并加载该页面,您将看到以下内容(图 9-13 )。

图 9-13
具有 img 元素的模式—宽图像的问题
如你所见,图像有问题。它超越了模态的界限。为了解决这个问题,您必须将类img-fluid附加到img元素上。这样做并重新加载页面。您将看到以下内容(图 9-14 )。

图 9-14
图像在模态中正确显示
添加 YouTube 视频
就像您对图像所做的那样,您可以类似地添加一个 YouTube 嵌入式视频参考。尝试下面的 HTML(清单 9-4 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Modal Dialogs</title>
</head>
<body>
<button class="btn btn-lg btn-success" data-toggle="modal" data-target=".modal">Open Modal</button>
<div class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Zakynthos - Shipwreck</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span>×</span>
</button>
</div>
<div class="modal-body">
<iframe width="100%" height="315" src="https://www.youtube.com/embed/tqy0Uvw_bFU" frameborder="0" allowfullscreen></iframe>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 9-4Embedding a YouTube Video
正如您在前面的代码中看到的,您可以使用iframe元素嵌入 YouTube 视频。确保width设置为 100%,并且height设置为合理的高度,这将保持您的视频以正确的纵横比显示。请注意,当您选择通过嵌入分享视频时,YouTube 会为您提供iframe元素的代码。您只需要调整宽度和高度属性,这样视频就可以很好地显示在您的模态中。
如果您保存前面的 HTML 并在浏览器上加载页面,您将看到以下内容(图 9-15 )。

图 9-15
有 YouTube 视频的模特
可选尺寸
Twitter Bootstrap 为您的模特提供三种可选尺寸:
-
超大模态:您需要在
modal-dialog类后面追加modal-xl类。它基本上将模态max-width设置为1140px。 -
大型模态:您需要在
modal-dialog类后面追加modal-lg类。它将max-width设置为800px。 -
小模态:您需要在
modal-dialog类后面追加modal-sm类。它将max-width设置为300px。
如果您没有指定任何前面的大小等级,那么默认设置为max-width到500px。
下一个是大尺寸的模态演示(清单 9-5 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Modal Dialogs</title>
</head>
<body>
<button class="btn btn-lg btn-success" data-toggle="modal" data-target=".modal">Open Modal</button>
<div class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Zakynthos from Wikipedia</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span>×</span>
</button>
</div>
<div class="modal-body">
<iframe width="100%" height="400" src="https://en.wikipedia.org/wiki/Zakynthos" id="frame-in-modal"></iframe>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 9-5Large Modal Demo
如果您保存该页面的文件并将其加载到您的浏览器上,您将看到以下内容(图 9-16 )。

图 9-16
大型模态演示
移除动画
如果你已经注意到,当你打开模态的时候,它从上到下的动画。您可以通过从顶层div容器中移除类fade来移除这个动画,并使模态立即出现。
试着从前面的例子中移除fade类。您将在动画中看到没有顶部淡入淡出的模态。
使用 Twitter 引导网格系统
您可以在 modal 的主体中使用 Twitter Bootstrap 网格系统。在modal-body div容器中适当地使用container-fluid,然后使用row和column-xx-x类。
我们来看一个例子(清单 9-6 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Modal Dialogs</title>
</head>
<body>
<button class="btn btn-lg btn-success" data-toggle="modal" data-target=".modal">Open Modal</button>
<div class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Zakynthos from Wikipedia</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span>×</span>
</button>
</div>
<div class="modal-body">
<div class="container-fluid">
<div class="row">
<div class="col-md-6">
<img src="img/ithaki-1.jpg" alt="Ithaki"/>
</div>
<div class="col-md-6">
<img src="img/elafonisos-2.jpg" alt="Elafonisos"/>
</div>
</div>
<div class="row">
<div class="col-md-6">
<img src="img/karpathos-3.jpg" alt="Karpathos"/>
</div>
<div class="col-md-6">
<img src="img/chios-4.jpg" alt="Chios"/>
</div>
</div>
</div>
</div> <!-- modal body -->
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 9-6Grid System Inside the Modal Body
这是 CSS:
img {
padding: 10px 10px;
width: 100%;
height: 250px;
}
如果您保存前面的代码并在浏览器上加载页面,当您打开模式时,您将看到以下内容(图 9-17 )。

图 9-17
模体内部使用的网格系统
垂直居中
模式的默认行为是出现在页面的顶部。如果你想让模态出现在中间,也就是垂直对齐,那么你就得在modal-dialog类旁边附加modal-dialog-centered类。
清单 9-7 展示了这一点。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<title>Modal Dialogs</title>
</head>
<body>
<button class="btn btn-lg btn-success" data-toggle="modal" data-target=".modal">Open Modal</button>
<div class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">This is an h4 inside Modal Header</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<p>This is a paragraph inside Modal Body</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
Listing 9-7Modal Vertically Centered
如果您保存此页面,将其加载到您的浏览器上,并打开模式,您将看到以下内容(图 9-18 )。

图 9-18
模态垂直居中
如您所见,模态出现在垂直居中位置。
用 JavaScript 激活模态
您已经看到,您可以在不使用任何 JavaScript 代码的情况下激活一个模态。您使用的按钮示例如下所示:
<button class="btn btn-lg btn-success" data-toggle="modal" data-target=".modal">Open Modal</button>
这里重要的位是data-toggle="modal"和data-target=".modal"。
你也可以用 JavaScript 打开一个模态对话框。让我们再次看看(清单 9-8 )希腊群岛的例子,但是这一次,您将不会像上一个例子那样使用按钮。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Modal Dialogs</title>
</head>
<body>
<button class="btn btn-lg btn-success" id="open-modal-button">Open Modal</button>
<div class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Zakynthos from Wikipedia</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span>×</span>
</button>
</div>
<div class="modal-body">
<div class="container-fluid">
<div class="row">
<div class="col-md-6">
<img src="img/ithaki-1.jpg" alt="Ithaki"/>
</div>
<div class="col-md-6">
<img src="img/elafonisos-2.jpg" alt="Elafonisos"/>
</div>
</div>
<div class="row">
<div class="col-md-6">
<img src="img/karpathos-3.jpg" alt="Karpathos"/>
</div>
<div class="col-md-6">
<img src="img/chios-4.jpg" alt="Chios"/>
</div>
</div>
</div>
</div> <!-- modal body -->
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<!-- Custom JavaScript -->
<script src="javascripts/open-dialog.js"></script>
</body>
</html>
Listing 9-8Greek Islands with JavaScript to Open the Modal
前面的文件与以前的版本有两个不同之处:
-
它引用一个带有自定义 JavaScript 代码的 JavaScript 文件。文件是
javascripts/open-dialog.js。参见文件底部的引用,在结束的body标签之前。 -
另一个是打开模态的按钮不再具有模态相关的
data-属性。
在没有给出open-dialog.js内容的情况下,如果您保存前面的代码,在浏览器上加载页面,并尝试通过单击按钮打开对话框,什么都不会发生。
为了打开对话框,您现在需要提供相应的 JavaScript 命令:
$(document).ready(function() {
$('#open-modal-button').on('click', function() {
$('.modal').modal();
return false;
});
});
如果您将前面的代码保存在javascripts/open-dialog.js文件中并重新加载页面,那么当您单击Open Modal按钮时,模式对话框将会打开。
这里的新东西是:
$('.modal').modal();
它在按钮#open-modal-button的 click 处理程序的实现中。所以,当你点击这个按钮时,你调用了 Twitter Bootstrap JavaScript 库的modal()方法。这在选择与$('.modal');匹配的元素时调用,因此在模态div容器上调用。
模式和选项
当调用$(...).modal()方法时,你可以给一个 JavaScript 对象提供模态函数的选项。您可以提供的选项如下:

图 9-19
无背景模式
backdrop:布尔值,默认值为true。它也可以是值为static的字符串。如果您将该值设置为false,那么模态将在没有背景的情况下打开,并且您将无法在模态之外点击来关闭它(图 9-19 )。
打开无背景模式的代码如下:
$(document).ready(function() {
$('#open-modal-button').on('click', function() {
$('.modal').modal({
backdrop: false
});
return false;
});
});
如果你将backdrop的值设置为static,,那么它将打开带有背景的模态,但是你不能通过点击模态区域之外来关闭模态。
如果您将backdrop设置为true,那么它将打开带有背景的模态,您可以通过在模态区域外单击来关闭模态。
-
keyboard:布尔值,默认值为true。当true,时,点击<ESC>键关闭模态。 -
show:布尔值,默认值为true。它显示了初始化时的模态。这是很有用的,因为你可能想要初始化一个模态,而不真正显示它,直到后来。将javascripts/open-dialog.js中的 JavaScript 代码修改如下(清单 9-9 )。
$(document).ready(function() {
$('.modal').modal({
backdrop: 'static',
keyboard: false,
show: false
});
$('#open-modal-button').on('click', function() {
$('.modal').modal('show');
return false;
});
});
Listing 9-9Initialize Modal Without Opening
这和原版差别不大。但是它更好,因为它将功能一分为二。首先,它初始化模态;然后,当按钮被点击时,它就显示出来。
用modal({....});初始化模态和用调用modal('show');显示已经初始化的模态都属于模态方法的范畴。让我们看看更多关于他们的细节。
模态方法
下面是模态方法的列表:
.modal('show');
$('modal-selector').modal('show');
它用于显示一个初始化的模态。
.modal('hide');
$('modal-selector').modal('hide');
它用于隐藏已初始化的模态。
.modal('toggle');
$('modal-selector').modal('toggle');
它用于隐藏打开的模态或显示隐藏的模态。
模态事件
你可能已经知道 JavaScript 编程涉及到很多事件编程。很多 JavaScript 插件都定义了它们的自定义事件。Twitter Bootstrap 模型也是如此。
以下是针对模型本身触发的事件:
-
show.bs.modal:当调用show方法时,该事件立即触发。如果由点击引起,被点击的元素可作为事件的relatedTarget属性。我们来做一个例子(列表 9-10 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Modal Dialogs</title>
</head>
<body>
<button class="btn btn-lg btn-success" data-toggle="modal" data-target=".modal">Open Modal 1</button>
<button class="btn btn-lg btn-success" data-toggle="modal" data-target=".modal">Open Modal 2</button>
<button class="btn btn-lg btn-success" data-toggle="modal" data-target=".modal">Open Modal 3</button>
<div class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Modal Demo of relatedTarget</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true" class="glyphicon glyphicon-remove"></span></button>
</div>
<div class="modal-body text-center">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<!-- Custom JavaScript -->
<script src="javascripts/related-target.js"></script>
</body>
</html>
Listing 9-10Demo of the show.bs.modal Event
前面的 HTML 页面正在使用 JavaScript 文件javascripts/related-target.js。这在清单 9-11 中给出。
$(document).ready(function(){
$('.modal').on('show.bs.modal', function(event){
var $buttonClicked = $(event.relatedTarget);
$(this).find('.modal-body').html("<h1>" + $buttonClicked.html() + " Clicked!</h1>");
});
});
Listing 9-11JavaScript File for Listing 9-10
从 HTML 标记中可以看出,模式对话框的modal-body是空的。您将使用 JavaScript 动态添加内容,对show.bs.modal事件做出反应。此外,您将添加的内容将与触发模式打开的按钮相关。如您所见,有三个按钮都可以打开模式对话框。
关于 JavaScript 文件内容,我在模态(.modal)目标的show.bs.modal事件上附加了一个处理程序。我还声明了参数event,当处理程序被调用时,它将持有relatedTarget。我将relatedTarget保存到$buttonClicked,,然后使用。html() jQuery 函数设置modal-body div的 html 内容。使用 jQuery 方法选择modal-body div。find() 。
这将是下面三幅图中描绘的最终结果,图 9-20 ,图 9-21 ,图 9-22 :

图 9-22
点击Third按钮时的页面模式

图 9-21
点击Second按钮时的页面模式

图 9-20
单击第一个按钮时的页面模式
-
shown.bs.modal:当模态对用户可见,并且所有的fade转换完成后,这个事件被触发。如果由点击引起,被点击的元素可作为事件的relatedTarget属性。 -
hide.bs.modal:当hide实例方法被调用时,该事件立即被触发。当您想要编写一些需要在模态被隐藏时执行的动作时,这可能是有用的。 -
hidden.bs.modal:当模式对用户隐藏完成时,触发该事件(将等待 CSS 转换完成)。 -
hidden.Prevented.bs.modal:此事件在以下情况下触发-
显示了模态。
-
其背景是
static。 -
在模态外点击或点击
<ESC>键。
-
任务和测验
Task Details
您需要实现一个页面,让用户选择两个最喜欢的城市之一。实际上
-
用户应该能够点击其中一个图像。单击时,模式应该关闭,所选图像应该显示在主页上占位符的位置。
-
以下是一些帮助你完成任务的提示:
-
你可能想要一个自定义的 CSS 文件。这将需要样式内的模态图像,以及主页上的中心图像。
-
您将需要一个定制的 JavaScript 文件:
-
它的职责是响应在模态对话框中的两个图像中的任何一个上执行的点击。
-
图像上的点击处理器需要
-
关闭模态。
-
用点击图像的
src属性替换中心图像的src。
-
-
-
-
When the user clicks the button to open the modal, the modal should appear as follows (Figure 9-24):
![img/497763_1_En_9_Fig24_HTML.jpg]()
图 9-24
任务-有城市可供选择的模式
-
When the page loads, it has the button to open the modal and an image placeholder, like this (Figure 9-23):
![img/497763_1_En_9_Fig23_HTML.jpg]()
图 9-23
任务—带有打开模式按钮和图像占位符的页面
关键要点
-
如何实现模式对话框
-
模式对话框部分,页眉、正文和页脚
-
模特的背景
-
如何垂直居中模式
-
如何在模体内部使用网格系统
-
如何去除打开时的渐变效果
-
如何显示模态体内部的图像
-
如何在 modal 的主体中显示 YouTube 视频
-
如何打开小模态和大模态
-
如何使用其选项自定义模式
-
如何使用模态的方法
-
如何附加到不同的模态事件
在下一章中,你将学习如何创建一个有很长内容的页面,旁边有一个导航栏,它的活动菜单根据内容在窗口中的位置而变化。
十、ScrollSpy(滚动新闻)
长内容页面通常有顶部导航栏,允许用户快速导航到页面中的各个部分。这个特性伴随着这样一个事实,即突出显示为活动的菜单项根据页面的可见部分自动更新/改变。ScrollSpy 是一个 Twitter Bootstrap JavaScript 插件,在使用时,它会根据文档中的位置自动改变高亮显示的菜单项。
在这一章中,你将学习 Twitter Bootstrap 如何让你在你的长内容页面中快速加入这样一个特性。
学习目标
-
了解如何向长内容页面添加 scrollspying 功能。
-
了解应该如何设置 HTML 标记来支持 scrollspying。
-
了解如何调整滚动部分的偏移量和激活点。
有菜单的长页
让我们从一个带菜单的长 HTML 页面开始(清单 10-1 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>ScrollSpy</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand" href="main.html">Home</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar"
aria-controls="navbar"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="#introduction">Introduction<span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#origins">Origins</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#creating-new-state-constitutions">State Constitutions</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#military-hostilities-begin">Military Hostilities</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#independence-and-union">Independence And Union</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#more">More</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<h1 id="introduction">American Revolution History</h1>
<h2>Introduction</h2>
<p>
The American Revolution was a political upheaval that took place between 1765 and 1783 during which colonists in the Thirteen American Colonies rejected the British monarchy and aristocracy, overthrew the authority of Great Britain, and founded the United States of America.
</p>
<p>
Starting in 1765, members of American colonial society rejected the authority of the British Parliament to tax them and create other laws affecting them, without colonial representatives in the government. During the following decade, protests by colonists—known as Patriots—continued to escalate, as in the Boston Tea Party in 1773 during which patriots destroyed a consignment of taxed tea from the Parliament-controlled and favored East India Company.[1] The British responded by imposing punitive laws—the Coercive Acts—on Massachusetts in 1774, following which Patriots in the other colonies rallied behind Massachusetts. In late 1774 the Patriots set up their own alternative government to better coordinate their resistance efforts against Great Britain, while other colonists, known as Loyalists, preferred to remain aligned to the British Crown.
</p>
<p>
Tensions escalated to the outbreak of fighting between Patriot militia and British regulars at Lexington and Concord in April 1775\. The conflict then evolved into a global war, during which the Patriots (and later their French, Spanish, and Dutch allies) fought the British and Loyalists in what became known as the American Revolutionary War (1775–1783). Patriots in each of the thirteen colonies formed Provincial Congresses that assumed power from the old colonial governments and suppressed Loyalism, and from there built a Continental Army under the leadership of General George Washington. Claiming King George III's rule to be tyrannical and infringing the colonists' "rights as Englishmen", the Continental Congress declared the colonies free and independent states in July 1776\. The Patriot leadership professed the political philosophies of liberalism and republicanism to reject monarchy and aristocracy, and proclaimed that all men are created equal. Congress rejected British proposals requiring allegiance to the monarchy and abandonment of independence.
</p>
<p>
The British were forced out of Boston in 1776, but then captured and held New York City for the duration of the war. The British blockaded the ports and captured other cities for brief periods, but failed to defeat Washington's forces. In early 1778, following a failed patriot invasion of Canada, a British army was captured at the Battle of Saratoga, following which the French openly entered the war as allies of the United States. The war later turned to the American South, where the British captured an army at South Carolina, but failed to enlist enough volunteers from Loyalist civilians to take effective control. A combined American–French force captured a second British army at Yorktown in 1781, effectively ending the war in the United States. The Treaty of Paris in 1783 formally ended the conflict, confirming the new nation's complete separation from the British Empire. The United States took possession of nearly all the territory east of the Mississippi River and south of the Great Lakes, with the British retaining control of Canada and Spain taking Florida.[2][3]
</p>
<p>
Among the significant results of the revolution was the creation of a new Constitution of the United States. The 'Three-Fifths Compromise' allowed the southern slaveholders to consolidate power and maintain slavery in America for another eighty years,[4] but through the expansion of voting rights and liberties over subsequent decades the elected government became responsible to the will of the people.[5] The new Constitution established a relatively strong federal national government that included an executive, a national judiciary, and a bicameral Congress that represented both states in the Senate and population in the House of Representatives.[6][7]
</p>
<p>
Among the significant results of the revolution was the creation of a new Constitution of the United States. The 'Three-Fifths Compromise' allowed the southern slaveholders to consolidate power and maintain slavery in America for another eighty years,[4] but through the expansion of voting rights and liberties over subsequent decades the elected government became responsible to the will of the people.[5] The new Constitution established a relatively strong federal national government that included an executive, a national judiciary, and a bicameral Congress that represented both states in the Senate and population in the House of Representatives.[6][7]
</p>
<h2 id="origins">Origins</h2>
<p>
Historians typically begin their histories of the American Revolution with the British victory in the French and Indian War in 1763, which removed France as a major player in North American affairs. Lawrence Henry Gipson, the historian of the British Empire, states:
</p>
<p>
It may be said as truly that the American Revolution was an aftermath of the Anglo-French conflict in the New World carried on between 1754 and 1763.[8]
</p>
<p>
The Royal Proclamation of 1763 may have played a role in the separation of the United States from Great Britain as colonists at the time wanted to continue in the economically beneficial cultural practice of taking land for one's own livelihood as part of the drive west. The lands west of Quebec and west of a line running along the crest of the Allegheny mountains became Indian territory, temporarily barred from settlement (to the great disappointment of the land speculators of Virginia and Pennsylvania, who had started the Seven Years' War to gain those territories).
</p>
<p>
For the prior history see Thirteen Colonies.
</p>
<h3>1764–1766: Taxes imposed and withdrawn</h3>
<p>
In 1764 Parliament passed the Currency Act to restrain the use of paper money that British merchants saw as a means to evade debt payments.[original research?] Parliament also passed the Sugar Act imposing customs duties on a number of articles. That same year Prime Minister George Grenville proposed to impose direct taxes on the colonies to raise revenue, but delayed action to see if the colonies would propose some way to raise the revenue themselves.[citation needed] None did, and in March 1765 Parliament passed the Stamp Act which imposed direct taxes on the colonies for the first time. All official documents, newspapers, almanacs and pamphlets—even decks of playing cards—were required to have the stamps.
</p>
<p>
The colonists objected chiefly on the grounds not that the taxes were high (they were low),[9] but because they had no representation in the Parliament. Benjamin Franklin testified in Parliament in 1766 that Americans already contributed heavily to the defense of the Empire. He said local governments had raised, outfitted and paid 25,000 soldiers to fight France—as many as Britain itself sent—and spent many millions from American treasuries doing so in the French and Indian War alone.[10][11] Stationing a standing army in Great Britain during peacetime was politically unacceptable. London had to deal with 1,500 politically well-connected British officers who became redundant; it would have to discharge them or station them in North America.[12]
</p>
<p>
In 1765 the Sons of Liberty formed. They used public demonstrations, boycotts, violence and threats of violence to ensure that the British tax laws were unenforceable. While openly hostile to what they considered an oppressive Parliament acting illegally, colonists persisted in sending numerous petitions and pleas for intervention from a monarch to whom they still claimed loyalty. In Boston, the Sons of Liberty burned the records of the vice admiralty court and looted the home of the chief justice, Thomas Hutchinson. Several legislatures called for united action, and nine colonies sent delegates to the Stamp Act Congress in New York City in October 1765\. Moderates led by John Dickinson drew up a "Declaration of Rights and Grievances" stating that taxes passed without representation violated their rights as Englishmen. Colonists emphasized their determination by boycotting imports of British merchandise.[13]
</p>
<p>
The Parliament at Westminster saw itself as the supreme law making authority throughout all British possessions and thus entitled to levy any tax without colonial approval.[14] They argued that the colonies were legally British corporations that were completely subordinate to the British parliament and pointed to numerous instances where Parliament had made laws binding on the colonies in the past.[15] They did not see anything in the unwritten British constitution that made taxes special[16] and noted that Parliament had taxed American trade for decades. Parliament insisted that the colonies effectively enjoyed a "virtual representation" like most British people did, as only a small minority of the British population elected representatives to Parliament.[17] Americans such as James Otis maintained the Americans were not in fact virtually represented.[18]
</p>
<p>
In London, the Rockingham government came to power (July 1765) and Parliament debated whether to repeal the stamp tax or to send an army to enforce it. Benjamin Franklin made the case for repeal, explaining the colonies had spent heavily in manpower, money, and blood in defense of the empire in a series of wars against the French and Indians, and that further taxes to pay for those wars were unjust and might bring about a rebellion. Parliament agreed and repealed the tax (February 21, 1766), but in the Declaratory Act of March 1766 insisted that parliament retained full power to make laws for the colonies "in all cases whatsoever".[19] The repeal nonetheless caused widespread celebrations in the colonies.
</p>
<p>
Briggs says unnamed modern American economic historians have challenged the view that Great Britain was placing a heavy burden on the North American colonies and have suggested the cost of defending them from the possibility of invasion by France or Spain was £400,000 – five times the maximum income from them. Briggs rejects the analysis, saying that issue was not invoked at the time.[20]
</p>
<h3>1767–1773: Townshend Acts and the Tea Act</h3>
<p>
In 1767 the Parliament passed the Townshend Acts, which placed duties on a number of essential goods including paper, glass, and tea and established a Board of Customs in Boston to more rigorously execute trade regulations. The new taxes were enacted on the belief that Americans only objected to internal taxes and not external taxes like custom duties. The Americans, however, argued against the constitutionality of the act because its purpose was to raise revenue and not regulate trade. Colonists responded by organizing new boycotts of British goods. These boycotts were less effective, however, as the Townshend goods were widely used.
</p>
<p>
In February 1768 the Assembly of Massachusetts Bay issued a circular letter to the other colonies urging them to coordinate resistance. The governor dissolved the assembly when it refused to rescind the letter. Meanwhile, in June 1768 a riot broke out in Boston over the seizure of the sloop Liberty, owned by John Hancock, for alleged smuggling. Custom officials were forced to flee, prompting the British to deploy troops to Boston. A Boston town meeting declared no obedience was due to parliamentary laws and called for the convening of a convention. A convention assembled but only issued a mild protest before dissolving itself. In January 1769 Parliament responded to the unrest by reactivating the Treason Act 1543 which permitted subjects outside the realm to face trials for treason in England. The governor of Massachusetts was instructed to collect evidence of said treason, and although the threat was not carried out it caused widespread outrage.
</p>
<p>
On March 5, 1770 a large mob gathered around a group of British soldiers. The mob grew more and more threatening, throwing snowballs, rocks and debris at the soldiers. One soldier was clubbed and fell.[21] There was no order to fire but the soldiers fired into the crowd anyway. They hit 11 people; three civilians died at the scene of the shooting, and two died after the incident. The event quickly came to be called the Boston Massacre. Although the soldiers were tried and acquitted (defended by John Adams), the widespread descriptions soon became propaganda to turn colonial sentiment against the British. This in turn began a downward spiral in the relationship between Britain and the Province of Massachusetts.[21]
</p>
<p>
A new ministry under Lord North came to power in 1770 and Parliament withdrew all taxes except the tax on tea, giving up its efforts to raise revenue while maintaining the right to tax. This temporarily resolved the crisis and the boycott of British goods largely ceased, with only the more radical patriots such as Samuel Adams continuing to agitate.
</p>
<p>
Two ships in a harbor, one in the distance. On board, men stripped to the waist and wearing feathers in their hair are throwing crates into the water. A large crowd, mostly men, is standing on the dock, waving hats and cheering. A few people wave their hats from windows in a nearby building.
This 1846 lithograph by Nathaniel Currier was entitled "The Destruction of Tea at Boston Harbor"; the phrase "Boston Tea Party" had not yet become standard.[22]
</p>
<p>
In June 1772, in what became known as the Gaspee Affair, American patriots including John Brown burned a British warship that had been vigorously enforcing unpopular trade regulations. The affair was investigated for possible treason, but no action was taken.
</p>
<p>
In 1772 it became known that the Crown intended to pay fixed salaries to the governors and judges in Massachusetts. Samuel Adams in Boston set about creating new Committees of Correspondence, which linked Patriots in all 13 colonies and eventually provided the framework for a rebel government. In early 1773 Virginia, the largest colony, set up its Committee of Correspondence, on which Patrick Henry and Thomas Jefferson served.[23]
</p>
<p>
A total of about 7000 to 8000 Patriots served on "Committees of Correspondence" at the colonial and local levels, comprising most of the leadership in their communities — Loyalists were excluded. The committees became the leaders of the American resistance to British actions, and largely determined the war effort at the state and local level. When the First Continental Congress decided to boycott British products, the colonial and local Committees took charge, examining merchant records and publishing the names of merchants who attempted to defy the boycott by importing British goods.[24]
</p>
<p>
In 1773 private letters were published where Massachusetts Governor Thomas Hutchinson claimed the colonists could not enjoy all English liberties, and Lieutenant Governor Andrew Oliver called for the direct payment of colonial officials. The letters, whose contents were used as evidence of a systematic plot against American rights, discredited Hutchinson in the eyes of the people the Assembly petitioned for his recall. Benjamin Franklin, postmaster general for the colonies, acknowledged that he leaked the letters which led to him being berated by British officials and fired from his job.
</p>
<p>
Meanwhile, Parliament passed the Tea Act to lower the price of taxed tea exported to the colonies in order to help the East India Company undersell smuggled Dutch tea. Special consignees were appointed to sell the tea in order to bypass colonial merchants. The act was opposed not only by those who resisted the taxes but also by smugglers who stood to lose business. In most instances the consignees were forced to resign and the tea was turned back, but Massachusetts governor Hutchinson refused to allow Boston merchants to give into pressure. A town meeting in Boston determined that the tea would not be landed, and ignored a demand from the governor to disperse. On December 16, 1773 a group of men, led by Samuel Adams and dressed to evoke the appearance of American Indians, boarded the ships of the British East India Company and dumped £10,000 worth of tea from their holds (approximately £636,000 in 2008) into Boston Harbor. Decades later this event became known as the Boston Tea Party and remains a significant part of American patriotic lore.[25]
</p>
<h3>1774–1775: Intolerable Acts and the Quebec Act</h3>
<p>
The British government responded by passing several Acts which came to be known as the Intolerable Acts, which further darkened colonial opinion towards the British. They consisted of four laws enacted by the British parliament.[26] The first, the Massachusetts Government Act, altered the Massachusetts charter and restricted town meetings. The second Act, the Administration of Justice Act, ordered that all British soldiers to be tried were to be arraigned in Britain, not in the colonies. The third Act was the Boston Port Act, which closed the port of Boston until the British had been compensated for the tea lost in the Boston Tea Party. The fourth Act was the Quartering Act of 1774, which allowed royal governors to house British troops in the homes of citizens without requiring permission of the owner.[27]
</p>
<p>
In response, Massachusetts patriots issued the Suffolk Resolves and formed an alternative shadow government known as the "Provincial Congress" which began training militia outside British-occupied Boston.[28] In September 1774, the First Continental Congress convened, consisting of representatives from each of the colonies, to serve as a vehicle for deliberation and collective action. During secret debates conservative Joseph Galloway proposed the creation of a colonial Parliament that would be able to approve or disapprove of acts of the British Parliament but his idea was not accepted. The Congress instead endorsed the proposal of John Adams that Americans would obey Parliament voluntarily but would resist all taxes in disguise. Congress called for a boycott beginning on 1 December 1774 of all British goods; it was enforced by new committees authorized by the Congress.[29]
</p>
<p>
The Quebec Act of 1774 extended Quebec's boundaries to the Ohio River, shutting out the claims of the 13 colonies. By then, however, the Americans had little regard for new laws from London; they were drilling militia and organizing for war.[30]
</p>
<p>
The British retaliated by confining all trade of the New England colonies to Britain and excluding them from the Newfoundland fisheries. Lord North advanced a compromise proposal in which Parliament would not tax so long as the colonies made fixed contributions for defense and to support civil government. This would also be rejected.
</p>
<h2 id="creating-new-state-constitutions">Creating New State Constitutions</h2>
<p>
Following the Battle of Bunker Hill in June 1775, the Patriots had control of Massachusetts outside the Boston city limits; the Loyalists suddenly found themselves on the defensive with no protection from the British army. In all 13 colonies, Patriots had overthrown their existing governments, closing courts and driving British officials away. They had elected conventions and "legislatures" that existed outside any legal framework; new constitutions were drawn up in each state to supersede royal charters. They declared that they were states now, not colonies.[31]
</p>
<p>
On January 5, 1776, New Hampshire ratified the first state constitution. In May 1776, Congress voted to suppress all forms of crown authority, to be replaced by locally created authority. Virginia, South Carolina, and New Jersey created their constitutions before July 4\. Rhode Island and Connecticut simply took their existing royal charters and deleted all references to the crown.[32] The new states were all committed to republicanism, with no inherited offices. They decided not only what form of government to create, and also how to select those who would craft the constitutions and how the resulting document would be ratified. But there would be no universal suffrage and real power, including the right to elect the future President would still lay in the hands of a few selected elites for many years. On 26 May 1776 John Adams wrote James Sullivan from Philadelphia;
</p>
<p>
"Depend upon it, sir, it is dangerous to open so fruitful a source of controversy and altercation, as would be opened by attempting to alter the qualifications of voters. There will be no end of it. New claims will arise. Women will demand a vote. Lads from twelve to twenty one will think their rights not enough attended to, and every man, who has not a farthing, will demand an equal voice with any other in all acts of state. It tends to confound and destroy all distinctions, and prostrate all ranks, to one common level".[33][34]
</p>
<p>
In states where the wealthy exerted firm control over the process, such as Maryland, Virginia, Delaware, New York and Massachusetts – the last-mentioned of these state's constitutions still being in force in the 21st century, continuously since its ratification on June 15, 1780 – the results were constitutions that featured:
</p>
<p>
Substantial property qualifications for voting and even more substantial requirements for elected positions (though New York and Maryland lowered property qualifications);[31]
Bicameral legislatures, with the upper house as a check on the lower;
Strong governors, with veto power over the legislature and substantial appointment authority;
Few or no restraints on individuals holding multiple positions in government;
The continuation of state-established religion.
</p>
<p>
In states where the less affluent had organized sufficiently to have significant power—especially Pennsylvania, New Jersey, and New Hampshire—the resulting constitutions embodied
</p>
<p>
universal white manhood suffrage, or minimum property requirements for voting or holding office (New Jersey enfranchised some property owning widows, a step that it retracted 25 years later);
strong, unicameral legislatures;
relatively weak governors, without veto powers, and little appointing authority;
prohibition against individuals holding multiple government posts;
</p>
<p>
The radical provisions of Pennsylvania's constitution lasted only 14 years. In 1790, conservatives gained power in the state legislature, called a new constitutional convention, and rewrote the constitution. The new constitution substantially reduced universal white-male suffrage, gave the governor veto power and patronage appointment authority, and added an upper house with substantial wealth qualifications to the unicameral legislature. Thomas Paine called it a constitution unworthy of America.[6]
</p>
<h2 id="military-hostilities-begin">Military hostilities begin</h2>
<p>
Massachusetts was declared in a state of rebellion in February 1775 and the British garrison received orders to disarm the rebels and arrest their leaders, leading to the Battles of Lexington and Concord on 19 April 1775\. The Patriots set siege to Boston, expelled royal officials from all the colonies, and took control through the establishment of Provincial Congresses. The Battle of Bunker Hill followed on June 17, 1775\. While a British victory, it was at a great cost; about 1,000 British casualties from a garrison of about 6,000, as compared to 500 American casualties from a much larger force.[35][36] First ostensibly loyal to the king and desiring to govern themselves while remaining in the empire, the repeated pleas by the First Continental Congress for royal intervention on their behalf with Parliament resulted in the declaration by the King that the states were "in rebellion", and the members of Congress were traitors.
</p>
<p>
In the winter of 1775, the Americans invaded Canada. General Richard Montgomery captured Montreal but a joint attack on Quebec was a total failure; many Americans were captured or died of smallpox.
</p>
<p>
In March 1776, with George Washington as the commander of the new army, the Continental Army forced the British to evacuate Boston. The revolutionaries were now in full control of all 13 colonies and were ready to declare independence. While there still were many Loyalists, they were no longer in control anywhere by July 1776, and all of the Royal officials had fled.[37]
</p>
<p>
In August 1775, George III declared Americans in arms against royal authority to be traitors to the Crown. Following their surrender at the Battles of Saratoga in October 1777, there were thousands of British and Hessian soldiers in American hands. Although Lord Germain took a hard line, the British generals on the scene never held treason trials; they treated captured enemy soldiers as prisoners of war.[38] The dilemma was that tens of thousands of Loyalists were under American control and American retaliation would have been easy. The British built much of their strategy around using these Loyalists.[39] Therefore, no Americans were put on trial for treason. The British maltreated the prisoners they held, resulting in more deaths to American sailors and soldiers than from combat operations.[39] At the end of the war, both sides released their surviving prisoners.[40]
</p>
<h2 id="independence-and-union">Independence And Union</h2>
<p>
In April 1776 the North Carolina Provincial Congress issued the Halifax Resolves, explicitly authorizing its delegates to vote for independence.[41] In May Congress called on all the states to write constitutions, and eliminate the last remnants of royal rule.
</p>
<p>
By June nine colonies were ready for independence; one by one the last four—Pennsylvania, Delaware, Maryland and New York—fell into line. Richard Henry Lee was instructed by the Virginia legislature to propose independence, and he did so on June 7, 1776\. On the 11th a committee was created to draft a document explaining the justifications for separation from Britain. After securing enough votes for passage, independence was voted for on July 2\. The Declaration of Independence, drafted largely by Thomas Jefferson and presented by the committee, was slightly revised and unanimously adopted by the entire Congress on July 4, marking the formation of a new sovereign nation, which called itself the United States of America.[42]
</p>
<p>
The Second Continental Congress approved a new constitution, the "Articles of Confederation," for ratification by the states on November 15, 1777, and immediately began operating under their terms. The Articles were formally ratified on March 1, 1781\. At that point, the Continental Congress was dissolved and on the following day a new government of the United States in Congress Assembled took its place, with Samuel Huntington as presiding officer.[43][44]
</p>
<h2 id="more">More...</h2>
<a href="https://en.wikipedia.org/wiki/American_Revolution">American Revolution on Wikipedia</a>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script src="./javascripts/main.js" type="text/javascript"></script>
</body>
</html>
Listing 10-1Long Page with a Menu
该页面引用自定义 JavaScript 的本地javascripts/main.js文件。暂时把这个当做空的。它还引用自定义 CSS 的本地stylesheets/main.css文件。把那个也当成空的。如果您保存前一页的内容并将其加载到您的浏览器上,您将看到以下内容(图 10-1 )。

图 10-1
带有顶部导航的长页面
从前面的章节中你已经知道了导航栏 HTML 标记。您还学习了如何处理隐藏body顶部内容的问题。以下是 CSS 文件中必须包含的内容:
body {
padding-top: 56px;
}
如果您保存前面的代码并在浏览器上重新加载页面,那么您将能够看到页面的顶部内容,而不会被导航栏隐藏(图 10-2 )。

图 10-2
顶部内容可见的长页面
这个页面的另一个问题也是我在上一本书 大师 HTML & CSS 第 23 章“定位”中处理过的问题,就是当你点击菜单项时导航栏所覆盖的内容的问题。例如,点击菜单项State Constitutions。你会看到下面的图(图 10-3 )。

图 10-3
导航栏覆盖的内容
正如您所看到的,与您链接的链接相对应的部分的开头被导航栏所覆盖。
您可以通过将下面的padding-top和margin-top CSS 属性添加到h1和h2元素来解决这个问题,这两个元素是页面的 HTML 元素,带有菜单项链接到的锚点(清单 10-2 )。
h1, h2 {
padding-top: 56px;
margin-top: -56px;
}
Listing 10-2Add to Your CSS File to Fix Hidden Section Content
如果您将前面的代码保存在您的stylesheets/main.css文件中,并在您的浏览器上重新加载该页面,点击State Constitutions将显示如下(图 10-4 )。

图 10-4
单击菜单项时,内容不被覆盖
然而,当点击More菜单项时,你希望页面将它的内容放在顶部。这种情况现在没有发生(图 10-5 )。

图 10-5
点击更多不会将内容显示在顶部
为了解决这个问题,你需要给页面的body增加一些下边距。
添加margin-bottom: 900px;。保存 CSS 文件并在浏览器上重新加载页面。点击More菜单项,会出现如下画面(图 10-6 )。

图 10-7
指向各节开头的菜单项

图 10-6
点击更多会在顶部显示内容
显示活动部分
当前页面的问题是,当您单击一个菜单项并且内容滚动到该点时,相应的菜单项不会变为活动状态。此外,如果您只是从上到下、从一节到另一节滚动内容,相应的菜单项不会变为活动状态。
这两个问题现在都可以通过使用 ScrollSpy 来解决,scroll spy 是一个 Twitter 引导 JavaScript 插件:
-
你需要告诉 ScrollSpy 哪个元素包含了你想要窥探的内容。通常,这就是
body。你设置数据属性data-spy="scroll"。 -
您需要告诉 ScrollSpy 哪个是包含菜单项列表的导航栏元素。在您的例子中,这是 id 为
navbar的div。因此,您必须将data-target="#navbar"属性添加到body元素中。 -
您还需要将
body元素的position属性设置为值relative。
所以,首先,转到 HTML 页面
<body>
对此:
<body data-spy="scroll" data-target="#navbar">
将position: relative添加到stylesheets/main.css文件中的body元素中。
保存所有的东西,并在你的浏览器上重新加载页面。您将看到第一个菜单项被突出显示,然后当您滚动时,根据页面的可见部分,相应的菜单项被突出显示。
激活截面点
有时,当节的开始位置早于页面顶部时,您可能希望活动节在菜单上突出显示。例如,当节的起点距离页面顶部 200 像素时,您可能想要激活节。您可以使用数据属性data-offset来实现,该属性将您想要激活的区域的像素数作为值。
变化
<body data-spy="scroll" data-target="#navbar">
对此:
<body data-spy="scroll" data-target="#navbar" data-offset="200">
在浏览器上保存并重新加载页面。然后开始滚动。您将看到,在部分开始到达页面顶部之前,部分已被激活。
它是如何工作的?
除了如前所述需要设置的正确数据属性(data-spy、data-target和可选的data-offset,您还需要确保
-
您的菜单项指向与这些部分的开头相对应的 id。再次查看导航栏中带有菜单项的 HTML 片段(图 10-7 ):
-
各部分的开头需要有相应的/正确的 id,例如:
<h2 id="military-hostilities-begin">Military hostilities begin</h2>
使用 JavaScript 激活
您可能需要使用 JavaScript 动态激活 ScrollSpy。因此,不是在body元素上附加特定的数据属性,而是不添加任何东西,而是调用下面的 JavaScript 代码:
$('body').scrollspy({ target: '#navbar' });
让我们看看实际情况。将 HTML body元素改为
<body>
然后更新javascripts/main.js文件,使内容如清单 10-3 所示。
$(document).ready(function() {
$('body').scrollspy({
target: '#navbar'
})
});
Listing 10-3Active ScrollSpy with JavaScript
当您保存所有文件并在浏览器上重新加载页面时,您仍然会看到 ScrollSpy 像以前一样工作。
请注意,您还可以在您直接构造的对象中赋予offset属性,并将其传递给scrollspy()方法。
任务和测验
Task Details
创建一个长页面来演示 ScrollSpy 功能。您的页面需要有一个顶部导航菜单,将页面内容移动到相应部分的开始。创建两个版本——一个使用 JavaScript,另一个使用数据属性。
关键要点
-
如何显示带有导航栏的长内容页面
-
如何让内容可见而不被导航栏隐藏
-
如何让最后一节内容出现在页面顶部
-
如何在用户从页面顶部滚动到底部时自动更改活动菜单项
-
如何使用数据属性或 JavaScript 来激活 ScrollSpy
在本书的最后一章,你将学习工具提示和弹出窗口,这是一个非常吸引人的页面特性,因为它为用户提供了与他们交互的元素的额外信息。
十一、工具提示和弹出窗口
工具提示和弹出窗口是在页面内容中嵌入额外的、次要的有用信息的好工具。这一章教你 Twitter 引导工具提示和弹出窗口。
您将创建如下所示的页面(图 11-1 )。

图 11-1
示例工具提示已激活
你将学习如何像下面这样嵌入 HTML 内容(图 11-2 )。

图 11-2
被视为 HTML 的工具提示 HTML 标记—请参见粗体文本
popovers 将增强次要的、有用的信息的样式,甚至更多(图 11-3 )。

图 11-3
Popover 示例
学习目标
-
了解工具提示。
-
了解如何激活工具提示及其选择性加入功能。
-
了解如何将一个单词或短语包装成适当的 HTML,以便为其附加工具提示。
-
学习如何将一个单词或短语包装成合适的 HTML,这样当用户移动到它上面时,它会突出显示并出现一个工具提示。
-
了解可用于自定义其行为的工具提示选项。
-
了解松饼。
-
了解工具提示和弹出式菜单之间的区别和相似之处。
-
了解松饼的选择。
工具提示
当用户将鼠标悬停在突出显示的文本上时,工具提示是显示有用文本的一种非常好的方式。所以它被用来提供一些额外的有用信息,比如提示或暗示。
这是一个使用工具提示的页面示例(图 11-4 )。

图 11-4
带有特定单词工具提示的示例页面
如果您将鼠标悬停在带虚线下划线的单词上,您将会看到工具提示。例如,参见图 11-5 。

图 11-5
工具提示已激活
用 Twitter 引导实现
让我们看看如何实现前面的例子。下面是 HTML 页面(清单 11-1 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Tooltips and Popovers</title>
</head>
<body>
<div class="container">
<h1>Drones</h1>
<h2>HK 251 Whirlwind Brushless Quadcopter Review</h2>
<p>
The XK 251 is a RTF mid-sized (250 mm diagonal) quadcopter
featuring brushless motors and carbon fiber arms and landing gear.
Brushless motors are more efficient and more powerful than the brushed variety typically found on toy-grade models.
They also have a much longer life span.
Here is an <a href="http://droneflyers.com/talk/threads/is-a-brushless-motor-better-than-a-brushed-motor.754/">
FAQ relating to the difference between brushed and brushless motors.</a>
The XK 251 weighs in at 215 grams meaning that no FAA registration is needed. It is powered by a small 2s (7.4v) battery.
</p>
<div class="text-center">
<img src="img/drone-image.jpg" alt="Drone Image" id="drone-image"/>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script src="./javascripts/main.js" type="text/javascript"></script>
</body>
</html>
Listing 11-1HTML Page with Tooltips
如果您保存前面的代码并在浏览器上加载页面,您将看到页面正确显示,但工具提示将不起作用。如果你将鼠标悬停在单词RTF和quadcopter上,你将不会看到工具提示冒泡(图 11-6 )。

图 11-6
RTF 和四轴飞行器还没有工具提示
为了让一个单词有一个工具提示,你需要做到以下几点:
-
将单词包装到一个
span元素中。因此,该词不会改变其相对于文本其余部分的位置。 -
添加数据属性
data-toggle="tooltip"。这将告诉 Bootstrap 在鼠标经过时会用工具提示来修饰span的内容。 -
添加数据属性
data-placement="top"。这将告诉 Bootstrap 工具提示需要出现在span内容的顶部。注意data-placement可以取值left、top、right或bottom。选择最适合您情况的值。 -
添加属性
title,该属性的值是鼠标经过时要显示的文本。 -
使用 JavaScript 激活工具提示。这是必要的,因为 Bootstrap 有默认不启用的工具提示。这样做是出于性能原因。你必须选择每一个你想要工具提示的特殊情况。
让我们对 HTML 页面上的单词RTF和quadcopter采取前面的步骤。将RTF一词包装如下:
<span data-toggle="tooltip" data-placement="top" title="Ready to Fly">RTF</span>
按照以下方式包装quadcopter:
<span data-toggle="tooltip" data-placement="bottom"
title="An aerial vehicle using 4 rotors, commonly using only the varying speed of the motors to achieve both stability and direction of flight.">quadcopter</span>
接下来,更新javascripts/main.js文件,如下所示:
$(document).ready(function() {
$('[data-toggle=tooltip]').tooltip();
});
上面的代码是实现的选择加入部分,它为所有具有数据属性data-toggle="tooltip"的元素启用工具提示。
如果您保存所有前面的代码并在浏览器上重新加载页面,一切都将就绪。当你将鼠标悬停在单词RTF和quadcopter ,上时,你会看到工具提示。
如您所见,工具提示显示在鼠标悬停时。
我们必须介绍一个小小的改进。您需要找到一种方法来告诉用户,如果他们将鼠标放在某个特定的单词上,就会出现一个工具提示,提供进一步的解释信息。如果你不这样做,那么用户就不知道这个单词后面隐藏着一个工具提示。
为了达到这个目的,你通常希望工具提示后面的单词用虚线加下划线。Twitter Bootstrap 让你的造型工作变得简单。您可以将文本包装在abbr元素中,而不是将工具提示包装在span中。
继续将span元素更改为abbr元素。
对于 RTF:
<abbr data-toggle="tooltip" data-placement="top" title="Ready to Fly">RTF</abbr>
对于quadcopter:
<abbr data-toggle="tooltip" data-placement="top"
title="An aerial vehicle using 4 rotors, commonly using only the varying speed of the motors to achieve both stability and direction of flight.">quadcopter</abbr>
当您保存这些更改并在浏览器上重新加载页面时,您会看到单词RTF和quadcopter用虚线加下划线(图 11-7 )。

图 11-7
工具提示的单词以下划线显示
工具提示选项
工具提示有许多不同的选项,可用于定制。让我们看看最重要的几个:
-
animation:有默认值true。它在显示工具提示时应用 CSS 淡入淡出过渡。 -
delay:可以是数字,也可以是 JavaScript 对象。如果它是一个数字,那么它定义了显示或隐藏工具提示的延迟,以毫秒为单位。如果它是一个对象,那么它可以有show和hide属性,它们的整数值分别代表显示或隐藏的延迟。
让我们试试那个。我们将设置 delay 属性,并查看工具提示的行为。在上一页,继续修改javascripts/main.js文件,使其类似于清单 11-2 。
$(document).ready(function() {
$('[data-toggle=tooltip]').tooltip({
delay: {
show: 3000, // 3 seconds
hide: 1000 // 1 second
}
});
});
Listing 11-2Add Delay to Tooltips
如果您保存前面的代码并在浏览器上重新加载页面,当您将鼠标悬停在带有工具提示的单词上 3 秒钟后,您将看到工具提示出现。您还会看到,当您将鼠标移出带有工具提示的单词时,它会在 1 秒钟后消失。
html:这是一个布尔选项,取值为true或false。其默认值为false。使用false,工具提示元素的title属性的值通过插入。text() 方法。这意味着即使标题包含 HTML 标记,这实际上也不会被使用;它将被视为纯文本。另一方面,如果html选项设置为true,当title上有一个包含 HTML 标记的值时,将使用将其插入工具提示区域。html() 方法,因此,html 标记将受到尊重。让我们看一个例子。
首先,给quadcopter单词的标题添加一些 HTML 标记:
<abbr data-toggle="tooltip" data-placement="top"
title="An aerial vehicle using <b>4 rotors</b>, commonly using only the varying speed of the motors to achieve both stability and direction of flight.">quadcopter</abbr>
您在标题中添加了<b>4 rotors</b> HTML 标记。
现在,确保javascripts/main.js文件如下:
$(document).ready(function() {
$('[data-toggle=tooltip]').tooltip({
html: false // default value
});
});
虽然当您将html的值设置为 false 时这是不必要的,但是稍后您将需要前面的代码片段。
在浏览器上保存并加载页面。当你将鼠标悬停在quadcopter单词上时,你会看到工具提示,但是<b>4 rotors</b>部分会被逐字打印,被视为纯文本(图 11-8 )。

图 11-8
逐字打印 HTML 标记
如果您希望将title属性的 HTML 标记视为 HTML 并以 HTML 的形式呈现,您需要将选项html的值设置为true:
$(document).ready(function() {
$('[data-toggle=tooltip]').tooltip({
html: true
});
});
将前面的代码保存在javascripts/main.js中,并在浏览器上重新加载页面。当您将鼠标悬停在单词quadcopter(图 11-9 )上时,您会看到这一点。

图 11-9
工具提示 HTML 标记被视为 HTML
如您所见,title属性的 HTML 内容被显示为一个 HTML 片段,没有任何问题。
波波夫斯
弹出式菜单类似于工具提示,但允许更丰富、更醒目的布局和样式。此外,需要单击目标元素,弹出窗口才会出现和消失。这是一个弹出器的例子(图 11-10 )。

图 11-10
Popover 示例
让我们改变上一页关于RTF和quadcopter单词的提示。你要放些松饼。
HTML 页面应该如下所示(清单 11-3 )。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="stylesheets/main.css" type="text/css">
<title>Popover Example Page</title>
</head>
<body>
<div class="container">
<h1>Drones</h1>
<h2>HK 251 Whirlwind Brushless Quadcopter Review</h2>
<p>
The XK 251 is an RTF
<a href="#"
data-toggle="popover"
data-placement="top"
title="Ready to Fly"
data-content="Ready to Fly drones are drones with the key at hand. You can start flying them immediately.">
<i class="fa fa-question-circle"></i>
</a>
mid-sized (250 mm diagonal)
quadcopter
<a href="#"
data-toggle="popover" data-placement="top"
title="Quadcopter"
data-content="An aerial vehicle using <b>4 rotors</b>, commonly using only the varying speed of the motors to achieve both stability and direction of flight.">
<i class="fa fa-question-circle"></i>
</a>
featuring brushless motors and carbon fiber arms and landing gear.
Brushless motors are more efficient and more powerful than the brushed variety typically found on toy-grade models.
They also have a much longer life span.
Here is an <a href="http://droneflyers.com/talk/threads/is-a-brushless-motor-better-than-a-brushed-motor.754/">
FAQ relating to the difference between brushed and brushless motors.</a>
The XK 251 weighs in at 215 grams meaning that no FAA registration is needed. It is powered by a small 2s (7.4v) battery.
</p>
<div class="text-center">
<img src="img/drone-image.jpg" alt="Drone Image" id="drone-image"/>
</div>
</div>
<!-- Optional JavaScript -->
<script src="https://kit.fontawesome.com/<your-font-awesome-account-public-key.js" crossorigin="anonymous"></script>
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script src="./javascripts/main.js" type="text/javascript"></script>
</body>
</html>
Listing 11-4stylesheets/main.css
Listing 11-3HTML Page with Popovers
这个要配上下面的stylesheets/main.css(清单 11-4 )和javascripts/main.js文件(清单 11-5 )。
清单 11-4。 stylesheets/main.css
a[data-toggle=popover] {
text-decoration: none;
}
清单 11-5。 javascripts/main.js
$(document).ready(function() {
$('[data-toggle=popover]').popover({
html: true
});
});
Note
这个页面再次使用 FontAwesome 在单词 RTF 和 quadcopter 旁边画问号图标。为了使用 FontAwesome,您必须用它们创建一个帐户,并生成对它们的 JavaScript 库的特定于帐户的引用。你必须在前面的代码有行<script src=" https://kit.fontawesome.com/ <your-font-awesome-account-public-key.js"crossorigin="anonymous"></script>的地方使用这个引用。
下面是带有弹出窗口的 HTML 页面和带有工具提示的 HTML 页面的区别和相似之处:
- 对于 popovers,我们使用以下数据属性:
-
data-toggle="popover"。对于工具提示,我们使用data-toggle="tooltip"。 -
data-placement属性用于既指定元素的位置。 -
title属性用于指定工具提示的内容。对于弹出框,这用于指定弹出框的方向。 -
data-content仅用于 popover,指定 popover 主体的内容。
-
参见图 11-11 了解 popover 的头部和主体以及它们分别与title和data-content,的关系。

图 11-11
Popover 的标题和正文
如果您保存前面的文件并在浏览器上加载页面,您将能够单击问号图标来查看弹出窗口。
正如您所体验到的,您集成弹出窗口的方式存在一个问题,即只有当用户单击用于显示弹出窗口的同一个热点时,弹出窗口才会关闭。
你如何允许用户点击任何地方来关闭弹出窗口?为了实现这一点,您需要稍微改变一下 popovers 的集成方式:
-
你需要使用数据属性
data-trigger="focus"。 -
您需要为第一个 popover 添加属性
tabindex="0",为第二个 popover 添加属性tabindex="1",依此类推。
让我们在你的页面上做这些更新。
对于RTF字:
RTF
<a href="#"
data-toggle="popover"
data-placement="top"
title="Ready to Fly"
tabindex="0"
data-trigger="focus"
data-content="Ready to Fly drones are drones with the key at hand. You can start flying them immediately.">
<i class="fa fa-question-circle"></i>
</a>
对于quadcopter字:
quadcopter
<a href="#"
data-toggle="popover" data-placement="top"
title="Quadcopter"
tabindex="1"
data-trigger="focus"
data-content="An aerial vehicle using <b>4 rotors</b>, commonly using only the varying speed of the motors to achieve both stability and direction of flight.">
<i class="fa fa-question-circle"></i>
</a>
如果您做了这些更改并重新加载页面,那么您将能够通过单击页面上的任意位置来关闭弹出窗口。
Tip
当您单击打开弹出窗口时,您会看到问号图标周围有一个蓝色边框,同时弹出窗口具有焦点。您可以通过应用以下 CSS 规则来消除它:
a[data-toggle=popover]:focus {outline: transparent;}
选择
像工具提示一样,弹出窗口也有各种选项。以下是一些最有用的方法:
-
animation:取一个布尔值true或false。默认值为true。它将 CSS 淡入淡出过渡应用到弹出窗口。 -
这要么是一个数字,要么是一个对象。这与工具提示的
delay选项完全一样。 -
html:布尔值,默认值为false。如果true,允许内容被解析为 HTML 而不是纯文本。
任务和测验
Task Details

图 11-12
带有工具提示和弹出窗口的任务页面
-
你需要开发一个网页来展示工具提示和弹出窗口。
-
试着创建一个如下的页面(对于这个页面,全部内容都取自维基百科)(图 11-12 )。
关键要点
-
如何创建当用户的鼠标移动到一个特殊的单词或短语上时出现的工具提示
-
如何创建当用户点击图标时出现的弹出窗口
结局
恭喜你!
您已经完成了与 Twitter Bootstrap 的实际接触!我真的希望你喜欢这次旅行,你学到的东西可以应用到你的项目中。











浙公网安备 33010602011771号