深入理解行内元素的布局

前言

总括: 本文通过实例讲解CSS中最大的难点之一,行内元素的布局,主要是挖掘line-height和vertical-align两个属性在布局方面的使用。

白茶清欢无别事,我在等风,也在等你。?

正文

讲道理line-height和vertical-align 这对基是十分低调的,日常开发中碰到的很多莫名其妙的bug很大一部分都是这俩货搞出来了的,但很少有人知道这对基的罪恶,因为可能花式改写一下CSS代码问题就解决了。实际上搞明白这俩东西才能让我们在布局工作中游刃有余。本文接下来就通过这对基的关系来了解内联元素具体的布局问题~we are刨根问底拦不住~?

? 读这篇文章之前请确定您有以下知识基础:

  • line-height的数字值是和font-size大小相关的;
  • vertical-align的百分比值是和line-height值相关的;

引出vertical-align

首先来看一个?:

<div class="test">
  <img src="https://sfault-avatar.b0.upaiyun.com/344/542/3445428434-5631776c183b2_huge256" ><span>Xx</span>
</div>
.test {
      background: red;
}
img {
    width: 50px;
    height: 50px;
}
span {
    background: white;
}

下面无实例内容的话戳这里

<script async src="https://jsfiddle.net/Damonare...;></script>

? 如上代码片段result所示,图片下面有一明显的红色条条,?什么鬼,很诡异不是么,我要的是img充满整个div啊!!!好吧,我加了一个额外的inline元素填写内容Xx,发现原来多出来的那一块正好是文字的下半空白部分。吆喝,这么巧?实际上,如果将这里的Xx内容去掉,只剩下img,那个条条依然存在,表现行为好像父元素div里面除了img元素还有一个空白的元素一样,?姑且叫它空白节点吧(肉眼中不存在却在影响着布局),这个是比较诡异的一个表现,查标准没找到有相关的说明。但请将这个空白节点先记住,我们的重点是研究条条是咋出来的。这条条看上去貌似是文本和图片垂直方向上对齐生成的,那么这就引粗来一个问题,inline元素默认的垂直方向的对齐方式是什么样的?也就是vertical-align的默认值是啥?

? OK,?I know you know。vertical-align默认值是baseline,OK,那就先来挖一挖vertical-align具体是个什么鬼。

Vertical-align(1)

vertical-align这个属性我感觉是CSS中最复杂的属性之一了...好多问题概念也让人看不懂...一方面它是作用在inline元素和table-cell元素身上,属性值特别多,另一方面该属性规范里并没有一个定论,导致一些属性不同浏览器的实现也不同,所以兼容性问题很多。对于一些 可替换元素,比如textarea, HTML标准没有说明它的基线,这意味着对其使用这个关键字,各浏览器表现可能不一样。我们这里先研究一下它的默认值baseline。

baseline字面意思就是基线,何为基线?首先请记住下面这几个概念:

  • 基线:小写字母‘x‘的下边缘所在的那条线;
  • x-height: 小写字母‘x‘的高度;
  • ex: 1ex就是一个小写字母‘x‘的高度,类似em单位,注意,ex和em都是相对单位;

我们看下CSS标准里怎么说的:相关标准链接

The baseline of an ‘inline-block‘ is the baseline of its last line box in the normal flow, unless it has either no in-flow line boxes or if its ‘overflow‘ property has a computed value other than ‘visible‘, in which case the baseline is the bottom margin edge.

中文翻译如下:

‘inline-block‘元素的基线是标准流中最后一个line box(行盒)的基线, 除非这个line box里面既没有in-flow line boxes(行内框)或者本身’overflow’属性的计算值不是’visible’, 这种情况下基线是该元素margin底边缘。

那么上面现象就很容易解释的通了,我们知道img元素默认的表现形式和inline-block元素一样,它的基线就是margin底边缘,而inline元素本身是有高度的,两者基线对齐自然就如上面那样表现了。?

?好吧,等会,到这里,我们发现实际又多了俩概念——inline元素的高度问题标准里说的line box(IFC)。

首先我们先来看下inline元素的高度问题,即——line-height属性。

Line-height

CSS中起高度作用的只有height和line-height两个属性吧。如果一个元素没设置height那么其最终的高度一定是由line-height决定的。之前inline元素的高度我以为是文字内容撑开的,但实际研究了下并不是这样的,看下面的?:

