重学CSS(8)—— 内联元素的掌管者line-height和vertical-align(下)

2024-04-03 06:32

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

1.vertical-align的五类属性

抛开inherit这类全局属性不谈,个人把vertical-align分成五类,作者将第一类和第二类总结成线类。

(1)跟x字母打交道的线类:baseline/middle

(2)基于行框盒子边缘的线类:top/bottom

(3)跟父级基线相关的文本类:text-top/text-bottom

(4)常用于公式的上标下标类:super/sub

(5)具体数值类:2px/2em/20%等

通常情况下,内联元素默认都是沿着字母x的下边缘对齐的,也就是vertical-align的默认值是baseline。但对于图片等替换元素,往往使用元素本身的下边缘作为基线,这一点在过去的简陋布局中显得非常好用,二十年前的网页你甚至都不需要会写CSS就可以让读者正常浏览网站内容,但是如今这些"好用的"特点会给我们的CSS布局带来很多不便之处。下面我们通过实战来一一测试这些属性的表现以及利用这些表现实现一些布局方式。

2.跟x字母打交道的vertical-align:baseline/middle

前面说到了,vertical-align的默认值是baseline,也就是字母x的下边缘,为了更好的看清x的下边缘在哪里,我们需要借助最常用的替换元素——图片。图片的下边缘通常为元素本身,我们来看字母x和图片都基于baseline对齐会有什么表现吧。

<div><span>字母x</span><img src="../小和尚.jpg">
</div>

最终效果如下图所示:

可以看到,表现结果跟理论相同,x下边缘与图片下边缘完全持平,那么为什么中文"字母"的下边缘没有和x下边缘对齐呢?没为什么,大部分中文和部分字母的下边缘就是低于baseline的,别问,问就是不知道。同时,你会发现,图片的下边缘会有4px的空隙,导致最终容器的高度多了4px,很多人第一反应就是甩锅中文,因为中文看起来比字母x大一些,低一些,然而就算你把span标签删除了依旧会多出这4个像素。那么多出的4px是哪里来的呢?这里还要请出vertical-align的好朋友line-height一起来解释这个问题。

首先line-height的默认值是normal,这个值是根据font-size和font-family计算得到的,得到的值一般会大于字母x的高度,由于高度多出来的部分由line-height计算后在文字上下均匀分布,因此你可以理解为多出来的4px是baseline到文字下边缘的距离。因此,要解决这多出来的4px其实很简单,修改图片的vertical-align即可,如,让他基于字母x的中点对齐。当然这只是理论上,你可以根据实际需求解决这个问题。

修改后的结果如下图所示:

说完了baseline,再来聊聊middle。我不敢说很多人,我自己之前在理解vertical-align:middle的时候,认为CSS在父容器中间找了一条中线,然后让所有的图文基于这条中线均匀分布。事实上,这样理解的坏处是,你会认为vertical-align需要加在父容器上,事实上vertical-align只在两类元素内生效,就是内联元素和table-cell元素。换句话说,vertical-align属性只能作用在display计算值为inline、inline-block、inline-table或table-cell元素上。需要注意的是,浮动,绝对定位等让元素块化的操作也会让vertical-align失效。了解了vertical-align的生效范围后,我们来看看如何让内联元素在垂直方向上居中吧。依旧是刚才的例子,我们想让图片在固定高度的容器里用vertical-align:middle属性垂直居中。

<div><span>字母x</span><img src="../小和尚.jpg">
</div>
<style>
div{height: 400px;background: rgba(0,0,0,0.1);text-align: center;
}
img{vertical-align: middle;
}
</style>

代码的结果如下图所示:

结果似乎不尽如人意,图片并没有垂直居中,为什么会这样呢?其实答案已经很明显了,vertical-align:middle属性已经生效了,在由span和img生成行框盒子中,图片已经基于字母x的中点垂直居中了,那么,怎么让图片在父级容器中居中呢?这里又要请到好朋友line-height的帮助了,只要让line-height的值等于父容器的高度即可,当然,为了简化代码,我们可以去掉height的申明,让元素保持流的特性,自动撑开容器高度。

这里图片已经完美垂直居中了,但对于文字,可能会有一定的偏差,因为字母x的中点和许多文字的实际中点会有所偏差,这个居中属性在文字偏大的时候就显得明显偏下或偏上了。因此在实际使用的过程中,不要盲目迷信vertical-align的文字居中能力。

3.基于行框盒子上下边缘对齐的top/bottom属性

vertical-align:top;表示当前内联元素的顶部在垂直上边缘对齐。在table-cell中表示元素底padding边缘和表格行的顶部对齐。这里我们只讨论内联元素。下面我们通过一个实例来探究一下这句话的涵义。代码如下:

<div><span style="font-size: 14px">14px</span><span style="font-size: 16px">16px</span><span style="font-size: 18px">18px</span><span style="font-size: 20px">字母x</span><img src="../小和尚.jpg">
</div>
<style>
div{height: 400px;background: rgba(0,0,0,0.1);
}
span{vertical-align: bottom;
}
img{vertical-align: bottom;
}
</style>

产生的结果如下,从下图可以很明显的看出来,内联元素的上下边缘对齐的边缘是行框盒子的边缘,不要混淆理解成了父级容器的边缘。

4.从了解到弃用:vertical-align的文本属性类

当你深入理解了这个属性之后,你就会发现这个属性很难有什么软用。(这句话写在开头是为了让你少钻点牛角尖)

作者在给vertical-align属性分类的时候,将baseline/middle/top/bottom分为一类,其实都是基于行框盒子进行划分的,只是个人由其表现差异性又细分成了两类。而文本属性类text-top/text-bottom在垂直方向布局的时候则和行框盒子没有多大关系了。

vertical-align:text-top 表示盒子的顶部和父级应有内容区域的顶部对齐。vertical-align:text-bottom 表示盒子的底部和父级应有内容区域的底部对齐。

内容区域指的是在默认状态下用鼠标选中文本时的背景蓝色区域,这里说的父级应有的内容区域指的是根据父级的font-size和font-family计算得到的内容区域。

有兴趣的可以参考原文例子。这里就不深究这个看不到前途的属性了。

5.简单了解vertical-align的上标下标类属性

HTML里有两个标签,sup上标,和sub下标。

sup对应的默认vertical-align:super。

sub对应的默认vertical-align:sub

这两个属性无需多做说明,只需看一下他的具体效果即可。

<div>H<sub>2</sub>O<sup>[1]</sup>
</div>
<div>[1]:H<sub>2</sub>O是水的分子式</div>

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

H2O[1]

[1]:H2O是水的分子式

6.vertical-align被忽略的实用数值属性

作者在原文中嘲讽"很多即使工作很多年的前端开发人员,可能不知道vertical-align的属性值支持数值,更不知道支持负值",这着实让他感到意外,没错我就是那个可能过一万年都不会去知道这个值的程序员。在说明这个属性的好处之前,先来看一个利用vertical-align“垂直居中”元素的例子。


<div style="line-height: 150px;"><span style="vertical-align: middle;font-size: 50px">我想垂直居中,却有些偏下</span><img src="../小和尚.jpg" style="vertical-align: middle;width: 50px;height: 50px">
</div>

从结果上来看,由于中文相对于x的middle表现的总体偏下,在文字偏大的时候这个问题就表现得尤为明显了,然而图片在这个时候表现得又比文字要好,如果是文字+图标(icon)的格式,往往会使得文字看起总是偏下,图标总有一些偏上,现在你知道锅应该甩给文字了。这个时候就要请我们的vertical-align数值属性来精确的调整文字的位置了。在不知道数值怎么设置的情况下,不如先来看看vertical-align:0,会发生什么,同时为了便于观察,把图片的垂直居中也改为基于基线对齐。

<div style="line-height:150px;position: relative;"><span style="vertical-align: 0;font-size: 50px">我的vertical-align是0,x</span><img src="../小和尚.jpg" style="vertical-align: baseline;width: 50px;height: 50px">
</div>

这时候可以看到,vertical-align:0的表现和vertical-align:baseline的表现一模一样!因此,vertical-align:数值,是基于baseline对齐的,为了图片和文字最终能居中,我们当然先要保证图片先居中(因为图片替换属性的特性的总能保持完全居中),再去调整文字的数值。最终调整结果如下

<div style="line-height:150px;position: relative;"><span style="vertical-align: -10px;font-size: 50px">借助x辅助调整数值,x</span><img src="../小和尚.jpg" style="vertical-align: middle;width: 50px;height: 50px">
</div>

除了数值,vertical-align还支持基于line-height的百分比计算数值,个人觉得没什么用就不说明了。

7.baseline在inline-block元素中的诡异表现

又到了CSS灵异事件的部分了,我觉得这些个灵异事件甚至可以单独抽出一个章节来讲。vertical-align属性的默认值baseline在文本之类的内联元素那里是指x的下边缘,对于替换元素则是替换元素的下边缘,看完这章应该对这两句话有很深的印象了,但是,如果是inline-block元素,规则就要复杂一些了。

一个inline-block元素,如果里面没有内联元素(包括匿名内联元素),且overflow不是visible,则该元素的基线是其margin盒子的底边缘,否则,其基线就是其元素里面最后一行内联元素的基线。

因为inline-block元素在实际开发中非常重要,搞清楚inline-block的诡异CSS是十分有必要的,理论看起太干,不如来个实际例子看看到底是怎么回事。

<div><span style="margin-bottom: 10px"></span><span>我有自己的内x</span>
</div>
<style>
div{background: rgba(0,0,0,0.1);
}
span{background: rgba(0,0,0,0.5);display: inline-block;width: 100px;height: 100px;
}
</style>

