你不知道的 CSS 之 包含块 ! 最细讲解,一听就懂!

你不知道的 CSS 之包含块

一说到 CSS 盒模型,这是很多小伙伴耳熟能详的知识,甚至有的小伙伴还能说出 border-box 和 content-box 这两种盒模型的区别。

但是一说到 CSS 包含块,有的小伙伴就懵圈了,什么是包含块?好像从来没有听说过这玩意儿。

好吧,如果你对包含块的知识一无所知,那么系好安全带,咱们准备出发了。

包含块英语全称为containing block,实际上平时你在书写 CSS 时,大多数情况下你是感受不到它的存在,因此你不知道这个知识点也是一件很正常的事情。但是这玩意儿是确确实实存在的,在 CSS 规范中也是明确书写了的:

CSS 2

image-20220814222458695

并且,如果你不了解它的运作机制,有时就会出现一些你认为的莫名其妙的现象。

那么,这个包含块究竟说了什么内容呢?

说起来也简单,就是元素的尺寸和位置,会受它的包含块所影响。对于一些属性,例如 width, height, padding, margin,绝对定位元素的偏移值(比如 position 被设置为 absolute 或 fixed),当我们对其赋予百分比值时,这些值的计算值,就是通过元素的包含块计算得来。

来吧,少年,让我们从最简单的 case 开始看。

<body><div class="container"><div class="item"></div></div>
</body>
.container{width: 500px;height: 300px;background-color: skyblue;
}
.item{width: 50%;height: 50%;background-color: red;
}

请仔细阅读上面的代码,然后你认为 div.item 这个盒子的宽高是多少?

image-20220814223451349

相信你能够很自信的回答这个简单的问题,div.item 盒子的 width 为 250px,height 为 150px。

这个答案确实是没有问题的,但是如果我追问你是怎么得到这个答案的,我猜不了解包含块的你大概率会说,因为它的父元素 div.container 的 width 为 500px,50% 就是 250px,height 为 300px,因此 50% 就是 150px。

这个答案实际上是不准确的。正确的答案应该是,div.item 的宽高是根据它的包含块来计算的,而这里包含块的大小,正是这个元素最近的祖先块元素的内容区。

因此正如我前面所说,很多时候你都感受不到包含块的存在。

包含块分为两种,一种是根元素(HTML 元素)所在的包含块,被称之为初始包含块(initial containing block)。对于浏览器而言,初始包含块的的大小等于视口 viewport 的大小,基点在画布的原点(视口左上角)。它是作为元素绝对定位和固定定位的参照物。

另外一种是对于非根元素,对于非根元素的包含块判定就有几种不同的情况了。大致可以分为如下几种:

  • 如果元素的 positiion 是 relative 或 static ,那么包含块由离它最近的块容器(block container)的内容区域(content area)的边缘建立。

  • 如果 position 属性是 fixed,那么包含块由视口建立。

  • 如果元素使用了 absolute 定位,则包含块由它的最近的 position 的值不是 static (也就是值为fixed、absolute、relative 或 sticky)的祖先元素的内边距区的边缘组成。

前面两条实际上都还比较好理解,第三条往往是初学者容易比较忽视的,我们来看一个示例:

<body><div class="container"><div class="item"><div class="item2"></div></div></div></body>
.container {width: 500px;height: 300px;background-color: skyblue;position: relative;
}
.item {width: 300px;height: 150px;border: 5px solid;margin-left: 100px;
}
.item2 {width: 100px;height: 100px;background-color: red;position: absolute;left: 10px;top: 10px;
}

首先阅读上面的代码,然后你能在脑海里面想出其大致的样子么?或者用笔和纸画一下也行。

公布正确答案:

image-20220814233548188

怎么样?有没有和你所想象的对上?

其实原因也非常简单,根据上面的第三条规则,对于 div.item2 来讲,它的包含块应该是 div.container,而非 div.item。

如果你能把上面非根元素的包含块判定规则掌握,那么关于包含块的知识你就已经掌握 80% 了。

