【前端(五)】CSS 知识梳理:浮动与定位

文章目录

  • [1. 浮动](#1. 浮动)
    • [1.1 什么是浮动?](#1.1 什么是浮动?)
    • [1.2 浮动语法与规则](#1.2 浮动语法与规则)
      • [1.2.1 基本语法(float)](#1.2.1 基本语法(float))
      • [1.2.2 浮动元素的位置规则(换行规则)](#1.2.2 浮动元素的位置规则(换行规则))
    • [1.3 解决浮动产生的影响(清除浮动)](#1.3 解决浮动产生的影响(清除浮动))
      • [1.3.1 `clear` 属性](#1.3.1 clear 属性)
      • [1.3.2 五种清除浮动的解决方案](#1.3.2 五种清除浮动的解决方案)
    • [1.4 浮动小练习](#1.4 浮动小练习)
  • [2. 定位](#2. 定位)
    • [2.1 定位概述](#2.1 定位概述)
    • [2.2 相对定位](#2.2 相对定位)
    • [2.3 绝对定位](#2.3 绝对定位)
    • [2.4 固定定位](#2.4 固定定位)
    • [2.5 粘性定位](#2.5 粘性定位)
    • [2.6 定位元素的层叠与居中](#2.6 定位元素的层叠与居中)
      • [2.6.1 层叠上下文](#2.6.1 层叠上下文)
      • [2.6.2 定位元素的水平垂直居中](#2.6.2 定位元素的水平垂直居中)

1. 浮动

前言:

在最初,float 最初的设计目的很简单:实现文字环绕图片的效果 。就像杂志里,一张图片嵌在文字中间,文字会自然地排在图片的四周。虽然现在有更先进的布局方式(如 Flexbox、Grid),但理解浮动依然是掌握 CSS 布局的重要基础。


1.1 什么是浮动?

当一个元素被设置为浮动时,它会脱离普通的文档流,并向左或向右移动,直到它的外边缘碰到包含块(父元素)或另一个浮动元素的边缘。这会导致以下三个核心行为:

  1. "块级化"元素

    • 无论原元素是行内(inline)、行内块(inline-block)还是块级(block),一旦设置 float,它的 display 计算值会变为block。
    • 这意味着 :
      • 可以给它设置 width、height、margin、padding 等块级属性。
      • 关键区别 :
        1. 不独占一行 。浮动元素虽然变成了块级,但它不会像普通块级元素那样独占一行,多个浮动元素可以排列在同一行(空间足够时);
        2. 无外边距塌陷:不会产生传统块级元素的 margin 塌陷或合并问题。
    • 尺寸由内容决定 :如果未设置宽高,元素宽高由内容撑开;如果设置了,则按设置值显示。
  2. "脱离文档流"并影响布局

    浮动元素会从普通的块级文档流中"浮起来",这会导致两个重要的布局影响:

    • 对兄弟元素的影响 :
      • 后面的块级兄弟:会无视浮动元素,占据其原本在文档流中的位置,导致被浮动元素覆盖。
      • 后面的行内/行内块兄弟:会"避让"浮动元素,围绕在它的周围,形成文字环绕效果。
      • 前面的兄弟:无影响。
    • 对父元素的影响 :
      • 高度塌陷 :父元素无法感知浮动元素的高度,导致自身高度变为 0(如果内部没有其他非浮动内容撑开)。
      • 宽度束缚:浮动元素的位置仍受父元素内容区的宽度限制,不会超出父元素边界。

📝 注意:浮动元素会脱离文档流,但不会切断CSS属性的继承链 。通过继承属性(如 font-size、text-align)可以改变浮动元素的内容样式;通过修改父容器尺寸/padding 可以间接改变浮动元素的位置。



1.2 浮动语法与规则

1.2.1 基本语法(float)

通过 float 属性设置浮动:

属性值 描述
left 元素向左浮动
right 元素向右浮动
none 元素不浮动(默认值)

1.2.2 浮动元素的位置规则(换行规则)

当一行宽度不足以容纳所有浮动元素时会换行。其规则是:

  1. 新浮动的元素会先尝试放在上一行所有浮动元素中底部最低点的那一行。
  2. 如果当前行的剩余宽度足够,它就会停在那里。
  3. 如果宽度不够,它会整体下移一行,直到找到一个能容纳它的位置。

代码示例:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .outer{
            height: 333px;
            width: 333px;
            background-color: orange;
            font-size: 22px;
            text-align: center;
            
        }
        .inter{
            height: 111px;
            width: 111px;
            background-color: greenyellow;
            float: right;
        }
        .box2{
            height: 77px;
            width: 77px;
        }
        .box3{
            height: 222px;
            width: 222px;
        }
        .box4{
            height: 11px;
            width: 11px;
        }
    </style>
</head>
<body>
    <div class="outer">
        <div class="inter box1">盒子1</div>
        <div class="inter box2">盒子2</div>
        <div class="inter box3">盒子3</div>
        <div class="inter box4">盒子4</div>
    </div>
</body>
</html>

如图所示,盒子4的位置:


1.3 解决浮动产生的影响(清除浮动)

当浮动导致父元素高度塌陷或影响后续兄弟元素布局时,我们需要"清除浮动"。这里的清除是指清除浮动对其他元素造成的影响。

1.3.1 clear 属性

属性值 描述
none 默认值,允许两侧有浮动元素
left 清除左侧浮动的影响
right 清除右侧浮动的影响
both 清除左右两侧浮动的影响

1.3.2 五种清除浮动的解决方案

方案 实现方式 优点 缺点 推荐度
方案一 给父元素设置固定高度 简单直接 扩展性差,内容变化时需手动调整高度 ❌ 不推荐
方案二 给父元素也设置浮动 简单 会引入新的浮动问题,可能影响更外层的布局 ❌ 不推荐
方案三 给父元素设置 overflow: hidden 简单,无额外标签 可能会隐藏超出父元素边界的内容 ⚠️ 场景受限
方案四 在所有浮动元素后添加一个空的块级元素,并设置 clear:both 原理清晰,兼容性好 添加了额外的无语义标签 ⚠️ 不推荐
方案五 使用父元素的 ::after 伪元素 无额外标签,语义化好,原理清晰 无 ✅ 强烈推荐

方案五:使用 ::after 伪元素(推荐)

这是目前最优雅、最主流的做法。原理是在父元素内容的最后,插入一个看不见的块级元素,并通过 clear:both 清除浮动,从而撑开父元素。

css 复制代码
.clearfix::after {
    content: "";
    display: block; /* 必须是块级元素,clear才生效 */
    clear: both;
}

使用方式:将 clearfix 这个类名添加到任何需要清除浮动的父元素上即可。

💡 深入理解:为什么 overflow: hidden 能清除浮动?

它的本质是创建了一个 BFC(块级格式化上下文)。BFC 是"Block Formatting Context"的缩写,可以理解为页面上一块独立的渲染区域。这块区域有自己的一套布局规则,并且它内部的元素不会影响到外部,外部的元素也不会影响到它内部的布局。

虽然 BFC 很强大,但使用 overflow: hidden 会有一个直接的视觉效果:超出元素边界的内容会被裁剪隐藏。如果你希望父元素有溢出显示(比如下拉菜单),就不适合用 overflow: hidden 来清除浮动。这种情况下,可以用其他创建 BFC 的方式(如 overflow: auto,但会出现滚动条),或者直接用推荐的 clearfix 方案(它不依赖 BFC,而是通过插入清除浮动的元素)。

⚠️ 重要原则:

  • 兄弟元素"全浮或全不浮":这是一个推荐的布局原则,避免复杂的浮动嵌套。如果希望使用浮动布局,通常让一组兄弟元素全部浮动,或者都不浮动,这样逻辑更清晰。如果只有部分元素浮动,非浮动元素可能会被浮动元素覆盖,或出现意外的文字环绕效果,导致布局难以控制。
  • clear 只对块级元素生效:clear 属性只对块级元素有效,对行内元素无效。

为什么 clear 清除浮动必须用在块级元素上?

当浏览器遇到设置了 clear 的块级元素时:检查该元素上方是否有浮动元素。如果有,则在当前元素的 margin-top 之上增加足够的间隙,使元素的上边框刚好位于所有浮动元素下边界的下方。所以clear 属性的设计初衷是通过增加外边距来控制块级元素在布局时的"避让"行为。行内元素与行内块元素不独占一行,在文档流中不参与这种垂直方向上的避让,因此 clear 对行内元素无效。这也就是为什么我们在 clearfix 伪元素中必须设置 display: block 的原因。


1.4 浮动小练习


注意点:

  1. 布局思路
    • 需要左右排列的元素 → 使用浮动(float: left/right)
    • 需要上下排列的元素 → 按正常文档流布局
  2. 公共样式复用
    我们可以预先写好清除浮动和左浮动的工具类,在需要的地方直接引用,减少重复代码:
css 复制代码
.clearfix::after {
    content: "";
    display: block;
    clear: both;
}
.floatleft {
    float: left;
}
  1. 尺寸计算注意事项
    盒子实际占用的宽度 = width + 左右 padding + 左右 border 宽度 。

示例代码:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        body{
            text-align: center;
        }
        .clearfix::after{
            content: "";
            display: block;
            clear: both;
        }
        .floatleft{
            float: left;
        }
        .logo,
        .banner2{
            width: 200px;
        }
        .banner1{
            width: 540px;
            margin: 0 10px;
        }
        .logo,
        .banner1,
        .banner2{
            height: 80px;
            background-color: #ccc;
            line-height: 80px;
        }
        .menu{
            width: 960px;
            height: 30px;
            background-color: #ccc;
            line-height: 30px;
            margin-top:10px;
        }
        .left{
            width: 760px;
            height: 410px;
            margin: 10px 0;
        }
        .module1{
            width: 368px;
            height: 198px;
            margin-bottom: 10px;
        }
        .module2{
            width: 178px;
            height: 198px;
        }
        .module1,
        .module2{
            border: 1px solid black;
            margin-right: 10px;
        }
        .right{
            width: 200px;
            height: 410px;
            margin: 10px 0;
        }
        .module3{
            width: 198px;
            height: 128px;
            border: 1px solid black;
        }
        .middle{
            margin: 10px 0;
        }
        .foot{
            width: 960px;
            height: 60px;
            background-color: #ccc;
            line-height: 60px;
        }
    </style>
</head>
<body>
    <div class="clearfix">
        <div class="logo floatleft">logo</div>
        <div class="banner1 floatleft">banner1</div>
        <div class="banner2 floatleft">banner2</div>
    </div>
    <div class="menu clearfix">菜单</div>
    <div class="clearfix">
        <div class="left clearfix floatleft">
            <div class="module1 floatleft">栏目1</div>
            <div class="module1 floatleft">栏目2</div>
            <div class="module2 floatleft">栏目3</div>
            <div class="module2 floatleft">栏目4</div>
            <div class="module2 floatleft">栏目5</div>
            <div class="module2 floatleft">栏目6</div>
        </div>
        <div class="right floatleft">
            <div class="module3">栏目7</div>
            <div class="module3 middle">栏目8</div>
            <div class="module3">栏目9</div>
        </div>
    </div>
    <div class="foot">页脚</div>
</body>
</html>

2. 定位

2.1 定位概述

CSS 定位允许你从正常的文档流中取出元素,并使它们具有不同的行为。定位主要分为五种:static(静态定位,默认)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和 sticky(粘性定位)。

定位类型 是否脱离文档流 偏移参考系 典型场景 特点记忆点
相对定位 否(占位) 自身原始位置 微调位置、作为绝对定位的容器 "占位演员":人走了,影子还留在原地,不影响周围布局。
绝对定位 是(完全脱离) 最近的非static祖先元素(包含块) 弹窗、下拉菜单、图层覆盖 "隐形人":从画布里抽出来,盖在别人上面,兄弟元素完全无视它。
固定定位 是(完全脱离) 浏览器视口(Viewport) 固定导航栏、返回顶部 "视口钉子":钉在窗户上,页面滚动,它纹丝不动。
粘性定位 否/是(混合) 滚动祖先元素 吸顶导航、滚动边界吸附 "变色龙":平时老实占坑,滚动到阈值就粘住。

2.2 相对定位

  • 语法 :position: relative; 配合 top、right、bottom、left 四个属性使用。
  • 特点 :
    1. 不脱离文档流:元素保留其原始位置,其他元素布局时不会占据该位置。偏移只是视觉上的移动,不会对其他元素产生任何影响。
    2. 偏移参考系 :相对于自身在文档流中的原始位置进行偏移。
    3. 作用 :通常作为绝对定位元素的包含块。

代码示例:

html 复制代码
<style>
  .box {
    width: 100px;
    height: 100px;
    background-color: lightblue;
  }
  .relative-box {
    position: relative;
    top: 20px;
    left: 20px;
    background-color: lightcoral;
  }
</style>
<div class="box">盒子1</div>
<div class="box relative-box">相对定位</div>
<div class="box">盒子3</div>
<!-- 观察:盒子3的位置并没有因为盒子2的偏移而改变,盒子2原来占的空间依然保留 -->

2.3 绝对定位

  • 语法 :position: absolute; 配合 top、right、bottom、left 四个属性使用。
  • 核心概念------包含块 :
    • 对于绝对定位元素,其偏移量是相对于最近的具有非 static 定位的祖先元素 (即 position 值为 relative、absolute、fixed 或 sticky 的祖先)。
    • 如果没有这样的祖先,则相对于初始包含块 (通常是 <html> 元素,即整个页面)。
    • 因此,relative 和 absolute 经常配合使用:给父元素设置 position: relative,使其成为子元素绝对定位的参考系。
  • 特点 :
    1. 完全脱离文档流:元素不再占用原空间,后面的兄弟元素会向上移动,无视它的存在。
    2. 块级化 :行为与浮动类似,display 计算值变为 block,可以设置宽高。
    3. 不避让行内元素:会覆盖在其他元素上方,而行内内容(文字)也不会避让它。
对比维度 浮动 定位(绝对/固定)
对块级兄弟 无视(兄弟从下方穿过) 无视(兄弟完全无视它)
对行内/行内块兄弟 避让(文字环绕) 无视(完全覆盖)
本质 "半脱离":对块级和行内态度截然不同 "全脱离":对任何兄弟都一视同仁(无视)

定位

浮动

代码示例:

html 复制代码
<style>
  .container {
    position: relative; /* 成为包含块 */
    width: 300px;
    height: 200px;
    background-color: lightgray;
    margin: 50px;
  }
  .absolute-box {
    position: absolute;
    bottom: 10px;
    right: 10px;
    width: 100px;
    height: 50px;
    background-color: gold;
  }
</style>
<div class="container">
  这是一个相对定位的容器。
  <div class="absolute-box">绝对定位</div>
</div>

2.4 固定定位

  • 语法 :position: fixed; 配合 top、right、bottom、left 四个属性使用。
  • 特点 :
    1. 完全脱离文档流:行为与绝对定位类似。
    2. 偏移参考系 :相对于浏览器视口(Viewport) 进行定位。即使页面滚动,它也会固定在视口的指定位置。
    3. 块级化 :与绝对定位相同,display 计算值变为 block。
  • 典型场景:固定在页面顶部的导航栏、右下角的"返回顶部"按钮。

2.5 粘性定位

  • 语法 :position: sticky; 通常配合 top 值使用。
  • 特点 :
    1. 混合行为 :在未达到设定的偏移阈值(如 top: 0)前,行为类似相对定位 (占据文档流位置)。当滚动到阈值时,行为类似固定定位(固定在指定位置)。
    2. 偏移参考系 :相对于离它最近的、具有"滚动机制"的祖先元素(即 overflow 不是 visible 的祖先元素)。如果祖先元素没有滚动条,则相对于视口。
    3. 父容器约束:粘性定位元素永远不会超出其父容器的范围。当父容器在滚动方向上离开视口时,粘性元素也会随之离开,不会"粘"在视口外。

代码示例:

html 复制代码
<style>
  .section {
    height: 300px;
    border: 1px solid #ccc;
    margin-bottom: 10px;
    overflow: auto;
  }
  .sticky-header {
    position: sticky;
    top: 0;
    background-color: #333;
    color: white;
    padding: 10px;
  }
</style>
<div class="section">
    <p>开始测试...</p>
    <p>准备开始...</p>
    <div class="sticky-header">我是粘性头部,滚动到顶部会粘住</div>
    <p>这里是很多很多内容...</p>
    <p>或许这里...</p>
    <p>或许这里...</p>
    <p>或许这里...</p>
    <p>或许这里...</p>
    <p>或许这里...</p>
    <p>或许这里...</p>
    <p>或许这里...</p>
    <p>或许这里...</p>
    <p>或许这里...</p>
</div>
<div class="section">另一个区块</div>

2.6 定位元素的层叠与居中

2.6.1 层叠上下文

  • 定位元素的显示层级比普通元素高,后写的元素会盖在先写的元素之上。
  • 可以通过 z-index 属性手动调整定位元素的显示层级。z-index 的值是数字(无单位),值越大,显示层级越高。
  • 注意 :z-index 只在定位元素(position 值非 static)上生效。如果 z-index 设置无效,请检查其所在层叠上下文的层级。

2.6.2 定位元素的水平垂直居中

让绝对/固定定位元素在包含块中水平垂直居中,有两种常用方案。

方案一:margin: auto 法(需设置宽高)

css 复制代码
.parent {
    position: relative; /* 或 absolute/fixed,作为包含块 */
}
.child {
    position: absolute;
    width: 200px;
    height: 100px;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: auto; /* 在四个方向都设置为auto,实现居中 */
}

方案二:transform 平移法(宽高未知也适用)

css 复制代码
.parent {
    position: relative;
}
.child {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%); /* 回退自身宽高的一半 */
}

💡 注意:

  • 对于绝对/固定定位元素,同时设置 left 和 right 为 0 可以让其宽度拉伸至包含块宽度(配合 margin:auto 可居中)。 同时设置 top 和 bottom 为 0 可以拉伸高度。
  • 不建议同时使用 left 和 right 来定位(除非需要拉伸),因为 left 优先级更高,right 会被忽略。top 和 bottom 同理。

以上为个人学习总结,旨在梳理个人理解。如有疏漏或不当之处,欢迎指正与交流。

相关推荐
Highcharts.js8 分钟前
可视化商用图表库对比,如何选择?
前端·javascript·学习·信息可视化·highcharts·前端可视化
TheITSea1 小时前
JavaScript Web APIs
开发语言·前端·javascript
恋猫de小郭1 小时前
Android CLI 支持 AI Agent 通过 Device Streaming 调试云真机
android·前端·flutter
Wang's Blog1 小时前
Java 项目实战: 外卖平台优化-前端dist部署与Nginx反向代理rewrite
java·前端·nginx
鬓戈1 小时前
Claude Code frontend-design 插件调研 与 Vue 旧系统风格一致性方案
前端·vue.js·人工智能
IT_陈寒2 小时前
SpringBoot自动配置的坑我帮你踩过了
前端·人工智能·后端
其实防守也摸鱼2 小时前
网安自测题:掌握核心知识点的实用练习
linux·运维·服务器·前端·数据库·sql·xss
geovindu4 小时前
css: Timeline scribble
前端·css·iphone
沙漠之主12 小时前
C++编程教学设计资料:从入门到实战的完整课程方案
java·前端·c++
hasty12 小时前
不上传新包,也能改变用户拿到的版本:npm dist-tag 的 OIDC 权限治理
前端·npm·node.js