.demo1{
  font-size: 20px;
  line-height: 0;
  border: 1px solid blue;
  background: red;
}
.demo2{
  font-size: 0;
  line-height: 20px;
  border: 1px solid red;
  background: yellow;
}

HTML代码:

<div class="demo1">测试</div>
<div class="demo2">测试</div>

下面没内容戳这或者自行拷贝代码本地测试

<script async src="https://jsfiddle.net/Damonare...;></script>

如上可证明,inline元素的高度决定者是line-height,并不是文字内容撑开的。??

CSS规范里对line-height的默认值有这么一句话:

We recommend a used value for ‘normal‘ between 1.0 to 1.2.

只是推荐...?是不是说实际上各个浏览器对于line-height的默认值实现不一定是一样的,但都介于1.0-1.2之间。具体各大浏览器的实现值待查证。这里需要记住line-height的默认值是啥就OK。

IFC

在之前的博文CSS的盒子模型里面,有拓展过相关知识,简短的介绍了下BFC和IFC,相较于BFC,IFC要复杂得多,规范里IFC的篇幅也要比BFC多得多。

简要总结下BFC,即块级元素可能会触发块级格式上下文(BFC),在块级格式上下文中,块级盒子竖直方向排列,不受上下文外部元素影响,自成一方世界。块容器盒指的是那些包含元素的盒子,块容器盒可能包含其它块级盒,也可能生成一个行内格式上下文(IFC)。?

但块容器盒要么只包含行内盒,要么只包含块级盒。但通常会同时包含两者。在这种情况下,将创建匿名块盒来包含毗邻的行内级盒。

看个?:

//demo1
<div>
  Some inline text
  <p>followed by a paragraph</p>
  followed by more inline text.
</div>
// demo2
<p>
  Some inline text
  <span>followed by a paragraph</span>
  followed by more inline text.
</p>

如上,demo1将创建两个匿名块盒,一个包含 p前面的文本 (Some inline text), 一个包含 p 后面的文本(followed by more inline text)。

demo2将生成一个行内格式上下文,生成一个匿名行盒(line box),里面包含两个匿名行内盒(inline box),Some inline text followed by more inline text.和一个span行内盒。

OK,至于怎么触发块级格式上下文请看块格式化上下文。这里只为了说明IFC而介绍下BFC。

当元素的 CSS 属性 display 的计算值为 inline, inline-blockinline-table 时,称它为行内级元素。

行内级元素生成行内级盒(inline-level boxes),参与行内格式化上下文(inline formatting context)。同时参与生成行内格式化上下文的行内级盒称为行内盒(Inline boxes)。

规范里IFC文字很多,提炼下我们需要的:

如果一个矩形区域,包含着一些排成一条线的盒子,称为line box。

一个line box的宽度,由他的包含块(containg block)和floats的存在情况决定。line box的高度,由你给出的代码决定。(line-height),即所有inline box的最大高度差。

当盒子的高度小于父级盒子高度时,垂直方向的对齐‘vertical-align‘属性决定。

Vertical-align(2)

在上面的vertical-align(1)中主要了解了什么是baseline,以及它是如何确定的。我们继续研究这个属性,看下面说明表格:

描述
baseline 默认。元素放置在父元素的基线上。
top 把元素的顶端与行中最高元素的顶端对齐
text-top 把元素的顶端与父元素字体的顶端对齐
middle 把此元素放置在父元素的中部。
bottom 把元素的顶端与行中最低的元素的顶端对齐。
text-bottom 把元素的底端与父元素字体的底端对齐。

除了baseline我们已经很了解之外,其它几个属性我们貌似也能看懂,唯一的问题可能是父元素的顶端低端都是什么鬼??需要确定一下,好的再次拿我们第一个例子来讲解,但我们需要变一下,加点东西进去:

<div class="demo">
  <span class=‘line-box‘>
    <img src="https://sfault-avatar.b0.upaiyun.com/344/542/3445428434-5631776c183b2_huge256" ><span>Xx</span>
  </span>
</div>
.demo {
  background: red;
}
.line-box {
  background: blue;
  line-height: 200px;
}
.line-box img {
  vertical-align: text-bottom;
  width: 50px;
}
.line-box span {
  margin-left: 20px;
  color: yellow;
}

实例

<script async src="https://jsfiddle.net/Damonare...;></script>

通过IFC部分我们知道,之前的例子实际上有生成一个匿名行盒(line box),虽然他可以继承父元素的属性,但我们没法直观的去操作它?,OK,把这个匿名行盒变成可控的span元素就好了?,如上demo所示。