实际上对于非根元素来讲,包含块还有一种可能,那就是如果 position 属性是 absolute 或 fixed,包含块也可能是由满足以下条件的最近父级元素的内边距区的边缘组成的:

  • transform 或 perspective 的值不是 none

  • will-change 的值是 transform 或 perspective

  • filter 的值不是 none 或 will-change 的值是 filter(只在 Firefox 下生效).

  • contain 的值是 paint (例如: contain: paint;)

我们还是来看一个示例:

<body><div class="container"><div class="item"><div class="item2"></div></div></div>
</body>
.container {width: 500px;height: 300px;background-color: skyblue;position: relative;
}
.item {width: 300px;height: 150px;border: 5px solid;margin-left: 100px;transform: rotate(0deg); /* 新增代码 */
}
.item2 {width: 100px;height: 100px;background-color: red;position: absolute;left: 10px;top: 10px;
}

我们对于上面的代码只新增了一条声明,那就是 transform: rotate(0deg),此时的渲染效果却发生了改变,如下图所示:

image-20220814234347149

可以看到,此时对于 div.item2 来讲,包含块就变成了 div.item。

好了,到这里,关于包含块的知识就基本讲完了。

我们再把 CSS 规范中所举的例子来看一下。

<html><head><title>Illustration of containing blocks</title></head><body id="body"><div id="div1"><p id="p1">This is text in the first paragraph...</p><p id="p2">This is text<em id="em1">in the<strong id="strong1">second</strong>paragraph.</em></p></div></body>
</html>

上面是一段简单的 HTML 代码,在没有添加任何 CSS 代码的情况下,你能说出各自的包含块么?

对应的结果如下:

元素包含块
htmlinitial C.B. (UA-dependent)
bodyhtml
div1body
p1div1
p2div1
em1p2
strong1p2

首先 HTML 作为根元素,对应的包含块就是前面我们所说的初始包含块,而对于 body 而言,这是一个 static 定位的元素,因此该元素的包含块参照第一条为 html,以此类推 div1、p1、p2 以及 em1 的包含块也都是它们的父元素。

不过 strong1 比较例外,它的包含块确实 p2,而非 em1。为什么会这样?建议你再把非根元素的第一条规则读一下:

  • 如果元素的 positiion 是 relative 或 static ,那么包含块由离它最近的块容器(block container)的内容区域(content area)的边缘建立。

没错,因为 em1 不是块容器,而包含块是离它最近的块容器的内容区域,所以是 p2。

接下来添加如下的 CSS:

#div1 { position: absolute; left: 50px; top: 50px 
}

上面的代码我们对 div1 进行了定位,那么此时的包含块会发生变化么?你可以先在自己思考一下。

答案如下:

元素包含块
htmlinitial C.B. (UA-dependent)
bodyhtml
div1initial C.B. (UA-dependent)
p1div1
p2div1
em1p2
strong1p2

可以看到,这里 div1 的包含块就发生了变化,变为了初始包含块。这里你可以参考前文中的这两句话:

  • 初始包含块(initial containing block)。对于浏览器而言,初始包含块的的大小等于视口 viewport 的大小,基点在画布的原点(视口左上角)。它是作为元素绝对定位和固定定位的参照物。

  • 如果元素使用了 absolute 定位,则包含块由它的最近的 position 的值不是 static (也就是值为fixed、absolute、relative 或 sticky)的祖先元素的内边距区的边缘组成。

是不是一下子就理解了。没错,因为我们对 div1 进行了定位,因此它会应用非根元素包含块计算规则的第三条规则,寻找离它最近的 position 的值不是 static 的祖先元素,不过显然 body 的定位方式为 static,因此 div1 的包含块最终就变成了初始包含块。

接下来我们继续修改我们的 CSS:

#div1 { position: absolute; left: 50px; top: 50px 
}
#em1  { position: absolute; left: 100px; top: 100px 
}

这里我们对 em1 同样进行了 absolute 绝对定位,你想一想会有什么样的变化?

