热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

CSS2.1SPEC:视觉格式化模型之包含块

CSS2.1SPEC:视觉格式化模型之包含块
原汁原味的才是最有味道的,在阅读CSS标准时对这一点的体会更加深刻了,阅读文档后的一大感觉就是很多看上去理所应当的样式表现也都有了对应的支持机制。本文首先从包含块写起,一方面总结标准中相应的阐述,并且结合具体的实例进行具体分析,特别是对于CSS2.1支持并不完善的IE6/7。由于经验尚浅,文中肯定存在一些问题,希望大家可以多多包涵并且指出问题。

阅读本文前,应当对于CSS盒模型以及视觉格式化模型中会产生的各种框(box,也可以成为盒子)以及各种不同的布局方式有比较准确的认识,可以阅读杜瑶大神的两篇文章,这两篇文章也是对标准中相关章节的翻译和阐述。

(1) 视觉格式化模型中的各种框

(2) 置换和非置换元素

或直接阅读CSS2.1 SPEC中的相关章节:

(1) Box model

(2) Visual formatting model

在讲包含块之前还是想先简单说一下视觉格式化模型

1、CSS视觉格式化模型

标准中对于视觉格式化模型的阐述为:

how user agents process the document tree for visual media.

即用户代理在视觉媒体下如何处理文档树,用户代理最常见的比如浏览器,而负责页面解析和渲染的就是浏览器的渲染引擎(现在更多地直接称为浏览器内核),文档既可以包括HTML文档,也包括其他通用标记语言所编写的文档。在视觉格式化模型中,文档树中的每个元素都会根据盒模型产生0个或多个框,影响这个框的布局的因素有:

(1)框的尺寸和类型,比如块级框和行内级框的布局方式就是不同的。

(2)框的定位方式,display属性绝对了一个元素所产生的框的定位方式,定位方式不同的框在布局时也有不同的规则。

(3)与其他框的关系,假如有两个框,它们之间是包含关系还是同辈关系而所产生的布局是不相同的。

(4)其他的额外信息(比如视口的大小,置换元素的固有尺寸等)

从这个角度讲,视觉格式化模型就是对上述这些因素是如何影响一个框的布局而进行的详细描述。

2、视口(viewport)

第一部分中出现了视口这个词,直观上看,我觉得视口可以理解为用户代理用来呈现解析和渲染后的文档树的区域,用户通过这个区域可以阅读文档得内容,在浏览器中,视口一般就是浏览器用于呈现网页的区域。

标准中对于视口的阐述为:

User agents for continuous media generally offer users a viewport (a window or other viewing area on the screen) through which users consult a document.

注意加粗的continuous media,我们平时所浏览的网页就属于连续媒体,而通过打印机打印的文档内容必须是分页的,所以就是分页媒体,即paged media(此处的解释略粗糙,仅是个人的简单看法)。网页是连续的媒体,那么问题就来了,视口不可能跟随网页的大小而变化,因此视口在小于文档的尺寸时,必须提供一种滚动机制,最常见的就是浏览器的滚动条,通过滚动条我们就可以浏览超出视口的文档部分,也就是文档中阐述的:

When the viewport is smaller than the area of the canvas on which the document is rendered, the user agent should offer a scrolling mechanism.

当然关于视口的知识点可不只是上述的这么简单,比如在移动web中,viewport的相关属性对于移动web的开发至关重要,但本文暂不涉及其他关于视口的知识点。

3、包含块(containing block)

一个网页是由一个一个的框(box)所组成的,每一个框在页面中都有自己的尺寸、位置以及其他的渲染属性(如背景色,字体等),那么这些框在布局的时候,它们的位置是如何决定的呢?另外,如果没有为框定义显示的尺寸(width,padding,border,margin)等,那么它们的尺寸又是如何确定的呢?答案的关键点就是包含块,个人认为,包含块是学习CSS布局时基础中的基础,不过还好,这个概念也并不难理解。

首先看一下标准中对于包含块的阐述:

The position and size of an element's box(es) are sometimes calculated relative to a certain rectangle, called the containing block of the element.

即视觉格式化模型中所产生的各种框,它们的位置和大小往往都是根据一个特定的矩形框边缘来计算得到的, 这个矩形框就是这个box的包含块。

注:如果讲一个框的包含块时,指的是它所处的包含块,而不是它形成的包含块。

那么该如何确定一个框的包含块呢?标准中规定了相应的规则:

3.1根元素的包含块

根元素(HTML中就是html标签)的包含块称为初始包含块:对于连续媒体(比如网页),它具有视口的尺寸并且定位在画布的原点(可以直观理解为视口的内容起始位置,如果初始包含块的direction属性为ltr,那么起点位置就是视口的左上角,如果为rtl,那么就为视口的右上角)。初始包含块的direction与根元素的direction属性相同,默认为ltr,即从左到右。

特别注意:初始包含块具有视口的尺寸,也就是说宽高都是和视口相同的,即使视口中出现了滚动

3.2元素定位为static(默认值)或relative(相对布局)时的包含块


对于定位属性为static(默认值)或relative(相对布局)的元素,其包含块是由最近的祖先块容器框的内容区域构成。

