文章目录
1 导航栏实现
导航条基本上是一个链接列表,所以使用 <ul>
和 <li>
元素非常有意义。
让我们从列表中删除边距和填充:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
ul
{
list-style-type:none;
margin:0;
padding:0;
}
</style>
</head>
<body>
<ul>
<li><a href="#home">主页</a></li>
<li><a href="#news">新闻</a></li>
<li><a href="#contact">联系</a></li>
<li><a href="#about">关于</a></li>
</ul>
</body>
</html>

- list-style-type:none - 移除列表前小标志。一个导航栏并不需要列表标记
- 移除浏览器的默认设置将边距和填充设置为0
上面的例子中的代码是垂直和水平导航栏使用的标准代码。
1.1 垂直导航条
我们创建一个左边是全屏高度的固定导航条,右边是可滚动的内容。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
body {
margin: 0;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
width: 25%;
background-color: #f1f1f1;
position: fixed;
height: 100%;
overflow: auto;
}
li a {
display: block;
color: #000;
padding: 8px 16px;
text-decoration: none;
}
li a.active {
background-color: #4CAF50;
color: white;
}
li a:hover:not(.active) {
background-color: #555;
color: white;
}
</style>
</head>
<body>
<ul>
<li><a class="active" href="#home">主页</a></li>
<li><a href="#news">新闻</a></li>
<li><a href="#contact">联系</a></li>
<li><a href="#about">关于</a></li>
</ul>
<div style="margin-left:25%;padding:1px 16px;height:1000px;">
<h2>Fixed Full-height Side Nav</h2>
<h3>Try to scroll this area, and see how the sidenav sticks to the page</h3>
<p>Notice that this div element has a left margin of 25%. This is because the side navigation is set to 25% width. If you remove the margin, the sidenav will overlay/sit on top of this div.</p>
<p>Also notice that we have set overflow:auto to sidenav. This will add a scrollbar when the sidenav is too long (for example if it has over 50 links inside of it).</p>
<p>Some text..</p>
<p>Some text..</p>
<p>Some text..</p>
<p>Some text..</p>
<p>Some text..</p>
<p>Some text..</p>
<p>Some text..</p>
</div>
</body>
</html>