没错,聪明的你大概应该知道,em1 的包含块不再是 p2,而变成了 div1,而 strong1 的包含块也不再是 p2 了,而是变成了 em1。

如下表所示:

元素包含块
htmlinitial C.B. (UA-dependent)
bodyhtml
div1initial C.B. (UA-dependent)
p1div1
p2div1
em1div1(因为定位了,参阅非根元素包含块确定规则的第三条)
strong1em1(因为 em1 变为了块容器,参阅非根元素包含块确定规则的第一条)

好了,这就是 CSS 规范中所举的例子。如果你全都能看明白,以后你还能跟别人说你是看过这一块知识对应的 CSS 规范的人。

另外,关于包含块的知识,在 MDN 上除了解说了什么是包含块以外,也举出了很多简单易懂的示例。

具体你可以移步到:布局和包含块 - CSS:层叠样式表 | MDN

好了,这就是有关包含块的所有内容了,你学会了么?-)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/593194.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

devops使用+vscode使用

官方文档 使用 Git 进行代码 - Azure DevOps | Microsoft Learn 用ssh远程连接服务器debug 在插件中搜索SSH &#xff0c;具体步骤可以参考以下步骤 https://cloud.tencent.com/developer/article/1840922

Flutter 混合开发 - 动态下发 libflutter.so libapp.so

背景 最近在做包体积优化&#xff0c;在完成代码混淆、压缩&#xff0c;裁剪ndk支持架构&#xff0c;以及资源压缩&#xff08;如图片转webp、mp3压缩等&#xff09;后发现安装包的中占比较大的仍是 so 动态库依赖。 具体查看发现 libflutter.so 和 libapp.so 的体积是最大的&…

基于SpringBoot的图书电子商务网站的设计与实现

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于SpringBoot的图书电子商务网站的设计…

LobeChat:搭建你的私人 GPT!

前端训练营&#xff1a;1v1私教&#xff0c;终身辅导计划&#xff0c;帮你拿到满意的 offer。 已帮助数百位同学拿到了中大厂 offer。欢迎来撩~~~~~~~~ Hello&#xff0c;大家好&#xff0c;我是 Sunday。 之前有同学问我&#xff1a;“老师&#xff0c;我想要搭建一个个人的 …

2024.1.2C语言 结构

一.结构的定义 1.概念 在C语言中&#xff0c;结构是一种用户自定义的数据类型&#xff0c;它允许您将多个不同类型的数据组合成一个单一的数据类型,如 struct student {int num;//学号char name[10];//姓名int computer, english, math;//3门课程成绩double average;//个人平…

《编程之光:解密ECMAScript与JavaScript的微妙关系》

目录 1. ECMAScript&#xff1a;光芒背后的规范2. JavaScript&#xff1a;语言的真实承载者3. 为何关系微妙&#xff1f;4. 编程之光的启示结尾&#xff1a; 标题&#xff1a;《编程之光&#xff1a;解密ECMAScript与JavaScript的微妙关系》 在前端开发的世界中&#xff0c;ECM…

搞懂flyaway一篇就够了

Flyway是一个用于数据库迁移的开源工具,它可以帮助开发人员轻松地管理数据库架构的变化。Flyway通过迁移来更新数据库,迁移可以使用特定于数据库的SQL语法或者用于高级数据库转换的Java编写。Flyway支持两种类型的迁移:有版本的迁移和可重复的迁移。有版本的迁移具有唯一的版…

Python编写API接口

本文将从以下几个方面详细阐述Python编写API接口的方法和技巧&#xff0c;希望能够对开发工程师们有所帮助&#xff1a; 一、API接口的基本概念 API全称为Application Programming Interface&#xff0c;是一种应用程序接口&#xff0c;可让不同的程序之间进行交互。API接口通…

TDD-LTE 附着流程和去附着流程

目录 1. 附着流程 1.1. 正常附着流程 2. 异常附着流程 2.1 RRC建立失败 2.2 核心网拒绝 2.3 eNodeB未收到初始化上下文建立请求 2.4 RRC重配置请求丢失 2. 去附着流程 2.1 非关机去附着流程 2.1.1 连接态非关机去附着 2.1.2 空闲态非关机去附着 2.2 关机去附着流程 …

