重学css(6)内联元素的掌管者line-height和vertical-align

2024-04-03 06:32

本文主要是介绍重学css(6)内联元素的掌管者line-height和vertical-align,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.字母x与CSS世界的基线

要了解内联元素,就不得不提到字母x,正是有了x,内联元素才确定了自己的基线(baseline),有了baseline之后,才有了line-height和vertical-align。因此在学习后面的内容之前,必须要了解一个概念:

字母x的下边缘线就是内联元素的基线(baseline)!

既然x那么重要,因此CSS还给了它一个特殊的称呼叫x-height。顾名思义,x-height指的就是小写字母x的高度,那么这个x-height有没有用呢?答案是肯定的,如vertical-align:middle的定义就是baseline往上1/2*x-height的位置,因此我们看到的vertical-align:middle在font-size较大的时候会显得不是特别“垂直居中”,因为不是每个字/字母的高度都和字母x相同,或者说,大部分都是不相同的。

由于vertical-align:middle需要基于x-height进行运算,那么CSS干脆给这个x-height一个名份,进一步衍生出了相对尺寸单位ex,1ex = x-height,因此这个单位会随着font属性的变化而变化,非常的不稳定,所以不太适合用来限定元素的尺寸,但某些情况下,ex的表现相当出色。如:我们需要如下效果

需要在文字后面加一个倒三角符号,这时候我们要让文字和图标对齐可能会借助vertical-align:middle,让文字和图片都基于中线对齐,事实上由于文字本身是基于baseline排版的,这时候我们只要让icon也基于baseline布局不就行了吗?那怎么让图标也基于基线布局呢?加个height:1ex不就完事了吗?如下所示:

<style>
.icon-arrow {display: inline-block;width: 20px;height: 1ex;background: url(/images/5/arrow.png) no-repeat center;
}
</style>

2.内联元素中真实存在的“行框盒子”

由于之前没有好好解析内联盒子的基础知识,这里要补充一个关于内联盒子的基础内容,这对于学习后面的知识有一定的帮助。首先我们需要明确两个非官方概念:什么是行框盒子以及行框盒子有什么用?

什么是行框盒子?事实上我并不敢说这是官方给出的一个盒模型,作者也没有提到,但他似乎真实存在于文字的每一行,而且是以行作为计算单位的,也就是每一行文字(不管他们是不是一个内联标签或匿名标签生成的),都在外面自动生成一个“行框盒子”。注意,这里仅代表我从书本上获取的观点,在后面的幽灵节点中会继续探讨官方是否给出了这个盒子。这么说可能不够直观,来看一个例子吧。

这是我用span标签生成的一段话,他被浏览器自动分割成了两行,你可以理解每行文字的外包裹就是一个行框盒子。那么什么时候会生成行框盒子呢?这里我仅凭个人测试提出两种生成行框盒子的情况,第一种,就是非空内联元素,注意这个非空,很关键,作者似乎总是忽略空元素的测试,我本人则对空元素比较在意。第二种,就是inline-block元素内部自动生成,注意这里可以为空了,具体为什么我也不知道,测试结果如此。

第二个问题是,行框盒子有什么用?作者为什么要提出行框盒子?因为这有助于我们理解很多问题。首先来看下面这个测试代码以及他们生成的结果。

<div style="background: yellow;"><span style="line-height: 40px">我行高40px</span><span style="line-height: 60px">我行高60px</span><span style="line-height: 30px">我行高30px</span><span style="line-height: 90px">我行高90px</span>
</div>

此时div的角色就像是“行框盒子”,因为div包裹了一行“行框盒子”(这里只有一行,两行情况又不同了),这样做是为了让你更直观的看到最终这些内联元素最终生成的“行框盒子”,生成的高度是90px,也就是说,同一行!内联元素生成的行框盒子的高度,取决于line-height最高的那个元素。为了加深你对这个结果的印象,我再放一张图,还是刚才那几个元素,这次我把父容器div的宽度压缩了。

image.png

最终结果跟上面测试的结论相同,第一行行高最高的是60px,第二行行高最高的是90px,两个“行框盒子”一相加,得到最终的150px,对于行框盒子的印象应该够深了吧!

3.内联元素的基石line-height

明白了行框盒子的概念之后,再来看line-height,就会容易的多了。作为内联元素的基石,line-height完全掌控了内联盒子的高度,注意,我说的是完全掌控,跟font-size没有半毛钱关系。