好的,非常乐意以一位前端专家的身份,为你详细解析这段关于垂直导航栏实现的代码案例。
这是一个非常经典和基础的前端教学案例,它循序渐进地展示了如何从一个普通的 HTML 列表,通过一步步添加 CSS 样式,最终构建出一个功能完善、布局合理的现代化网页侧边导航栏。
下面我将分步解析其中的核心知识点。
1.1.1 HTML 结构
<ul>
<li><a href="#home">主页</a></li>
<li><a href="#news">新闻</a></li>
<li><a href="#contact">联系</a></li>
<li><a href="#about">关于</a></li>
</ul>
- 语义化 (Semantics): 选择
<ul>
(无序列表) 和<li>
(列表项) 来构建导航。这是一个非常重要的最佳实践。从语义上讲,导航栏本质上就是一组“链接的列表”,使用<ul>
和<li>
能够让浏览器、搜索引擎和屏幕阅读器(为视障人士服务)更好地理解页面结构。 - 链接 (
<a>
): 每个列表项<li>
中都包含一个<a>
(锚点) 标签,这是实现页面跳转或链接的唯一方式。href="#home"
这样的写法是一个“页内链接”,点击它会跳转到当前页面中id="home"
的元素位置。
1.1.2 CSS 样式
ul {
list-style-type: none; /* 移除列表项前的默认小圆点 */
margin: 0; /* 移除 ul 元素的默认外边距 */
padding: 0; /* 移除 ul 元素的默认内边距 */
}
- 目的: 不同浏览器对于
<ul>
、<body>
等元素会自带一些默认的margin
(外边距) 和padding
(内边距) 样式。为了在所有浏览器上获得一致的、可控的显示效果,我们通常会首先“重置”这些默认样式,将它们设为 0。 list-style-type: none;
: 这是关键一步,它移除了<li>
元素前方的默认项目符号(比如小黑点)。对于导航栏来说,这些符号是不需要的。
1.1.3 基本垂直导航栏
在重置了基础样式后,我们开始把它变成一个真正的“导航栏”。
/* 对 <ul> 容器进行样式化 */
ul {
width: 200px; /* 设置导航栏的固定宽度 */
background-color: #f1f1f1; /* 设置浅灰色背景,使其与页面内容区分开 */
}
/* 对 <li> 里的 <a> 链接进行样式化 */
li a {
display: block; /* 核心!将链接变为块级元素 */
color: #000; /* 链接文字颜色为黑色 */
padding: 8px 16px; /* 设置内边距,增加点击区域和视觉空间感 */
text-decoration: none; /* 移除链接默认的下划线 */
}
display: block;
: 这是将一个普通链接列表变成导航栏样式的最关键属性。- 默认情况下,
<a>
标签是 行内元素 (inline element)。它的宽度只由其内部的文字决定,并且你无法设置其width
和height
。点击区域也仅限于文字本身。 - 将其设置为 块级元素 (block element) 后,
<a>
标签会“撑满”其父元素<li>
的整个宽度(这里是 200px)。这意味着整个灰色区域(而不仅仅是文字)都变成了可点击的链接,极大地提升了用户体验。同时,这也使得padding
能够上下左右生效,创造出更美观的视觉效果。
- 默认情况下,
padding: 8px 16px;
: 这个简写属性表示“上下内边距为 8px,左右内边距为 16px”。它在<a>
元素内部创建了空白空间,让文字不会紧贴着边框,看起来更舒适。text-decoration: none;
: 导航链接通常不需要下划线,这个属性可以将其移除。
1.1.4 增加交互性与状态
一个静态的导航栏是不够的,用户需要视觉反馈来知道他们正在与哪个元素交互,以及他们当前在哪一页。
/* 鼠标悬停 (hover) 时的效果 */
li a:hover {
background-color: #555; /* 背景变为深灰色 */
color: white; /* 文字变为白色 */
}
/* “激活”状态的样式 */
li a.active {
background-color: #4CAF50; /* 背景变为绿色 */
color: white; /* 文字变为白色 */
}
:hover (伪类)
: 这是一个 CSS 伪类 (pseudo-class),它定义的样式只在用户的鼠标指针悬停在该元素上时才会生效。这是提供即时视觉反馈最常用的方法。.active (类选择器)
: 这是一个自定义的 类 (class)。它的作用是高亮显示用户当前所在的页面对应的导航项。这个active
类通常需要通过 JavaScript 或后端服务器语言动态地添加到对应的<a>
标签上。例如,当用户访问“新闻”页面时,新闻链接的 HTML 就会变成<a class="active" href="#news">新闻</a>
。
1.1.4 最终案例
这是前面所有知识点的综合应用,构建了一个非常常见的网页布局:左侧固定的导航菜单和右侧可滚动的内容区域。
HTML:
<div style="margin-left:25%;padding:1px 16px;height:1000px;">
</div>
CSS:
/* 对 <ul> 导航栏的核心样式 */
ul {
width: 25%; /* 宽度为视窗(viewport)的25% */
position: fixed; /* 核心!固定定位 */
height: 100%; /* 高度占满整个视窗 */
overflow: auto; /* 如果内容超出,则显示滚动条 */
}
/* 对 <a> 链接的悬停效果进行优化 */
li a:hover:not(.active) {
background-color: #555;
color: white;
}
position: fixed;
: 这是实现固定导航栏的魔法所在。- 当一个元素的
position
被设为fixed
,它会脱离正常的文档流,其定位将相对于浏览器视窗 (viewport)。 - 这意味着,即使用户滚动右侧的内容区域,这个导航栏也会牢牢地“固定”在屏幕的左侧,不会随滚动而移动。
height: 100%;
配合position: fixed;
,使得导航栏的高度始终与浏览器窗口的高度一致。
- 当一个元素的
overflow: auto;
: 这个属性非常实用。它规定,如果导航栏中的链接项太多,以至于超出了屏幕的高度,那么导航栏内部将会出现一个独立的滚动条,而不会影响到整个页面的滚动。margin-left: 25%;
(应用于右侧<div>
): 这是与position: fixed
协同工作的关键一步。- 因为导航栏 (
<ul>
) 设置了position: fixed
后脱离了文档流,它会“浮”在页面的上层。如果没有其他设置,右侧的内容<div>
会从页面的最左边开始布局,从而被左侧的导航栏所遮盖。 - 通过给右侧内容
<div>
设置margin-left: 25%
,我们等于是在其左侧“推开”了 25% 视窗宽度的空间,这个宽度正好等于左侧导航栏的宽度 (width: 25%
)。这样,内容区域就完美地显示在了导航栏的右边。
- 因为导航栏 (
li a:hover:not(.active)
: 这是一个更精细的选择器链。:not(.active)
的意思是“不包含 .active 类的元素”。- 所以整个选择器的含义是:当鼠标悬停在一个链接上,并且这个链接不是当前激活的链接时,才应用悬停样式。
- 这样做可以防止那个已经用绿色高亮的 “active” 链接在鼠标滑过时,背景色又变成灰色,从而保持了状态的清晰性,是很好的用户体验设计。
1.2 水平导航条
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
border: 1px solid #e7e7e7;
background-color: #f3f3f3;
}
li {
float: left;
}
li a {
display: block;
color: #666;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
li a:hover:not(.active) {
background-color: #ddd;
}
li a.active {
color: white;
background-color: #4CAF50;
}
</style>
</head>
<body>
<ul>
<li><a class="active" href="#home">主页</a></li>
<li><a href="#news">新闻</a></li>
<li><a href="#contact">联系</a></li>
<li><a href="#about">关于</a></li>
</ul>
</body>
</html>

这个案例中,实现水平布局的关键在于两个 CSS 属性:float: left;
和 overflow: hidden;
。
1.2.1 改变 1
- 在垂直导航条中:我们没有对
<li>
设置任何布局属性。作为块级元素,它们会自然地、一个接一个地垂直排列下来,每个<li>
独占一行。 - 在水平导航条中:我们给
<li>
添加了float: left;
。float
(浮动) 属性会使元素脱离正常的文档流(document flow),并尽可能地向左(或向右)移动,直到它碰到其父容器的边缘或者另一个浮动元素的边缘。- 当第一个
<li>
设置为float: left;
,它会浮动到其父容器<ul>
的最左侧。 - 紧接着,第二个
<li>
也会float: left;
,它会紧挨着前一个浮动元素的右侧排列。 - 以此类推,所有的
<li>
元素就会像积木一样一个挨一个地水平排列起来,从而形成水平导航条。
1.2.2 改变 2
这是一个非常经典且重要的 CSS技巧,通常被称为“清除浮动”(Clearfix)。
- 问题所在:当一个容器元素(这里是
<ul>
)内部的所有子元素(所有的<li>
)都设置了浮动(float
)时,这些子元素就脱离了正常的文档流。这会导致父容器<ul>
无法正确计算其高度,它会认为自己内部“没有内容”,从而导致其高度“坍塌”为 0。如果你给<ul>
设置了背景色或边框,你会发现它们根本不显示,因为<ul>
自身没有了高度。 - 解决方案:给父容器
<ul>
添加overflow: hidden;
。- 这个属性会触发一个名为“块级格式化上下文”(Block Formatting Context, BFC)的 CSS特性。
- BFC 的一个重要作用就是能够包含其内部的浮动元素。一旦
<ul>
成为了一个 BFC,它就会重新计算其高度,以包裹住所有浮动的<li>
子元素。 - 因此,
overflow: hidden;
在这里的主要目的不是为了隐藏溢出的内容,而是为了清除<li>
浮动带来的父元素高度坍塌问题,让<ul>
的背景和边框能够正常显示。
特性 / 属性 | 垂直导航条 | 水平导航条 | 目的与解释 |
---|---|---|---|
核心布局 | 依赖 <li> 默认的块级垂直堆叠 |
li { float: left; } |
根本区别:改变列表项的排列方向,从垂直变为水平。 |
父容器处理 | 无特殊处理 | ul { overflow: hidden; } |
关键辅助:清除内部 <li> 浮动造成的高度坍塌问题,确保 <ul> 能包裹住所有 <li> 。 |
尺寸与定位 | width: 25%; position: fixed; height: 100%; |
无(宽度自适应内容) | 垂直导航条案例是固定在页面的侧栏,而水平导航条通常是页面顶部或内部的流动元素,随页面滚动。 |
<a> 标签样式 |
padding: 8px 16px; |
padding: 14px 16px; text-align: center; |
细微的视觉调整。水平导航条通常需要更大的上下 padding 来撑开高度,text-align 确保文字居中。 |
背景与边框 | 背景在<ul> 上 |
背景和边框都在<ul> 上 |
水平导航条通常作为一个整体的“条”,所以背景和边框应用在 <ul> 上更合适。 |
值得注意的是,使用
float
是实现水平布局的传统方法。在现代前端开发中,我们有了更强大、更灵活的工具:
- Flexbox (弹性盒子):这是目前实现一维布局(水平或垂直)的首选方案。只需给父元素
<ul>
设置display: flex;
,其子元素<li>
就会自动水平排列,无需处理浮动带来的副作用。- Grid (网格):用于更复杂的二维布局(同时处理行和列)。
尽管如此,理解
float
布局依然非常重要,因为你需要维护很多旧项目,并且它能帮助你更深刻地理解 CSS 的盒模型和文档流概念。
2 下拉菜单
HTML 部分:
我们可以使用任何的 HTML 元素来打开下拉菜单,如:<span>
, 或 a <button>
元素。
使用容器元素 (如: <div>
) 来创建下拉菜单的内容,并放在任何你想放的位置上。
使用 <div>
元素来包裹这些元素,并使用 CSS 来设置下拉内容的样式。
CSS 部分:
.dropdown
类使用 position:relative
, 这将设置下拉菜单的内容放置在下拉按钮 (使用 position:absolute
) 的右下角位置。
.dropdown-content
类中是实际的下拉菜单。默认是隐藏的,在鼠标移动到指定元素后会显示。 注意 min-width
的值设置为 160px。你可以随意修改它。 注意: 如果你想设置下拉内容与下拉按钮的宽度一致,可设置 width
为 100% ( overflow:auto
设置可以在小尺寸屏幕上滚动)。
我们使用 box-shadow
属性让下拉菜单看起来像一个"卡片"。
:hover
选择器用于在用户将鼠标移动到下拉按钮上时显示下拉菜单。
<!DOCTYPE html>
<html>
<head>
<title>下拉菜单实例|菜鸟教程(runoob.com)</title>
<meta charset="utf-8">
<style>
/* 下拉按钮样式 */
.dropbtn {
background-color: #4CAF50; /* 设置按钮背景色为绿色 */
color: white; /* 设置按钮文字颜色为白色 */
padding: 16px; /* 设置按钮内边距为16px */
font-size: 16px; /* 设置按钮文字大小为16px */
border: none; /* 去除按钮边框 */
cursor: pointer; /* 鼠标悬停时显示手型指针 */
}
/* 下拉菜单容器样式 */
.dropdown {
position: relative; /* 设置为相对定位,作为下拉内容的定位参考 */
display: inline-block; /* 设置为行内块元素,使元素宽度适应内容 */
}
/* 下拉内容样式(默认隐藏) */
.dropdown-content {
display: none; /* 默认隐藏下拉内容 */
position: absolute; /* 设置为绝对定位,相对于父元素定位 */
right: 0; /* 右对齐(可被覆盖) */
background-color: #f9f9f9; /* 设置下拉内容背景色为浅灰色 */
min-width: 160px; /* 设置下拉内容最小宽度为160px */
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); /* 添加阴影效果,增强立体感 */
}
/* 下拉菜单中的链接样式 */
.dropdown-content a {
color: black; /* 设置链接文字颜色为黑色 */
padding: 12px 16px; /* 设置链接内边距,上下12px,左右16px */
text-decoration: none; /* 去除链接下划线 */
display: block; /* 设置为块元素,使链接占满整行 */
}
/* 下拉菜单链接的悬停效果 */
.dropdown-content a:hover {background-color: #f1f1f1} /* 鼠标悬停时背景色变为稍深的灰色 */
/* 当鼠标悬停在下拉容器上时显示下拉内容 */
.dropdown:hover .dropdown-content {
display: block; /* 显示下拉内容 */
}
/* 当鼠标悬停在下拉容器上时改变按钮样式 */
.dropdown:hover .dropbtn {
background-color: #3e8e41; /* 按钮背景色变为深一点的绿色 */
}
</style>
</head>
<body>
<h2>下拉内容的对齐方式</h2>
<p>left 和 right 属性指定了下拉内容是从左到右或从右到左。</p>
<!-- 左侧下拉菜单 -->
<div class="dropdown" style="float:left;">
<button class="dropbtn">左</button>
<div class="dropdown-content" style="left:0;"> <!-- 左对齐下拉内容 -->
<a href="#">菜鸟教程 1</a>
<a href="#">菜鸟教程 2</a>
<a href="#">菜鸟教程 3</a>
</div>
</div>
<!-- 右侧下拉菜单 -->
<div class="dropdown" style="float:right;">
<button class="dropbtn">右</button>
<div class="dropdown-content"> <!-- 使用默认的右对齐 -->
<a href="#">菜鸟教程 1</a>
<a href="#">菜鸟教程 2</a>
<a href="#">菜鸟教程 3</a>
</div>
</div>
</body>
</html>

3 提示工具
HTML: 使用容器元素 (like <div>
) 并添加 “tooltip” 类。在鼠标移动到 <div>
上时显示提示信息。
提示文本放在内联元素上(如 <span>
) 并使用 class=“tooltiptext”。
CSS:
tooltip 类使用 position:relative,提示文本需要设置定位值 position:absolute。
tooltiptext 类用于实际的提示文本。模式是隐藏的,在鼠标移动到元素显示 。设置了一些宽度、背景色、字体色等样式。
border-radius 属性用于为提示框添加圆角。
:hover 选择器用于在鼠标移动到到指定元素 <div>
上时显示的提示。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<style>
.tooltip {
position: relative;
display: inline-block;
border-bottom: 1px dotted black;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 120px;
background-color: black;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px 0;
position: absolute;
z-index: 1;
top: 150%;
left: 50%;
margin-left: -60px;
/* 淡入 - 1秒内从 0% 到 100% 显示: */
opacity: 0;
transition: opacity 1s;
}
.tooltip .tooltiptext::after {
content: "";
position: absolute;
bottom: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent transparent black transparent;
}
.tooltip:hover .tooltiptext {
visibility: visible;
opacity: 1;
}
</style>
<body style="text-align:center;">
<h2>底部提示框/顶部箭头</h2>
<div class="tooltip">鼠标移动到我这
<span class="tooltiptext">提示文本</span>
</div>
</body>
</html>

3.1 HTML 结构
<div class="tooltip">鼠标移动到我这
<span class="tooltiptext">提示文本</span>
</div>
.tooltip
: 这是外层的父容器。它包含了触发提示的文本(“鼠标移动到我这”)和实际的提示框内容。这个容器扮演着两个重要角色:- 触发区域:用户的鼠标需要悬停在这个
<div>
上。 - 定位锚点:它将作为内部提示框
<span>
的定位基准。
- 触发区域:用户的鼠标需要悬停在这个
.tooltiptext
: 这是内层的子元素,也就是真正的提示框。它默认是隐藏的,只有在特定条件下(鼠标悬停在父容器上时)才会显示。
关键点:将提示框 .tooltiptext
嵌套在触发器 .tooltip
内部,是实现这个效果的结构基础。
3.2 CSS 样式
3.2.1 容器样式
.tooltip {
position: relative;
display: inline-block;
border-bottom: 1px dotted black;
}
position: relative;
: 这是整个定位系统的基石。当一个父元素被设置为position: relative
时,它就创建了一个“定位上下文”。这意味着,任何在它内部的、被设置为position: absolute;
的子元素,其位置都将相对于这个父元素进行计算,而不是相对于整个浏览器窗口。在这里,它确保了.tooltiptext
会出现在.tooltip
的附近。display: inline-block;
: 这个属性让<div>
元素既有行内元素(inline
)的特性(不独占一行,可以和文本排在一起),又有块级元素(block
)的特性(可以设置宽度、高度、内边距和外边距)。border-bottom: 1px dotted black;
: 这纯粹是为了美观,给触发文本添加一个虚线样式的下划线,向用户暗示这是一个可交互的元素。
3.2.2 初始隐藏状态
.tooltip .tooltiptext {
/* --- 隐藏与外观 --- */
visibility: hidden;
width: 120px;
background-color: black;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px 0;
/* --- 定位 --- */
position: absolute;
z-index: 1;
top: 150%;
left: 50%;
margin-left: -60px;
/* --- 动画效果 --- */
opacity: 0;
transition: opacity 1s;
}
隐藏与外观:
visibility: hidden;
: 这是隐藏提示框的主要方式。与display: none;
不同,visibility: hidden;
会在页面上保留元素所占的空间,只是让它不可见。这一点对于实现transition
动画至关重要,因为如果用display: none
,元素会直接从渲染树中移除,无法平滑过渡。- 剩下的
width
,background-color
,color
,text-align
,border-radius
,padding
都是基础的样式,用于定义提示框的外观(固定宽度、黑底白字、圆角等)。
定位:
position: absolute;
: 将提示框从正常的文档流中“抽离”出来,使其可以被精确地放置。由于其父元素.tooltip
是position: relative;
,所以它的所有定位都是相对于.tooltip
的。z-index: 1;
: 确保提示框会显示在其他页面元素的上层,不会被遮挡。top: 150%;
: 将提示框的顶部定位在距离其父元素顶部 150% 的位置。100%
意味着紧贴父元素底部,150%
则在下方留出了一些空隙。left: 50%;
和margin-left: -60px;
: 这是一个经典的水平居中技巧。left: 50%;
将提示框的左边界移动到父元素的中心线。margin-left: -60px; 再将提示框向左移动自身宽度(width: 120px;)的一半。
这两步结合起来,就实现了提示框相对于父元素的完美水平居中。
动画效果:
opacity: 0;
: 将元素的透明度设为 0,即完全透明。虽然visibility: hidden;
已经让它看不见了,但opacity
是可以被transition
动画化的属性。transition: opacity 1s;
: 这是实现淡入淡出效果的关键。它告诉浏览器:“请监视opacity
这个属性,如果它的值发生变化,请不要立即改变,而是用 1 秒的时间平滑地过渡到新值。”
3.2.3 绘制小箭头
.tooltip .tooltiptext::after {
content: "";
position: absolute;
bottom: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent transparent black transparent;
}
::after
: 这是一个伪元素,它允许我们在不添加额外 HTML 元素的情况下,在.tooltiptext
内部的末尾创建一个虚拟的子元素。content: "";
: 伪元素必须设置content
属性才能被渲染出来,即使内容为空。position: absolute;
: 箭头也是相对于.tooltiptext
进行定位的。- 定位箭头:
bottom: 100%;
: 将箭头的底部定位在.tooltiptext
的顶部。这样箭头就正好“粘”在了提示框的上面。left: 50%; margin-left: -5px;
: 同样是水平居中技巧,5px
是箭头宽度 (border-width
) 的一半。
- 绘制三角形的魔法:
border-width: 5px;
和border-style: solid;
: 我们创建了一个看不见的、边框宽度为 5px 的小方块。border-color: transparent transparent black transparent;
: 这是最关键的一步。它分别设置了上、右、下、左四个边框的颜色。我们将上、右、左三个边框设为透明 (transparent
),只把下边框 (bottom-border
) 设为黑色。由于边框在角上是斜着交汇的,所以当其他边框都透明时,单独显示的那个下边框就会呈现为一个指向上的三角形。
3.2.4 触发显示
.tooltip:hover .tooltiptext {
visibility: visible;
opacity: 1;
}
:hover
: 这是一个伪类,它会在鼠标指针悬停在元素上时生效。.tooltip:hover .tooltiptext
: 这个选择器的意思是:“当鼠标悬停在.tooltip
元素上时,请选中它内部的.tooltiptext
元素”。visibility: visible;
: 使提示框变为可见。opacity: 1;
: 使提示框的透明度变为 1(完全不透明)。
当鼠标悬停时,opacity
的值从 0
变为 1
。由于我们之前在 .tooltiptext
上设置了 transition: opacity 1s;
,浏览器捕捉到这个变化,并开始执行一个持续 1 秒的、从完全透明到完全不透明的平滑动画,从而实现了优雅的“淡入”效果。当鼠标移开时,opacity
又会从 1
变回 0
,触发“淡出”效果。
4 图片廊
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
div.img {
border: 1px solid #ccc;
}
div.img:hover {
border: 1px solid #777;
}
div.img img {
width: 100%;
height: auto;
}
div.desc {
padding: 15px;
text-align: center;
}
* {
box-sizing: border-box;
}
.responsive {
padding: 0 6px;
float: left;
width: 24.99999%;
}
@media only screen and (max-width: 700px){
.responsive {
width: 49.99999%;
margin: 6px 0;
}
}
@media only screen and (max-width: 500px){
.responsive {
width: 100%;
}
}
.clearfix:after {
content: "";
display: table;
clear: both;
}
</style>
</head>
<body>
<h2 style="text-align:center">响应式图片相册</h2>
<div class="responsive">
<div class="img">
<a target="_blank" href="img_fjords.jpg">
<img src="https://www.runoob.com/wp-content/uploads/2016/04/img_fjords.jpg" alt="Trolltunga Norway" width="300" height="200">
</a>
<div class="desc">Add a description of the image here</div>
</div>
</div>
<div class="responsive">
<div class="img">
<a target="_blank" href="img_forest.jpg">
<img src="https://www.runoob.com/wp-content/uploads/2016/04/img_forest.jpg" alt="Forest" width="600" height="400">
</a>
<div class="desc">Add a description of the image here</div>
</div>
</div>
<div class="responsive">
<div class="img">
<a target="_blank" href="img_lights.jpg">
<img src="https://www.runoob.com/wp-content/uploads/2016/04/img_lights.jpg" alt="Northern Lights" width="600" height="400">
</a>
<div class="desc">Add a description of the image here</div>
</div>
</div>
<div class="responsive">
<div class="img">
<a target="_blank" href="img_mountains.jpg">
<img src="https://www.runoob.com/wp-content/uploads/2016/04/img_mountains.jpg" alt="Mountains" width="600" height="400">
</a>
<div class="desc">Add a description of the image here</div>
</div>
</div>
<div class="clearfix"></div>
<div style="padding:6px;">
<h4>重置浏览器大小查看效果</h4>
</div>
</body>
</html>

4.1 HTML 结构
HTML 的部分为相册建立了基本的骨架,每个相册项目都使用相同的结构。
<div class="responsive">
<div class="img">
<a target="_blank" href="...">
<img src="..." alt="...">
</a>
<div class="desc">...</div>
</div>
</div>
<div class="clearfix"></div>
<div class="responsive">
:这是每个相册项目的最外层容器,主要负责控制排版,决定每个项目占据的宽度和位置。<div class="img">
:这是包覆图片和说明文字的“卡片”,负责加上外框等视觉样式。<a>
和<img>
:标准的图片连结结构。<div class="desc">
:用来放置图片下方的说明文字。<div class="clearfix">
:这是一个看不见的辅助元素,它的作用是“清除浮动”,用来解决因排版产生的布局问题。下面会在 CSS 部分详细说明。
4.2 CSS 样式
CSS 是实现整个响应式效果和样式的核心,以下是几个关键概念的解析。
4.2.1 通用盒模型
* {
box-sizing: border-box;
}
这是现代网页排版中一个非常关键的设定。在预设情况下,一个元素的 width
属性只包含内容的宽度,而 padding
(内边距)和 border
(边框)的宽度会额外加上去,这使得在用百分比设定宽度时,计算会变得很麻烦。
box-sizing: border-box;
改变了这种计算方式,它让 width
属性包含了内容、padding
和 border
的总和。这样做之后,如果你设定一个元素的宽度为 25%
并加上 padding
,它的总宽度仍然会是容器的 25%
,让排版变得直观许多。
4.2.2 核心排版
.responsive {
padding: 0 6px;
float: left;
width: 24.99999%;
}
float: left;
:这个属性让相册项目向左浮动,使它们能在水平方向上一个接一个地排列,而不是预设的垂直堆叠。width: 24.99999%;
:这个设定让每个项目的宽度大约是其父容器的四分之一,从而形成四栏式排版。使用.99999%
而不是整数25%
是一个常见技巧,用来避免某些浏览器的计算误差导致第四个项目被挤到下一行。padding: 0 6px;
:为每个项目左右各加上一点内边距,让图片之间不会紧紧贴在一起。
4.2.3 清除浮动
.clearfix:after {
content: "";
display: table;
clear: both;
}
当你使用 float
属性时,父容器常常会无法正确识别其内部浮动元素的高度,导致自身高度“坍塌”为零,这会影响后续元素的排版。
clearfix 是解决这个问题的标准方法。它透过在最后一个浮动元素的后面放一个空的 div
,并利用 CSS 的伪元素 :after
来清除浮动。
clear: both;
是这里的关键,它命令这个看不见的元素必须移动到所有左、右浮动元素的下方。这个动作会“撑开”父容器,使其能正确地包覆所有浮动项目。
4.2.4 响应式设计
这部分是实现“响应式”效果的关键。Media Queries (@media
) 是一种 CSS 语法,它允许你只在符合特定条件(例如萤幕宽度)时才套用某段 CSS 规则。
/* 适用于萤幕宽度小于等于 700px 的情况 */
@media only screen and (max-width: 700px){
.responsive {
width: 49.99999%; /* 改为两栏 */
margin: 6px 0;
}
}
/* 适用于萤幕宽度小于等于 500px 的情况 */
@media only screen and (max-width: 500px){
.responsive {
width: 100%; /* 改为单栏 */
}
}
max-width: 700px
:当浏览器视窗的宽度小于或等于 700 像素时(例如在平板上),.responsive
的宽度会被改为49.99999%
,相册就会自动重排成两栏式的版面。max-width: 500px
:当视窗宽度进一步缩小到 500 像素或更小时(例如在手机上),宽度会被设为100%
,每个项目占据一整行的空间,形成易于滑动的单栏式列表。
5 图像拼合
图像拼合是一个网页性能优化技术,它将多个小图示(例如导航按钮的不同状态)合并到一张图片中。然后,透过 CSS 的 background-image
和 background-position
属性,像移动一个“视窗”一样,只显示这张大图中的特定部分。好处是,浏览器只需要载入一张图片,而不是多张小图,从而减少了 HTTP 请求,加快了载入速度。
在下面的例子CSS指定显示图像 “img_navsprites.gif” 的一部分:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
img.home {
width: 46px;
height: 44px;
background: url(/images/img_navsprites.gif) 0 0;
}
img.next {
width: 43px;
height: 44px;
background: url(/images/img_navsprites.gif) -91px 0;
}
</style>
</head>
<body>
<img class="home" src="/images/img_trans.gif"><br><br>
<img class="next" src="/images/img_trans.gif">
</body>
</html>

<img class="home" src="img_trans.gif" />
:因为不能为空,src 属性只定义了一个小的透明图像。显示的图像将是我们在 CSS 中指定的背景图像。宽度:46px;高度:44px;
:定义我们使用的那部分图像background:url(img_navsprites.gif) 0 0;
:定义背景图像和它的位置(左0px,顶部0px)
这是使用图像拼合最简单的方法,现在我们使用链接和悬停效果。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
/* --- 导航列整体容器设定 --- */
#navlist {
position: relative; /* 设定为相对定位,作为内部列表项 (li) 绝对定位的基准 */
}
/* --- 导航列中每个项目 (li) 的通用设定 --- */
#navlist li {
margin: 0;
padding: 0;
list-style: none; /* 移除列表预设的小圆点 */
position: absolute; /* 设定为绝对定位,以便我们可以手动、精确地放置每个按钮的位置 */
top: 0; /* 让所有按钮都从容器的顶部开始定位 */
}
/* --- 设定按钮和内部连结的尺寸 --- */
#navlist li, #navlist a {
height: 44px; /* 设定按钮的高度 */
display: block; /* 将连结 (a) 设定为块级元素,使其能填满整个 li 区域,确保整个按钮范围都可点击 */
}
/* --- “主页”按钮 (#home) 的样式 --- */
#home {
left: 0px; /* 从容器最左边开始放置 */
width: 46px; /* 设定按钮的宽度 */
}
#home {
/* 预设状态:使用精灵图,背景位置在 (X:0, Y:0),显示图片最左上角的主页图示 */
background: url('img_navsprites_hover.gif') 0 0;
}
#home a:hover {
/* 滑鼠悬停状态:背景位置变为 (X:0, Y:-45px),也就是将背景图向上移动 45px,显示图片下半部分的悬停效果图示 */
background: url('img_navsprites_hover.gif') 0 -45px;
}
/* --- “上一个”按钮 (#prev) 的样式 --- */
#prev {
left: 63px; /* 从容器左边 63px 处开始放置,与 #home 按钮留出间距 */
width: 43px; /* 设定按钮的宽度 */
}
#prev {
/* 预设状态:背景位置在 (X:-47px, Y:0),也就是将背景图向左移动 47px,显示中间的“上一个”图示 */
background: url('img_navsprites_hover.gif') -47px 0;
}
#prev a:hover {
/* 滑鼠悬停状态:背景位置变为 (X:-47px, Y:-45px),在水平偏移的基础上,再将背景图向上移动 45px */
background: url('img_navsprites_hover.gif') -47px -45px;
}
/* --- “下一个”按钮 (#next) 的样式 --- */
#next {
left: 129px; /* 从容器左边 129px 处开始放置 */
width: 43px; /* 设定按钮的宽度 */
}
#next {
/* 预设状态:背景位置在 (X:-91px, Y:0),将背景图向左移动 91px,显示最右侧的“下一个”图示 */
background: url('img_navsprites_hover.gif') -91px 0;
}
#next a:hover {
/* 滑鼠悬停状态:背景位置变为 (X:-91px, Y:-45px) */
background: url('img_navsprites_hover.gif') -91px -45px;
}
</style>
</head>
<body>
<ul id="navlist">
<li id="home"><a href="default.asp"></a></li>
<li id="prev"><a href="css_intro.asp"></a></li>
<li id="next"><a href="css_syntax.asp"></a></li>
</ul>
</body>
</html>