实战Keras3.0:自定义图片数据集分类任务

一、创建自定义图片数据集 1、数据收集 以10张小狗图片和10张小猫图片为例 2、数据预处理 1、创建Excel表格&#xff0c;并在其中创建两列&#xff0c;一列是图片路径&#xff0c;另一列是对应的标签&#xff08;狗0、猫1&#xff09; 2、用pandas库的read_excel函数读取Exc…

java企业人事信息管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web企业人事信息管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境 为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为M…

【学习记录23】Linux环境下安装nginx

自己折腾了个服务器在上面跑前端项目&#xff0c;记录一下以备后期查询&#xff0c;为了省钱每年都换一次云服务器。。。每次都得重装各种东西&#xff01;&#xff01;&#xff01; 1、安装所需环境 //安装gcc yum install gcc-c//安装PCRE pcre-devel yum install -y pcre …

Python-单行赋值的执行顺序

一般情况下&#xff0c;python 的元组赋值可以当作没有顺序&#xff1a; a, b 1, 2 a Out[3]: 1 b Out[4]: 2 但是如果交换的变量存在关联&#xff0c;元组赋值就是有顺序的&#xff1a; a, b b, a a, b Out[6]: (2, 1) 结果是a,b的值交换了顺序。如果按照&#xff1a; …

RTC第二个功能和应用程序

一般RTC模块设备管理时间日历、计时器等。从年到二。一些爱普生RTC 模块可以通过使用来自32768 Hz的分割频率来管理次第二功能。本文件 描述了RTC模块的三个具体的应用程序。&#xff08;表1&#xff09; 表1中的功能和产品 [FOUT函数应用程序] 图1描述了RTC模块&#xff0…

springboot项目maven install 失败提示unable to rename “*.jar“ to “*.jar.original“

项目场景&#xff1a; 项目作为springcloud项目&#xff0c;安装包的打包一直使用的是idea中 maven->lifestyle->install 问题描述 今天打包的时候报错&#xff1a;unable to rename “*.jar” to “*.jar.original” 而且打包出来的jar包的大小明显小了 原因分析&…

iOS和iPadOS设备启动到打开App

一、设备启动过程 启动过程每个步骤包含的组件都经 Apple 加密签名以启用完整性检查&#xff0c;因此只有在验证信任链后&#xff0c;启动才能继续&#xff1b; 这些组件包括引导载入程序、内核、内核扩展项和蜂窝网络基带固件&#xff1b; 这一安全启动链的设计旨在验证软件的…

Python数据挖掘与机器学习实践技术应用

近年来&#xff0c;Python编程语言受到越来越多科研人员的喜爱&#xff0c;在多个编程语言排行榜中持续夺冠。同时&#xff0c;伴随着深度学习的快速发展&#xff0c;人工智能技术在各个领域中的应用越来越广泛。机器学习是人工智能的基础&#xff0c;因此&#xff0c;掌握常用…

qt .pro工程转vs工程

1. 新建vs空项目或者Qt Console Application&#xff1b; 2. 扩展 -》Qt VS Tools -》Open Qt Project (.pro) 打开对应的pro文件即可将.pro工程转成vs工程&#xff1b; 注意&#xff1a; &#xff08;1&#xff09;转成的vs工程在pro文件同级目录下&#xff0c;双击打开vcx…

网络通信(7)-TCP协议解析

目录 一、定义 二、主要特点 三、报文格式 四、工作方式

科兴未来|中国北京 · HICOOL 2024全球创业大赛招募启动

HICOOL 2024全球创业大赛正式启动&#xff0c;我们诚挚地邀请来自世界各地的创业项目报名参赛&#xff0c;在全球舞台上展示自己&#xff0c;加速成长。 一、参赛收获 大赛将为获奖项目提供包括人才落户、子女教育、医疗保障等在内的创业政策支持。此外&#xff0c;参赛项目将…