这一点也比较好理解,虽然出现了块容器框和内容区域两个词,对于CSS盒模型和视觉格式化模型中的各种框有所了解后应该就能明白。下面有个简单的例子:

##DEMO 1:static或relative定位的元素的包含块

CSS代码:

.container{
width: 1000px;
margin: 50px auto;
border: 2px solid #000000;
padding: 50px;
}
      

HTML代码:

       
<p class="container" style="">
<p class="static-p-1" style="background: #CCCCCC;">
static定位的元素
p>
p>
带黑色边框的container有50px的padding,可以看到class为static-p-1元素是基于container的内容区域(content area)来定位的,这一点IE6/7也都是遵循标准的。


3.3元素定位为absolute时的包含块

对于position为absolute的元素,其包含块为最近的拥有非static定位属性(即position为relative,absolute或fixed)的元素所产生,有下面两种情况:

<1>如果这个元素为一个块容器框元素,那么包含块由这个元素的内边距边界(padding edge)形成

<2>如果这个元素是一个行内元素,那么这个包含块由包围该行内级元素的第一个行框和最后一个行框的box形成。如果行内元素被分割成了多行,那么在CSS2.1中,包含块则是未定义的。

如果没有这样的祖先,那么其包含块就是初始包含块

注:在分页媒体中包含不一样的情况,本文暂不讨论分页媒体中的情况

absolute的情况相对复杂一些,看以下例子:

##DEMO 2:绝对定位元素的包含块(1)-块容器框形成包含块

CSS代码:

.container{
width: 1000px;
margin: 50px auto;
border: 2px solid #000000;
padding: 50px;
position: relative;
}
.absolute-p-1{
position: absolute;
left: 0px;
top: 0px;
}
HTML代码:

<p class="container">
<p class="absolute-p-1">
absolute定位的元素
p>
p>
效果如下:

可以看到,absolute-p-1的元素是绝对定位,并且定位起点为左侧0px,上部0px,虽然container有50px的padding,但由于绝对定位的元素是根据块容器框的padding edge来定位,所以absolute-p-1还是紧贴左上角显示。

##DEMO 3:绝对定位元素的包含块(2)-行内元素形成包含块

DEMO3中,我们把container换成行内元素span,为了更明显地显示效果,我们给body加了一个高度并且设置了背景色,并且为span和absolute-p-1设置了不同的字体颜色,代码如下

CSS代码:

body{
margin: 0px;
font-size: 14px;
height: 500px;
background: #a0b3d6;
}
.container{
margin: 50px auto;
position: relative;
color: #eeeeee;
}
.absolute-p-1{
position: absolute;
color: #ff0000;
left: 0px;
top: 0px;
}

HTML代码:

<span class="container">
行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块
行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含
行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含
行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含
<p class="absolute-p-1">
absolute定位的元素
p>
span>
      

效果:

在IE6/7中效果也相同,另外我们提到过,如果元素是一个行内级元素,那么这个包含块由包围该行内级元素的第一个行框和最后一个行框的box形成。我们来验证标红部分的阐述,即把absolute-p-1的top定位改为bottom,即bottom:0px,效果如下:

这也验证了标准中所阐述的内容。

注:在IE6中,绝对定位元素如果只用bottom定位,但是形成包含块的元素没有触发hasLayout时,bottom不会根据包含块的底部来定位,这个bug通过zoom:1等属性触发hasLayout可以解决。

##DEMO 4:绝对定位元素的包含块(4)-行内元素被分割成多行时

视觉格式化模型中描述过,如果一个行内级元素包含了块级元素,那么这个行内级元素就会被分割成2块,并且都成为了块级元素。我们把DEMO3中的container改动一下:

<span class= "container">

    行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块
行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含
<p style="background: #eeeeee">中间出来了一个pp>
<p class="absolute-p-1">
absolute定位的元素
p>
行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含
行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含
span>
此时的效果在不同的浏览器中存在差异:IE6+和firefox中的效果为:

而chrome中的效果为:

可以看出,chrome中的绝对定位元素在定位时是基于被分割后形成的第二个框来定位的,而如果我们把绝对定位元素移动到分割元素之前,即:

<span class="container">
行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块
行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含
<p class="absolute-p-1">
absolute定位的元素
p>
<p style="background: #eeeeee">中间出来了一个pp>
行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含
行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含块行内级包含
span>
      

那么chrome中的效果就成了:

              
      

可见,chrome中的位置是与绝对定位元素在代码中的位置相关的。

##DEMO 5:绝对定位元素的包含块(4)-初始包含块作为包含块

如果一个绝对定位元素找到有非static定位属性的祖先,那么初始包含块就作为其包含块,这里需要注意的是初始化包含块的尺寸问题,2.1节中曾经讲过初始包含块具有视口的尺寸,即使存在滚动时,DEMO代码如下:

CSS代码:为了出现滚动,我们为body加了1000px的高度

.body-for-demo4{
height:1000px;
background: #a0b3d6;
}
.absolute-p-2{
    height: 100px;
width: 100px;
background: #03a9f4;
position: absolute;
bottom: 0px;
left:0px;
}
HTML代码:
      