可以看到第一个inline-block元素由于没有内容导致其baseline位置发生改变,变成了margin盒子的下边缘,而另一个inline-block元素的基线是其最后一个行框盒子的基线,在本例中,就是第二行的x字母,由于inline元素的布局是基于baseline的,因此就出现了如图所示的"错位"。

除了空inline-block元素和非空inline-block元素会发生错位,行数不同的inline-block元素也会发生错位。如下图所示:

虽然这两种情况都会发生错位,但需要注意他们发生错位的机制完全不同!

想要解决这个错位问题其实很简单,只要你明白错位问题的产生的根本原因是inline-block元素和baseline有过节即可,所以inline-block元素的vertical-align可以用不基于基线的属性,由于数值属性也是基于基线的因此也会发生错位问题,所以需要具体问题具体分析,我只给出一种最简单的解决方案。如下所示

最后,给大家推荐一个前端学习进阶内推交流群685910553(前端资料分享),不管你在地球哪个方位,
不管你参加工作几年都欢迎你的入驻!(群内会定期免费提供一些群主收藏的免费学习书籍资料以及整理好的面试题和答案文档!)

如果您对这个文章有任何异议,那么请在文章评论处写上你的评论。

如果您觉得这个文章有意思,那么请分享并转发,或者也可以关注一下表示您对我们文章的认可与鼓励。

愿大家都能在编程这条路,越走越远。

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



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

相关文章

vue, 左右布局宽,可拖动改变

1:建立一个draggableMixin.js  混入的方式使用 2:代码如下draggableMixin.js  export default {data() {return {leftWidth: 330,isDragging: false,startX: 0,startWidth: 0,};},methods: {startDragging(e) {this.isDragging = tr

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

React+TS前台项目实战(十七)-- 全局常用组件Dropdown封装

文章目录 前言Dropdown组件1. 功能分析2. 代码+详细注释3. 使用方式4. 效果展示 总结 前言 今天这篇主要讲全局Dropdown组件封装,可根据UI设计师要求自定义修改。 Dropdown组件 1. 功能分析 (1)通过position属性,可以控制下拉选项的位置 (2)通过传入width属性, 可以自定义下拉选项的宽度 (3)通过传入classN

js+css二级导航

效果 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Con

基于Springboot + vue 的抗疫物质管理系统的设计与实现

目录 📚 前言 📑摘要 📑系统流程 📚 系统架构设计 📚 数据库设计 📚 系统功能的具体实现    💬 系统登录注册 系统登录 登录界面   用户添加  💬 抗疫列表展示模块     区域信息管理 添加物资详情 抗疫物资列表展示 抗疫物资申请 抗疫物资审核 ✒️ 源码实现 💖 源码获取 😁 联系方式 📚 前言 📑博客主页:

vue+el国际化-东抄西鉴组合拳

vue-i18n 国际化参考 https://blog.csdn.net/zuorishu/article/details/81708585 说得比较详细。 另外做点补充,比如这里cn下的可以以项目模块加公共模块来细分。 import zhLocale from 'element-ui/lib/locale/lang/zh-CN' //引入element语言包const cn = {mess

vue同页面多路由懒加载-及可能存在问题的解决方式

先上图,再解释 图一是多路由页面,图二是路由文件。从图一可以看出每个router-view对应的name都不一样。从图二可以看出层路由对应的组件加载方式要跟图一中的name相对应,并且图二的路由层在跟图一对应的页面中要加上components层,多一个s结尾,里面的的方法名就是图一路由的name值,里面还可以照样用懒加载的方式。 页面上其他的路由在路由文件中也跟图二是一样的写法。 附送可能存在

vue+elementUI下拉框联动显示

<el-row><el-col :span="12"><el-form-item label="主账号:" prop="partyAccountId" :rules="[ { required: true, message: '主账号不能为空'}]"><el-select v-model="detailForm.partyAccountId" filterable placeholder="

vue+elementui分页输入框回车与页面中@keyup.enter事件冲突解决

解决这个问题的思路只要判断事件源是哪个就好。el分页的回车触发事件是在按下时,抬起并不会再触发。而keyup.enter事件是在抬起时触发。 so,找不到分页的回车事件那就拿keyup.enter事件搞事情。只要判断这个抬起事件的$event中的锚点样式判断不等于分页特有的样式就可以了 @keyup.enter="allKeyup($event)" //页面上的//js中allKeyup(e

vue子路由回退后刷新页面方式

最近碰到一个小问题,页面中含有 <transition name="router-slid" mode="out-in"><router-view></router-view></transition> 作为子页面加载显示的地方。但是一般正常子路由通过 this.$router.go(-1) 返回到上一层原先的页面中。通过路由历史返回方式原本父页面想更新数据在created 跟mounted