css|vertical-align实现垂直居中玩出的花样⛅⛅

1,223 阅读5分钟

场景题

某次面试的时候,遇到一个场景题,就是span不居中的问题

第一个span是需要做省略处理的,第二个是放置固定的内容

看一下代码

<!--
 * @Author: Kongjingjing
 * @Date: 2022-09-29 10:50:18
 * @Descripttion: 
-->
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>Document</title>
		<style>
			* {
				padding: 0;
				margin: 0;
			}
			div {
				width: 100%;
				background-color: bisque;
				text-align: center;
			}
			.span1 {
				display: inline-block;
				width: 50px;
				height: 100px;
				line-height: 100px;
				background-color: chocolate;
				overflow: hidden;
				white-space: nowrap;
				text-overflow: ellipsis;
			}
			.span2 {
				display: inline-block;
				height: 100px;
				line-height: 100px;
				background-color: cadetblue;
			}
		</style>
	</head>
	<body>
		<div>
			<span class="span1">我爱你哦中国</span>
			<span class="span2">请前往东京</span>
		</div>
	</body>
</html>

展示的效果:

很明显出现了不居中的情况,但是按照我之前学的知识,line-height和height设置成同样的值,就可以实现垂直居中

image.png

那为了解决这个问题,并且只用一行语句,那怎么解决呢?

image.png

再看一下效果

image.png

vertical-align

那就详细来学习一下vertical-align

vertical-align这个是设置元素的垂直排列的.

用来定义行内元素的基线相对于该元素所在行的基线的垂直对齐.

提取重点:行内元素有效,块级元素必然不起作用

vertical-align可以取得值

baseline(默认值) :把行内级盒子的基线与父盒的基线对齐,如果没有基线, margin bottom边缘与父盒基线对齐;
sub :把行内级盒子的基线降到父盒下标的适当位置;
super :把行内级盒子的基线升到父盒上标的适当位置;
<percentage> :把行内级盒子提升或者下降段距离 (距离相对于line height计算),0%意味着同baseline一样;
<length> :把行内级盒子提升或者下降一段距离 , 0cm意味着同baseline-样;
middle :行内级盒子的中心点与父盒基线加上x height-半的线对齐;
text-top :把行内级盒子的顶部同父盒的内容区域顶部对齐;
text-bottom :把行内级盒子的底部同父盒的内容区域底部对齐;
top :把行内级盒子的顶部跟line box顶部对齐;
bottom :把行内级盒子的底部跟line box底部对齐;

image.png

baseline

    <style type="text/css">
        div {
            width: 500px;
            height: 200px;
            border: 1px solid #000;
            font-size: 55px;
        }

        span {
            vertical-align: baseline;
            font-size: 14px;
            line-height: 14px;
            background-color: antiquewhite;
        }
    </style>
</head>

<body>
    <div>
        中国Engxx
        <span>中国Engxx</span>
    </div>
</body>

image.png

top

<head>
    <style type="text/css">
        .all {
            width: 300px;
            height: 300px;
            background: #0f0;
        }

        .box1 {
            display: inline-block;
            width: 200px;
            height: 200px;
            background: #ff0;
            vertical-align: top;
        }
    </style>
</head>

<body>
    <div class="all">abcdefg
        <div class="box1"></div>
    </div>
</body>

image.png

bottom

<head>
    <style type="text/css">
        .all {
            width: 300px;
            height: 300px;
            background: #0f0;
        }

        .box1 {
            display: inline-block;
            width: 200px;
            height: 200px;
            background: #ff0;
            vertical-align: bottom;
        }
    </style>
</head>

<body>
    <div class="all">
        <div class="box1"></div>
        abcdefg
    </div>
</body>

子元素的bottom会出现在父元素的bottom上,这里需要强调的是父元素的bottom并不是盒子的最下边,而是父元素里面文本或者inline-block元素的最下面

image.png

middle

<head>
    <style type="text/css">
        .all {
            width: 300px;
            height: 300px;
            background: #0f0;
        }

        .box1 {
            display: inline-block;
            width: 200px;
            height: 200px;
            background: #ff0;
            vertical-align: middle;
        }
    </style>
</head>

<body>
    <div class="all">
        <div class="box1"></div>
        abcdefg
    </div>
</body>

image.png

体会基线对齐的含义