我们通过设置line box的line-height来控制line-box的高度,然后设置img的vertical-align属性值,来观察具体的对齐方式。OK,读者你可以自行本地测试或是直接更改fiddle内容来看效果。但这里很容易有个误区,就是父元素的middle,top这些值是怎么确定的?如上,我们通过更改img元素的vertical-align的值,来观察区别,表面上看着好像是父元素根据Xx内容来进行确定的,实则不然。我们再来看一个例子:

下面没内容戳这

<script async src="http://jsfiddle.net/Damonare/...;></script>

上面例子中,我们更改了Xx的对齐方式,发现了很奇特的现象?,当Xx设置为text-bottom或是text-top的时候父元素(ling box)被撑大了?,但这另一方面这也证明了,父元素的基线和中线等并不是由文本Xx决定的,谁决定的呢?前面提过的那个空白节点决定的!?这个空白节点实际上是理解内联元素布局的重点!不知道它的存在,很多问题是搞不清楚的。那么这个空白节点又到底是怎么影响布局的呢?前面说过基线的决定着是小写字母x,这个时候问题就来了,可能你早就想问了,不同字体下面的小写字母x底部边缘肯定是有区别的啊,好,我们在研究下font-family

Font-family

我们再来看一个?:

下面没示例内容请戳这

<script async src="http://jsfiddle.net/Damonare/...;></script>

关于字体具体的知识可以看这篇博文,我简单的总结一下重点。首先字体是有一个字体度量的概念的,

  • 一款字体会定义一个 em-square,它是用来盛放字符的金属容器。这个 em-square 一般被设定为宽高均为 1000 相对单位,不过也可以是 1024、2048 相对单位。
  • 字体度量都是基于这个相对单位设置的,包括 ascender、descender、capital height、x-height 等。注意这里面的值是可以超出em-square范围的。
  • 在浏览器中,上面的 1000 相对单位会按照你需要的 font-size 缩放。

看上面的例子我们也能看出来,实际上一个内联元素是有两个高度的content-area 高度(background-color实际渲染的那个高度)和 virtual-area 高度(实际区域占空间的高度也就是line-height)。?

结论

  • 所有的内联元素都有两个高度

    • 基于字体度量的 content-area
    • virtual-area(也就是 line-height )
  • 内联元素都有一个空白节点存在着来确定基线等概念;
  • 基线的确定和字体有关,和内部的内联元素无关;
  • IFC很难懂;
  • line-box(行盒) 的高度的受其子元素的 line-height 和 vertical-align 的影响;
  • 我们貌似没法用CSS来更改字体度量。

题目确实有些标题党的嫌疑了,实际上也没有挖很深,比如vertical-align在inline-table元素的作用效果以及sup,sub等其他的属性值,以及line-height具体的属性值如何生效的都没有涉及。我想把这篇文章重点放在布局上,而且篇幅也有限。没涉及的请自行查阅资料吧,在此说声抱歉。?

??以上。

后记

? 从刚开始做前端,身边CSS简单易学但很坑的声音就不绝于耳,很多人也说HTML、CSS一星期就能学会,现在渐渐觉得真是谬论。是,单纯掌握浮动,定位,对齐,居中等基础能解决一大半的布局问题,甚至百分之百,因为很多情况真的是变个写法莫名其妙就实现了想要的结果。可能这也是很多人说CSS坑的原因,但实际上很多开发者是不看CSS标准的,模仿个网站或是看着视频写个demo就觉得掌握了CSS,远远不是这样的。渐渐觉得深挖CSS要比深挖JavaScript难的多...你觉得CSS坑?谁让你不看标准呢....??♀?

原文地址:https://www.cnblogs.com/baimeishaoxia/p/12200689.html

时间: 2024-11-29 03:48:18

深入理解行内元素的布局的相关文章

CSS设置行内元素和块级元素的水平居中、垂直居中

