2025-09-05 CSS5——常见实现

发布于:2025-09-06 ⋅ 阅读:(12) ⋅ 点赞:(0)

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>
image-20250905012409251
  • 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>
image-20250905012948317

好的,非常乐意以一位前端专家的身份,为你详细解析这段关于垂直导航栏实现的代码案例。

这是一个非常经典和基础的前端教学案例,它循序渐进地展示了如何从一个普通的 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)。它的宽度只由其内部的文字决定,并且你无法设置其 widthheight。点击区域也仅限于文字本身。
    • 将其设置为 块级元素 (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>
image-20250905014345247

这个案例中,实现水平布局的关键在于两个 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>
image-20250905015309594

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>
image-20250905020659186

3.1 HTML 结构

<div class="tooltip">鼠标移动到我这
  <span class="tooltiptext">提示文本</span>
</div>
  • .tooltip: 这是外层的父容器。它包含了触发提示的文本(“鼠标移动到我这”)和实际的提示框内容。这个容器扮演着两个重要角色:
    1. 触发区域:用户的鼠标需要悬停在这个 <div> 上。
    2. 定位锚点:它将作为内部提示框 <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;: 将提示框从正常的文档流中“抽离”出来,使其可以被精确地放置。由于其父元素 .tooltipposition: relative;,所以它的所有定位都是相对于 .tooltip 的。

    • z-index: 1;: 确保提示框会显示在其他页面元素的上层,不会被遮挡。

    • top: 150%;: 将提示框的顶部定位在距离其父元素顶部 150% 的位置。100% 意味着紧贴父元素底部,150% 则在下方留出了一些空隙。

    • left: 50%;margin-left: -60px;: 这是一个经典的水平居中技巧

      1. left: 50%; 将提示框的左边界移动到父元素的中心线。

      2. 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>
image-20250905020758554

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 属性包含了内容、paddingborder 的总和。这样做之后,如果你设定一个元素的宽度为 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-imagebackground-position 属性,像移动一个“视窗”一样,只显示这张大图中的特定部分。好处是,浏览器只需要载入一张图片,而不是多张小图,从而减少了 HTTP 请求,加快了载入速度。

在下面的例子CSS指定显示图像 “img_navsprites.gif” navigation images的一部分:

<!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>
image-20250905022231779
  • <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>
image-20250905022402669

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>
image-20250905022813641

网站公告

今日签到

点亮在社区的每一天
去签到