You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

5.4 KiB

有没有一种布局方式,在文本保持垂直居中的情况下,文本很多时,可以限制其不超出外层高度 并出现滚动条

场景再现

业务中场景的confirm框,警示图标加文字的结构.要求是图标和文字水平垂直居中,文字过长时优先占满横向空间,横向空间不足时自动换行以及出现滚动条.

示例1 示例1

首先,文字自动换行,我们需要为label添加`whiteSpace: "normal"

旧时代的布局策略

传统布局下,图标与文字同时水平居中,我们最先想到的就是bi.center_adapt,在旧时代的水平垂直居中实现采用的是display:inline-block方式,容器设置text-align:center同时对每个子元素 设置vertical-align:middle

    {
        type: "bi.inline_center_adapt",
        items: [
            {
                el: {
                    type: "bi.icon_label",
                    cls: o.iconCls + " icon-size-50",
                    width: 50,
                },
            }, {
                el: {
                    type: "bi.label",
                    cls: "content-text",
                    text: this.options.text,
                    whiteSpace: "normal",
                    textAlign: "left",
                    lgap: 10,
                },
            },
        ],
    };

看起来一切都那么完美,但是当文字超长的时候,文字在垂直平方向上不受束缚的扩张,水平方向也超出了容器

示例3

有的朋友可能会想到了,那么给文字设置一个max-wdith样式,数值为容器宽度减去提示图标宽度.接下来在添加一个max-height:100%,这样文本区域的长和宽都被束缚住了 姑且不谈这样定宽是否考虑了通用性与自适应场景.看一下效果:文字确实换行了,但是在竖直方向上也可以正常出现滚动条

新时代的flex

FineUI在现代浏览器上对大多数布局组件的实现策略都是基于flex的,那么flex布局处理这种场景是不是更加简便呢?

flex实现水平居中设置justify-content:center即可,对应到布局组件的属性为horizontalAlign:center(此处指水平方向布局) 限制文本换行后内容高度不会超过容器,那么需要设定align-items:stretch,对应到对应到布局组件的属性为verticalAlign:center(此处指水平方向布局)

是不是so easy,理想很丰满,但是现实是文字并没有自动换行,而是超出了容器.因为我们的justify-content:center,致使flex总是让子项目居中分布即使是左右都超出了容器

    {
        type: "bi.flex_center_adapt",
        items: [
            {
                el: {
                    type: "bi.icon_label",
                    cls: o.iconCls + " icon-size-50",
                    width: 50,
                },
            }, {
                el: {
                    type: "bi.label",
                    cls: "content-text",
                    text: this.options.text,
                    whiteSpace: "normal",
                    textAlign: "left",
                    lgap: 10,
                },
            },
        ],
    };

示例3

连老王都不知道flex是个好东西还是个不好的东西,我们就不对flex的好与坏进行评判了.只要探究该如何解决问题

参考旧时代解决方案,对label文本添加一个max-wdith样式,这样便满足了功能需求.

但是,这个方案完美吗?max-width的具体值,需要根据容器宽度指定,这样使组件失去了复用性和独立性,倘若哪天popover尺寸规范变了,max-width的值也需要随之变更.

既然max-width是不固定的,那使用calc可以吗?max-width:calc(100% - 50px).当然可以,这样更精确,但是,100%是相对谁的,百分百确定吗?

多数情况下,能够合理利用max-width控制,实现功能效果,就已经超越大多数布局使用者了.精益求精的话,有没有完美的方案呢?

拓展思路,将问题进行拆分,拆分为两个问题解决.首先需要垂直水平居中,然后需要图标宽度固定和文字随内容增加占满剩余空间.

为了实现水平垂直居中,我们需要设置如下props

    verticalAlign: "middle",
    horizontalAlign: "center",

映射到flex属性即为

    justify-content: center;
    align-items: center;

图标宽度固定,则其在flex容器内既不拉伸也不收缩,文字随内容增加占满剩余空间,则其在空间剩余时不会拉伸,在空间不足时将自动收缩,那么props为

columnSize: [50, ""]

映射到flex属性,图标:

    flex-grow: 0;
    flex-shrink: 0;

label文字

    flex-grow: 0;
    flex-shrink: 1;

最终基于FineUI布局组件的的完整实现方式

    {
        type: "bi.horizontal",
        verticalAlign: "stretch",
        horizontalAlign: "center",
        scrollx: false,
        columnSize: [50, ""],
        items: [
        {
            el: {
                type: "bi.icon_label",
                cls: o.iconCls + " icon-size-50",
                width: 50,
            },
        }, {
            el: {
                type: "bi.label",
                cls: "content-text",
                text: this.options.text,
                whiteSpace: "normal",
                textAlign: "left",
                lgap: 10,
            },
        },
    ],
};