CSS设置行内元素的水平居中 div{text-align:center} /*DIV内的行内元素均会水平居中*/ CSS设置行内元素的垂直居中 div{height:30px; line-height:30px} /*DIV内的行内元素均会垂直居中*/ PS:当然,如果既要水平居中又要垂直居中,那么综合一下 div{text-align:center; height:30px; line-height:30px} CSS设置块级元素的水平居中 div p{margin:0 auto; widt

css块级元素和行内元素详细解析

块级元素和行内元素是布局中常见的两种基本元素,但是未必有很多人深入的研究它们的细微差别. 常见块级元素:div  p  form ul ol li 等: 常见的行内元素:span stronh em; 它们的区别主要有以下几点: 1.块级元素独自占一行且宽度会占满父元素宽度,行内元素不会独占一行,相邻行内元素可以排在同一行. 如图: <head> <meta charset="UTF-8"> <title>测试</title> <s

HTML 块级元素行内元素的区别

HTML标签 一.块级元素和行内元素是布局中常见的两种基本元素 常见块级元素:div  p  form ul ol li 常见的行内元素:span stronh em; 二.块级元素特性 1.默认独占一行 2.没有宽高时默认撑开一排 3.支持所有css属性 三.内联元素的特性 1.同排可以继续跟同类的标签 2.内容撑开宽度 3.不支持宽高 4.不支持上下的margin和padding 5.代码换行被解析 四.块级元素内联元素相互转换 css        display:block;  块级元素

从块级元素和行内元素的分析到bfc的布局理解

接口和属性介绍 播放器提供了progressMakers属性,是一个数组类型,每一条记录包含offset时间和text打点的内容,还可以包含其他属性,此属性用于告诉播放器进度条打点记录,记录内容属性说明: 名称 类型 说明 offset Number 打点的视频偏移时间,单位:秒 text String 打点的文本信息,默认UI会使用 isCustomized Boolean 是否使用默认UI,不使用设置为true 事件 Aliplayer提供两个事件:鼠标进入进度条上的打点和鼠标离开进度条上的

css布局中关于 块状元素和行内元素的区分

这两天在准备实习的面试和笔试,准备复习一下这些基础的概念,避免自己处于一种仅脑袋理解嘴巴不能表述出来的状态. 块状元素和行内元素的概念是在css页面布局这个地方出现.主要是将html标签按照一定的特性分成2类:块状元素和行内元素(内联元素). 首先概念上理解一下: 块状元素:   块状元素(Block element),字面理解就是一个方块嘛,它一般是其它元素的容器元素,可以容纳块状元素和行内元素,它默认是不会和其它元素同一行的,即相当于两个块状元素写一块是垂直布局的.最常用块状元素是div和p

内联元素和行内元素的区别和理解

转载:http://hi.baidu.com/dingo826/blog/item/f69884f44f5394def3d38578.html 块对象默认宽度是100%(继承自父元素),如果没有采用“float:left/right;”样式,相邻的两个块对象就会分排在不同的两行上. 内联对象的宽度取决于其内部元素的宽度与padding样式值之和,不可直接指定其宽度与高度(“display:block;”.“float:left/right;”强行转换后可以定义),相邻的两个内联对象会排在同一行上

微信小程序布局之行内元素和块级元素

元素按照显示方式主要可以分为块级元素和行内元素,元素的显示方式由display属性控制. 块级元素特点总结: 1.总是在新行上开始 2.宽度的默认为width+margin-left+margin-right+padding-left+padding-right刚好等于父级元素的内容区域宽度,即父元素的width.当设定新的宽度,如果宽度是100%,并且padding.margin不为零,导致块级元素宽度溢出父元素 3.盒子模型的高度默认由内容决定 4.盒子模型中高度.宽度和内外边距都是可控制

css盒模型和块级、行内元素深入理解

一.CSS盒模型 盒模型概述 盒模型是CSS的核心知识点之一,它指定元素如何显示以及如何相互交互.页面上的每个元素都被看成一个矩形框,这个框由元素的内容.内边距.边框和外边距组成.如下图所示: 内边距出现在内容区域的周围.如果在元素上添加背景,那么背景应用于元素的内容和内边距组成的区域.因此可以用内边距在内容周围创建一个隔离带,使内容不与背景混合在一起.添加边框会在内边距区域外边增加一条线.这些线可以有不同的样式和宽度,如实线.虚线.点画线.在边框外边的是外边距,外边距是透明的,一般使用它控制元

css 块状元素与行内元素(内联元素)的理解

块状元素: 它一般是其他元素的容器元素,可以容纳块状元素和行内元素,它默认是不会和其他元素同一行的,即相当于两个块状元素写一起是垂直布局的.最常用的是div和p 行内元素: 行内元素又称内联元素,它只能够容纳文本及其他行内元素,常见的行内元素有 超链接,a, span ,img 行内元素与块状元素的差异是:行内元素并不会从新的一行开始,水平方向会一个个接着. 每个块状元素会从新的一行开始. 强调一下: display:block; float:left/right; 当css对行内元素定义这两属