6 网页布局
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
* {
box-sizing: border-box;
}
body {
font-family: Arial;
padding: 10px;
background: #f1f1f1;
}
/* 头部标题 */
.header {
padding: 30px;
text-align: center;
background: white;
}
.header h1 {
font-size: 50px;
}
/* 导航条 */
.topnav {
overflow: hidden;
background-color: #333;
}
/* 导航条链接 */
.topnav a {
float: left;
display: block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
/* 链接颜色修改 */
.topnav a:hover {
background-color: #ddd;
color: black;
}
/* 创建两列 */
/* Left column */
.leftcolumn {
float: left;
width: 75%;
}
/* 右侧栏 */
.rightcolumn {
float: left;
width: 25%;
background-color: #f1f1f1;
padding-left: 20px;
}
/* 图像部分 */
.fakeimg {
background-color: #aaa;
width: 100%;
padding: 20px;
}
/* 文章卡片效果 */
.card {
background-color: white;
padding: 20px;
margin-top: 20px;
}
/* 列后面清除浮动 */
.row:after {
content: "";
display: table;
clear: both;
}
/* 底部 */
.footer {
padding: 20px;
text-align: center;
background: #ddd;
margin-top: 20px;
}
/* 响应式布局 - 屏幕尺寸小于 800px 时,两列布局改为上下布局 */
@media screen and (max-width: 800px) {
.leftcolumn, .rightcolumn {
width: 100%;
padding: 0;
}
}
/* 响应式布局 -屏幕尺寸小于 400px 时,导航等布局改为上下布局 */
@media screen and (max-width: 400px) {
.topnav a {
float: none;
width: 100%;
}
}
</style>
</head>
<body>
<div class="header">
<h1>我的网页</h1>
<p>重置浏览器大小查看效果。</p>
</div>
<div class="topnav">
<a href="#">链接</a>
<a href="#">链接</a>
<a href="#">链接</a>
<a href="#" style="float:right">链接</a>
</div>
<div class="row">
<div class="leftcolumn">
<div class="card">
<h2>文章标题</h2>
<h5>2019 年 4 月 17日</h5>
<div class="fakeimg" style="height:200px;">图片</div>
<p>一些文本...</p>
<p>菜鸟教程 - 学的不仅是技术,更是梦想!菜鸟教程 - 学的不仅是技术,更是梦想!菜鸟教程 - 学的不仅是技术,更是梦想!菜鸟教程 - 学的不仅是技术,更是梦想!</p>
</div>
<div class="card">
<h2>文章标题</h2>
<h5>2019 年 4 月 17日</h5>
<div class="fakeimg" style="height:200px;">图片</div>
<p>一些文本...</p>
<p>菜鸟教程 - 学的不仅是技术,更是梦想!菜鸟教程 - 学的不仅是技术,更是梦想!菜鸟教程 - 学的不仅是技术,更是梦想!菜鸟教程 - 学的不仅是技术,更是梦想!</p>
</div>
</div>
<div class="rightcolumn">
<div class="card">
<h2>关于我</h2>
<div class="fakeimg" style="height:100px;">图片</div>
<p>关于我的一些信息..</p>
</div>
<div class="card">
<h3>热门文章</h3>
<div class="fakeimg"><p>图片</p></div>
<div class="fakeimg"><p>图片</p></div>
<div class="fakeimg"><p>图片</p></div>
</div>
<div class="card">
<h3>关注我</h3>
<p>一些文本...</p>
</div>
</div>
</div>
<div class="footer">
<h2>底部区域</h2>
</div>
</body>
</html>