<body class="body-for-demo4">
<p class="absolute-p-2">
p>
body>

效果如下:      


可以看到,虽然body的高度超出了初始包含块使得滚动条出现,但是初始包含块的尺寸时没有发生改变的。       

如果我们把body设置一个position:relative的属性,那么绝对定位框就会跑到页面底部了。


2.4元素定位为fixed时的包含块

元素定位属性为fixed时,对于连续媒体,包含块由视口形成,对于分页媒体,则由页面区域形成。

position为fixed的元素特点是不随页面的滚动而滚动,它的包含块由视口形成,这一点也比较好理解。但是IE6不支持fixed的属性,可以使用css表达式或者hack的方式使IE6支持fixed。可参考:

http://caibaojian.com/468.html


另外CSS2.1标准的原文第10章第1节中也有包含块的示例,标准中的示例更加基础,同样也可以参考。        
推荐阅读
  • CSS|网格-行-结束属性原文:https://www.gee ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • css元素可拖动,如何使用CSS禁止元素拖拽?
    一、用户行为三剑客以下3个CSS属性:user-select属性可以设置是否允许用户选择页面中的图文内容;user-modify属性可以设置是否允许输入 ... [详细]
  • javascript  – 概述在Firefox上无法正常工作
    我试图提出一些自定义大纲,以达到一些Web可访问性建议.但我不能用Firefox制作.这就是它在Chrome上的外观:而那个图标实际上是一个锚点.在Firefox上,它只概述了整个 ... [详细]
  • 深入理解CSS中的margin属性及其应用场景
    本文主要介绍了CSS中的margin属性及其应用场景,包括垂直外边距合并、padding的使用时机、行内替换元素与费替换元素的区别、margin的基线、盒子的物理大小、显示大小、逻辑大小等知识点。通过深入理解这些概念,读者可以更好地掌握margin的用法和原理。同时,文中提供了一些相关的文档和规范供读者参考。 ... [详细]
  • 如何在HTML中获取鼠标的当前位置
    本文介绍了在HTML中获取鼠标当前位置的三种方法,分别是相对于屏幕的位置、相对于窗口的位置以及考虑了页面滚动因素的位置。通过这些方法可以准确获取鼠标的坐标信息。 ... [详细]
  • 本文介绍了响应式页面的概念和实现方式,包括针对不同终端制作特定页面和制作一个页面适应不同终端的显示。分析了两种实现方式的优缺点,提出了选择方案的建议。同时,对于响应式页面的需求和背景进行了讨论,解释了为什么需要响应式页面。 ... [详细]
  • 分享css中提升优先级属性!important的用法总结
    web前端|css教程css!importantweb前端-css教程本文分享css中提升优先级属性!important的用法总结微信门店展示源码,vscode如何管理站点,ubu ... [详细]
  • 本文介绍了一种图片处理应用,通过固定容器来实现缩略图的功能。该方法可以实现等比例缩略、扩容填充和裁剪等操作。详细的实现步骤和代码示例在正文中给出。 ... [详细]
  • ECMA262规定typeof操作符的返回值和instanceof的使用方法
    本文介绍了ECMA262规定的typeof操作符对不同类型的变量的返回值,以及instanceof操作符的使用方法。同时还提到了在不同浏览器中对正则表达式应用typeof操作符的返回值的差异。 ... [详细]
  • 使用chrome编辑器实现网页截图功能的方法
    本文介绍了在chrome浏览器中使用编辑器实现网页截图功能的方法。通过在地址栏中输入特定命令,打开控制台并调用命令面板,用户可以方便地进行网页截图操作。 ... [详细]
  • 本文介绍了网页播放视频的三种实现方式,分别是使用html5的video标签、使用flash来播放以及使用object标签。其中,推荐使用html5的video标签来简单播放视频,但有些老的浏览器不支持html5。另外,还可以使用flash来播放视频,需要使用object标签。 ... [详细]
  • 如何压缩网站页面以减少页面加载时间
    本文介绍了影响网站打开时间的两个因素,即网页加载速度和网站页面大小。重点讲解了如何通过压缩网站页面来减少页面加载时间。具体包括图片压缩、Javascript压缩、CSS压缩和HTML压缩等方法,并推荐了相应的压缩工具。此外,还提到了一款Google Chrome插件——网页加载速度分析工具Speed Tracer。 ... [详细]
  • 本文整理了常用的CSS属性及用法,包括背景属性、边框属性、尺寸属性、可伸缩框属性、字体属性和文本属性等,方便开发者查阅和使用。 ... [详细]
  • 本文介绍了Cocos2dx学习笔记中的更新函数scheduleUpdate、进度计时器CCProgressTo和滚动视图CCScrollView的用法。详细介绍了scheduleUpdate函数的作用和使用方法,以及schedule函数的区别。同时,还提供了相关的代码示例。 ... [详细]
author-avatar
KTone
敲一夜代码,流下两三行泪水,掏空四肢五体,六杯咖啡七桶泡面,还有八个测试九层审批,可谓十分艰难
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有