来思考一下下面这个问题,一个空的div的高度是0,在里面写上几个字,他的高度就被撑开了,那么这个高度是由何而来呢?首先可以确定的是,是由新增的文字撑开的,在内联元素中,还有一类叫做“匿名内联元素”的近亲,他们外面没有包裹任何内联元素标签,但事实上他们的表现跟内联元素相同,只是不能单独定义自己的样式(当然可以从父级去继承一些过来,虽然继承的权重最低,但总比没有强)。好了,我们知道这几个字是匿名内联元素了,因此高度是由这个内联元素的高度撑开的,那么这个内联元素的高度又取决于什么呢?下面我们来做两个测试。

image.png

如结果所示,最终撑开高度的是line-height,而不是font-size。注意这里说的是非替换元素的纯内联元素,替换元素的概念可以看一下之前的文章。之前说过padding和border可以影响元素的高度,那么在内联元素中,是否也可以呢?答案是:不行!但有些情况下,视觉上还是有一些偏差。如下测试

<div style="background: yellow"><span style="line-height: 40px;padding: 20px;border: 1px solid">我有padding和border</span>
</div>

由于markdown编辑器支持标签语言,因此我们可以直接预览最终效果如下(小提示:你可以通过浏览器直接检查下面的元素看到CSS样式)

我有padding和border

因此对于纯内联元素,他的高度计算只跟line-height相关。 line-height === 纯内联元素height !!!

关于line-height的计算方式,作者“啰哩吧嗦”算了半天,我只总结成一个公式,line-height = font-size + 上半行距 + 下半行距 。对于CSS来讲,font-size是已知的,因此他只需要计算半行距即可,至于它是怎么算的,就没必要深究了。我只讲这个计算方式会导致一种情况,第一行文字和最后一行文字的上方和下方都只有半行距的距离,中间部分则是一个行距,如对样式有较高要求的可以考虑一下这个因素,用其他方式去弥补这里的高度差。

4.line-height在块级元素和内联替换元素中的疲软性

说完了line-height在内联元素中的表现,再来说说line-height在块级元素和内联替换元素中承担什么样的角色吧。

首先我们先来看简单的,line-height在块级元素中承担一个什么样的角色呢?答案是:屁用没有。当然,本章第三点的第一个例子就是在块级元素上直接写line-height属性,所以,还是有那么丁点作用的,这个作用是line-height无处不在的继承属性决定的,正好块级元素内的匿名内联元素自己写不了样式,那就只能继承父级的line-height了,所以line-height最终还是作用于内联元素,而不是块级元素。然后由内联元素生成的行框盒子相加,撑开了块级元素的高度。

既然line-height在块级元素中没用,那他在内联替换元素中又有哪些表现呢?这个等讲完vertical-align再总结。

5.深入line-height的各类属性值

本节的标题让人觉得摸不着头脑,line-height还有别的属性?还真没有,line-height就一个值,只是可以有不同的类型。

line-height的默认值是normal,注意不是none,还支持数值,百分比值和具体长度值。

首先要了解一下这个看上去就不一般的normal,normal本身是一个跟font-family有关的变量,而且在不同的浏览器中还有不同的计算值,因此对于还原设计稿的这种要求,我们不可能用默认的normal属性,同时由于line-height无处不在的继承属性,有时候不知不觉的你就把这个属性给改了,因此normal属性可以不讨论(我们一切以实用性出发)。

实际上,我们平时会设置line-height为具体的数值,如line-height:xx像素。这种做法完全适用于现在高要求的精致网站,对于需要高保真还原设计稿的需求,完全可以用用具体数值。当然也有一种情况你可以用数字或百分比,就是现在有很多网站有自己的设计标准,如微信小程序,ant-design之类的,他们会要求文章内部的行高是字号的1.3-1.4倍,文章标题的的行高是字号的多少多少倍,这种情况下你大可以根据设计要求,用比例计算方式来写行高。

这里我只推荐用长度值(1,2,3),而不是百分比值(100%,200%),你可能觉得1不是等于100%嘛,其实我也这么认为,一般都是按照喜好随便挑一个。事实上,这里面问题可大了去了。

长度值和百分比值的计算方式是完全相同的。都是font-size长度/百分比,向下取整,141.4 = 19.6 = 19px,注意不是四舍五入,是向下取整的。

那么长度和百分比哪里不同呢?答案是:继承方式,就是line-height中无处不在的继承方式不同。这里我们来看一个实例:

<div class="box box-1"><h3>标题</h3><p>内容</p>
</div>
<div class="box box-2"><h3>标题</h3><p>内容</p>
</div>
<style>
.box   { font-size: 14px; }
.box-1 { line-height: 1.5; }
.box-2 { line-height: 150%; }
</style>

结果如下图所示:

最终表现得结果不一样,问题就在于这个继承方式。

