跳到主要内容

行内元素垂直居中

2023年02月19日
柏拉文
越努力,越幸运

一、文本


1.1、单行文本

  • 方式一 line-height

    <div
    style="
    width: 800px;
    height: 400px;
    background-color: antiquewhite;
    text-align:center;
    line-height: 400px;
    "
    >
    <span>测试垂直居中</span>
    </div>

1.2、多行文本

  • 方式一 display: table-cell + vertical + align

    可用 vertical-align 属性, 而 vertical-align 只有在父层为 td 或者 th 时, 才会生效,对于其他块级元素, 例如 div 、 p 等,默认情况是不支持的。

    为了使用 vertical-align ,我们需要设置父元素 display:table , 子元素 display:table-cell; vertical-align:middle;

    <div
    style="
    width: 800px;
    height: 400px;
    background-color: antiquewhite;
    text-align:center;
    display: table;
    "
    >
    <span style="display: table-cell; vertical-align: middle"
    >测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中</span
    >
    </div>
  • 方式二 display: inline-block + vertical-align

    设置幽灵节点的高度以及幽灵节点的基线(通过 line-height ),来设置幽灵节点的 x-height , 是 span 的中线与幽灵节点的中线对齐,同样也可以使 vertical-align: middle; 居中

    <div
    style="
    width: 800px;
    height: 400px;
    background-color: antiquewhite;
    text-align:center;
    line-height: 400px;
    "
    >
    <span
    style="
    vertical-align: middle;
    line-height: normal;
    display: inline-block;
    "
    >测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中</span
    >
    </div>
  • 方式三 display: gird

    <div
    style="
    width: 800px;
    height: 400px;
    background-color: antiquewhite;
    display: grid;
    "
    >
    <span style="margin: auto"
    >测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中测试垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中垂直居中</span
    >
    </div>

二、文本和图标


2.1 方案一、vertical-align: middle

  • 初始情况,未设置任何值

    实时编辑器
    function Test(props) {
        const box = {
            border: "1px solid black"
        }
        const label = {
    
        }
        const icon = {
            display: "inline-block",
            width: "20px",
            height: "20px",
            backgroundColor: "blue"
        }
        return (
            <div style={ box }>
                <span style={ label }>颜色xx</span>
                <span style={ icon }></span>
            </div>
        );
    }
    
    结果
    Loading...

    现象: 可以看见,是文字的baseline(字母x的下边缘)和蓝色盒子的底部边界值(baseline)对齐

  • 设置文字和图标的vertical-align:middle

    实时编辑器
    function Test(props) {
        const box = {
            border: "1px solid black"
        }
        const label = {
            verticalAlign: "middle"
        }
        const icon = {
            display: "inline-block",
            width: "20px",
            height: "20px",
            backgroundColor: "blue",
            verticalAlign: "middle"
        }
    
        return (
            <div style={ box }>
                <span style={ label }>颜色xx</span>
                <span style={ icon }></span>
            </div>
        );
    }
    
    结果
    Loading...

    现象: 现在文字和图标已经水平对齐了,理论上是文字图标垂直中点已经和行盒子的基线+字母x高度的一半对齐

    问题: 文字(span标签)的上方(注意是上方)与行盒子(父元素)之间有条缝隙。其实行盒子最后,会存在一个我们看不见的文本盒(w3c称作struct),这里我们通过添加一个伪元素,添加一个字母x,直观的模拟下,该文本盒也会有默认大小(除非font-size设为0)的。所以该缝隙,就是由于文本盒本身空间所占据的

    优化: 通过给父元素设置font-size:0, 子元素单独设置font-size 来去掉缝隙

  • 经过font-size 优化之后, 设置文字和图标的vertical-align:middle

    实时编辑器
    function Test(props) {
        const box = {
            fontSize: "0px",
            border: "1px solid black"
        }
        const label = {
            fontSize: "14px",
            verticalAlign: "middle"
        }
        const icon = {
            display: "inline-block",
            width: "20px",
            height: "20px",
            backgroundColor: "blue",
            verticalAlign: "middle"
        }
        return (
            <div style={ box }>
                <span style={ label }>颜色xx</span>
                <span style={ icon }></span>
            </div>
        );
    }
    
    结果
    Loading...
  • 给父元素高度之后,需要给父元素添加line-height: 父元素内容区高度 再设置文字和图标的vertical-align: middle

    实时编辑器
    function Test(props) {
        const box = {
            width: "200px",
            height: "200px",
            fontSize: "0px",
            lineHeight: "calc(200px - 2px)",
            border: "1px solid black",
            position: "relative",
        }
        const label = {
            fontSize: "14px",
            verticalAlign: "middle"
        }
        const icon = {
            display: "inline-block",
            width: "20px",
            height: "20px",
            backgroundColor: "blue",
            verticalAlign: "middle"
        }
        const line = {
            position: "absolute",
            width: "200px",
            height: "1px",
            top: "100px",
            backgroundColor: "red",
        }
        return (
            <div style={ box }>
                <span style={ label }>颜色xx</span>
                <span style={ icon }></span>
                <div style={ line }></div>
            </div>
        );
    }
    
    结果
    Loading...

2.2 方案二、flex 、align-items: center

实时编辑器
function Test(props) {
    const box = {
        width: "200px",
        height: "200px",
        border: "1px solid black",
        position: "relative",
        display: "flex",
        alignItems: "center"
    }
    const label = {
        fontSize: "14px",
    }
    const icon = {
        width: "20px",
        height: "20px",
        backgroundColor: "blue",
    }
    const line = {
        position: "absolute",
        width: "200px",
        height: "1px",
        top: "100px",
        backgroundColor: "red",
    }
    return (
        <div style={ box }>
            <span style={ label }>颜色xx</span>
            <span style={ icon }></span>
            <div style={ line }></div>
        </div>
    );
}
结果
Loading...

2.3 方案三、grid 、align-items: center

实时编辑器
function Test(props) {
    const box = {
        width: "200px",
        height: "200px",
        border: "1px solid black",
        position: "relative",
        display: "grid",
        gridTemplateColumns: "auto 20px",
        alignItems: "center",
        justifyContent: "flex-start"
    }
    const label = {
        fontSize: "14px",
    }
    const icon = {
        width: "20px",
        height: "20px",
        backgroundColor: "blue",
    }
    const line = {
        position: "absolute",
        width: "200px",
        height: "1px",
        top: "100px",
        backgroundColor: "red",
    }
    return (
        <div style={ box }>
            <span style={ label }>颜色xx</span>
            <span style={ icon }></span>
            <div style={ line }></div>
        </div>
    );
}
结果
Loading...