<style>
    .all{width: 500px;height: 300px;background: #0f0;}   
    .all div{ display: inline-block;background: #ff0;}     
    .box1{font-size: 12px;}      
    .box2{font-size: 18px;}      
    .box3{font-size: 26px;}      
    .box4{font-size: 40px;}      
</style>
<body>
    <div class="all">
        <div class="box1">1000phone</div>
        <div class="box2">meimei</div>
        <div class="box3">dalian</div>
        <div class="box4">hahaha</div>
    </div>
</body>

页面中我放了四个行内块元素,里面放了不同字号的文本内容,子盒子也没有设置高度,所有的盒子我都没设置vertical-align,看看他们会怎么样排列:

image.png

不错,所有元素都按照基线的位置对齐了,就是因为他们的默认垂直对齐方式的取值正是baseline的原因。

super

...
span {
        vertical-align: super;
    }
<div>2<span>3</span></div>

image.png

一个非常合适的上标、或者表示幂次的感觉

sub

...
span {
        vertical-align: sub;
    }
<div>a<span>1</span></div>

image.png

行高控制的到底是哪里垂直居中?

做为一个资深的前端开发,大家都清楚的知道:行高等于容器高可以设置单行文本的垂直居中,那么万一容器里面装的是图片呢?装的是盒子呢?

如果盒子里面装的是行内块元素,不管是图片还是其他元素,它身上的vertical-align就会在行高范围内进行运动。

<style>
    .all{width: 500px;height: 500px;background: #0f0;line-height: 400px;}   
    .all img{vertical-align:bottom;width: 100px;}
</style>
<body>
    <div class="all">
        <img src="1.jpg" alt="">
    </div>
</body>

image.png image.png

image.png

image.png

分别调整了图片的vertial-align的取值,你会发现他其实就是在行高范围内进行移动的,所以图片的垂直居中通常也会选择取值为middle的做法。

引申的场景题

1、父元素不设置高,子元素是一个图片,期望是父元素的高正好等于子元素

image.png 结果为什么是这样?下面为什么空出一块?

因为图片默认是和父级的基线对齐的,就算父级没有文字,但是基线也是在的。可以验证一下

image.png

基线对齐,所以会有空白

🔺怎么解决:

1、设置vertical-align的值不是baseline

2、2个行内块元素,一个有内容,一个没有内容

<head>
    <style type="text/css">
        .parent {
            width: 200px;
            border: 1px solid #000;
            font-size: 14px;
        }

        .child {
            display: inline-block;
            width: 50px;
            height: 50px;
            line-height: 50px;
            background-color: rgb(207, 68, 86);
        }

        strong {
            display: inline-block;
            width: 50px;
            height: 50px;
            line-height: 50px;
            background-color: brown;
        }
    </style>
</head>

<body>
    <div class="parent">
        <div class="child"></div>
        <strong>xx</strong>
    </div>
</body>

image.png

出现上述的原因,是因为默认是基线对齐的,所以以X的基线为准,进行对齐

所以这个时候设置line-height已经完成不能完成垂直居中的任务了,需要

image.png

3、父元素没有高度,父元素的高度由子元素撑开,子元素要想垂直居中,需要做的事情

    .child {
            display: inline-block;
            width: 50px;
            height: 50px;
            line-height: 50px;
            vertical-align: middle;
    }

4、上面讨论的都是父元素没有高度,如果父元素指定了高度,子元素要垂直居中,又该如何?

因为父元素的高本来是由子元素综合排列后最佳高度决定的,那么如果有一个子元素和父元素指定的高一致,再设置 middle 方式对齐,父元素的 x 中点就会对齐该元素的垂直中点,其它元素就可以设置 middle 来对齐父元素的 x 中点了。(只要最高的那个子元素对齐方式符合了,其它的小元素肯定能通过 middle 对齐,所以父元素的 x 中点会以最高的子元素为准)


<head>
    <style type="text/css">
        .box3 {
            width: 100%;
            height: 100px;
            border: 1px solid #000;
        }

        .child3 {
            width: 50px;
            height: 20px;
            display: inline-block;
            background-color: #ff8000;
            vertical-align: middle;
        }

        .child2 {
            width: 10px;
            height: 100%;
            display: inline-block;
            vertical-align: middle;
            background-color: crimson;
        }
    </style>
</head>

<body>
    <div class="box3">
        中国Engxxx<i>xJg</i>
        <div class="child3"></div>
        <div class="child2"></div>
    </div>
</body>

image.png

上面图中的红条 child2 就是来充数挤空间的元素,但是实际项目里在 html 单独写个 div 占位显然不优雅,可以改成这样:

<head>
    <style type="text/css">
        .box3 {
            width: 100%;
            height: 100px;
            border: 1px solid #000;
        }

        .child3 {
            width: 50px;
            height: 20px;
            display: inline-block;
            background-color: #ff8000;
            vertical-align: middle;
        }

        .box3::before {
            content: '';
            width: 0;
            height: 100%;
            display: inline-block;
            vertical-align: middle;
        }
    </style>
</head>

<body>
    <div class="box3">
        中国Engxxx<i>xJg</i>
        <div class="child3"></div>
    </div>
</body>

image.png

回复第一题

解释了这么多,现在可以回到我们的第一个场景题了,之所以会出现这样比较怪的对齐方式,就是基线问题,我们实际上知道,省略号的出现其实是css的一个障眼法,那我们把省略号的css样式去掉,再来看一下

image.png

这个时候就很清楚,为什么出现对不齐的情况了。也就明白了,为什么可以使用vertical-align: top; 解决了

参考👀:

关于vertical-align那些事

vertical-align属性的用法