使用数值,line-height = 本身的font-size*数值

使用百分比,line-height = 继承来的line-height*数值

你会发现,一个是基于自身的font-size,一个是基于继承的line-height,完全不同,而且数值在大多数情况下的表现更优,也更符合实际情况。所以我个人推荐不要用line-height的百分比值,就当没听过。

6.内联元素line-height的“大值特性”

其实这个问题并不能单纯的理解为,内联元素line-height取最大那么简单,其中还包含之前所说的“行框盒子”的内容,以及行框盒子产生的幽灵节点。在探索大值特性之前,我们得先了解一下,幽灵节点是什么。来看具体的实例:


<!DOCTYPE HTML>
<html>
<head>
<title></title>
</head>
<body>
<div style="background: yellow"><span style="display: inline-block;"></span></div>
</body>
</html>

注意这段代码必须要有声明。这段代码的结果是:

这里的span标签的高度确实是0,那么究竟是什么撑开了div的高度呢?就是上面提到的“幽灵空白节点”,你可以想象这个幽灵空白节点是一个没有宽度的空白节点,当然你不要去dom结构里找他,肯定是找不到的。在了解幽灵空白节点之前,先得知道,什么时候会出现这个幽灵空白节点,根据我的测试,结果跟作者的描述相同。

产生行框盒子的前面自动生成幽灵空白节点。由于之前提到了,inline-block元素内部可以生成幽灵空白节点,因此这里确实存一个一个看不见的内联元素,且他有自己的line-height。

幽灵空白节点的line-height = font-size(默认12px) * normal,因此这个幽灵空白节点就有自己的高度了,有自己的高度就撑开了inline-block的高度,inline-block又撑开了父容器的高度,那么现在就一切都说得通了。

做好了一切的准备工作,最后做个总结和检测,理解了下面这个案例,你就真正理解了内联元素的line-height。

<div class="box box1"><span>span: line-height:20px</span>
</div>
<div class="box box2"><span>span: line-height:96px</span>
</div>
<style>
.box {width: 280px;margin: 1em auto;outline: 1px solid #beceeb;background: #f0f3f9;
}
.box1 {line-height: 96px;
}
.box1 span {line-height: 20px;
}
.box2 {line-height: 20px;
}
.box2 span {line-height: 96px;
}
</style>

由于markdown编辑器支持标签语言,因此我们可以直接预览最终效果如下(小提示:你可以通过浏览器直接检查下面的元素看到CSS样式)

span: line-height:20px

span: line-height:96px

上面这两个box最终得到的高度是一样的,为什么会这样呢?

刚才说到,每个非空内联元素外面都会生出一层“行框盒子”,而每个行框盒子左边就有一个幽灵空白节点,box1>span的line-height是20px,但他隔壁住了个幽灵空白节点,继承了父元素的line-height:96px,我们已经知道行框盒子的高度是由最高的内联元素的行高决定的,因此box1的最终高度和box2的相同,都是96px。

本章内容过于多,vertical-align就放到下章讲,学了vertical-align之后我们再来看如何结合两者实现多行元素的垂直居中展示,有兴趣的可以关注后续文章,点个关注。

这篇关于重学css(6)内联元素的掌管者line-height和vertical-align的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/872147

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

Vue3项目开发——新闻发布管理系统(六)

文章目录 八、首页设计开发1、页面设计2、登录访问拦截实现3、用户基本信息显示①封装用户基本信息获取接口②用户基本信息存储③用户基本信息调用④用户基本信息动态渲染 4、退出功能实现①注册点击事件②添加退出功能③数据清理 5、代码下载 八、首页设计开发 登录成功后,系统就进入了首页。接下来,也就进行首页的开发了。 1、页面设计 系统页面主要分为三部分,左侧为系统的菜单栏,右侧

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用@CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略,该策略要求请求的域名、协议和端口必须与提供资源的服务相同。如果不相同,则需要服务器显式地允许这种跨域请求。一般在springbo

HTML提交表单给python

python 代码 from flask import Flask, request, render_template, redirect, url_forapp = Flask(__name__)@app.route('/')def form():# 渲染表单页面return render_template('./index.html')@app.route('/submit_form',

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密

vue2 组件通信

props + emits props:用于接收父组件传递给子组件的数据。可以定义期望从父组件接收的数据结构和类型。‘子组件不可更改该数据’emits:用于定义组件可以向父组件发出的事件。这允许父组件监听子组件的事件并作出响应。(比如数据更新) props检查属性 属性名类型描述默认值typeFunction指定 prop 应该是什么类型,如 String, Number, Boolean,