jjzjj

超长溢出头部省略打点,坑这么大,技巧这么多?

ChokCoco 2024-01-13 原文

在业务中,有这么一种场景,表格下的某一列 ID 值,文本超长了,正常而言会是这样:

通常,这种情况都需要超长省略溢出打点,那么,就会变成这样:

但是,这种展示有个缺点,3 个 ID 看上去就完全一致了,因此,PM 希望能够实现头部省略打点,尾部完全展示,那么,最终希望的效果就会是这样的:

OK,很有意思的一个需求,最开始我以为只是实现一个头部超长溢出打点功能,但是随着实践,发现事情并没有那么简单,下面我们就一探究竟。

利用 direction 实现头部超长溢出打点

正常而言,我们的单行超长溢出打点,都是实现在尾部的,代码也非常简单,像是这样:

<p>Make CSS Ellipsis Beginning of String</p>
p {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

这里,我们可以通过 direction,将省略打点的位置,从尾部移动至头部:

p {
    direction: rtl;
}

结果如下:

简单介绍一下 direction

  • direction:CSS 中的 direction 用于设置文本排列的方向。 rtl 表示从右到左 (类似希伯来语或阿拉伯语), ltr 表示从左到右。

另外两个与排版相关的属性还有:

  • writing-mode:定义了文本水平或垂直排布以及在块级元素中文本的行进方向。
  • unicode-bidi:它与 direction 非常类似,两个会经常一起出现。在现代计算机应用中,最常用来处理双向文字的算法是Unicode 双向算法。而 unicode-bidi 这个属性是用来重写这个算法的。

OK,那么上述需求,是不是简单的添加一个 direction: rtl 就能解决问题呢?我们尝试一下。

direction: rtl 会导致使用下划线 _ 连接的数字内容排版错误

我们给上述的代码,添加一个简单的结构:

<div>
    13993199751_18037893546_4477657
</div>
<div>
    13993199751_18037893546_4477656
</div>
<div>
    13993199751_18037893546_4477655
</div>
div {
    width: 180px;
    overflow: hidden;
    text-overflow: ellipsis;
    direction: rtl;
    white-space: nowrap;
}

效果如下:

成功了!看似好像成功了,但是出了一点小问题!

虽然实现了头部打点,但是我们的数字结尾好像不是我们想要的结果,仔细看一下数字的结尾情况:

这是什么情况呢?

这是由于 direction 在处理纯数字、非纯数字文本上的规则不一致,我们再来看这么一段测试代码:

<div>
    11111_22222_33333_44444
</div>
<div>
    11111 22222 33333 44444
</div>
<div>
    aaaaa bbbbb ccccc dddddd eeeeee
</div>
<div>
    aaaaa_11111_22222_33333_44444
</div>

CSS 层面不考虑溢出情况,仅作用 direction: rtl

div {
    width: 240px;
    direction: rtl;
}

在修改书写方向后,效果如下:

可以看到,这里非常核心的一点在于,对于纯数字的文本内容,数字的排列顺序也会跟着相应的书写顺序,进行反向排列

而形如 11111_22222_33333_44444 这种用下划线连接的文本,处理的方式也会与 11111 22222 33333 44444 一样,实现了从左往右的排列,改变了原有的顺序。

多方案解决

因为我们的 ID是由纯数字加下划线组成,所以无法绕开这种展示。

那么,基于这个现状,我们可以如何去解决这个问题呢?

方案一:两次 direction 反转

方法一,既然最终展示的文案被反转了,那么我们可以尝试通过多一层的嵌套,进行二次反转可以解决问题。

代码如下:

<div class="g-twice-reverse">
    <span>13993199751_18037893546_4477657</span>
</div>
.g-twice-reverse {
    overflow: hidden;
    text-overflow: ellipsis;
    direction: rtl;
    white-space: nowrap;
    
    span {
       direction: ltr; 
    };
}

尝试后的结果如下:

可以看到,内容还是被反转了,我们希望的结果是 ...037893546_4477657。不过不用着急,可以尝试再配合 unicode-bidi 属性试一下。最终发现,配合 unicode-bidi: bidi-override 可以实现我们想要的最终效果:

.g-twice-reverse {
    overflow: hidden;
    text-overflow: ellipsis;
    direction: rtl;
    white-space: nowrap;
    
    span {
       direction: ltr; 
       unicode-bidi: bidi-override;
    };
}

最终结果如下:

完美!这里,我们利用了两层结构:

  1. 外层的 g-twice-reverse 正常设置从右向左的溢出省略打点
  2. 内容添加一层 span,利用 direction: ltrunicode-bidi: bidi-override 的配合,在内部再反向反转排版规则。

当然,这里需要解释一下 unicode-bidi

bidi-override 的作用是对文本进行覆盖,使得其中的内联元素(inline element)按照我们想要的书写方向展示。而 unicode-bidi: bidi-override 取值的作用是用于覆盖默认的 Unicode 双向算法以控制文本的显示方向。

这里,bidi-overridedirection<span> 中的组合,实现了更细粒度的文本方向处理。

方案二:通过伪元素破坏其纯数字的性质

上述的方案需要完全理解其思路还是有比较高的成本的,比较烧脑。

有没有更好理解的方案呢?我们继续尝试。

既然上面被反转排版的内容是纯数字或者由下划线连接成的数字,那么我们能不能尝试破坏其纯数字的特性

譬如,给数组的头部添加一个看不见字母,尝试一下,这里构造两组数据对比一下:

<div class="g-add-letter">
    <span>a</span>
    <span>546_4477657</span>
</div>
<div class="g-add-letter">
    <span>a</span>
    <span>13993199751_18037893546_4477657</span>
</div>
.g-twice-reverse {
    overflow: hidden;
    text-overflow: ellipsis;
    direction: rtl;
    white-space: nowrap;
}

看看效果:

嘿,别说,这个方案看上去真的可行。只是添加一个 <span>a</span> 肯定是不合适的,后面维护的同学肯定一脸懵逼。并且这个 a 字母需要隐藏起来。思来想去,这不是和以前清除浮动的场景非常类似吗?这里使用伪元素再贴切不过,我们再改造下代码:

<div class="g-add-letter">
    <span>546_4477657</span>
</div>
<div class="g-add-letter">
    <span>13993199751_18037893546_4477657</span>
</div>
.g-add-letter {
    overflow: hidden;
    text-overflow: ellipsis;
    direction: rtl;
    white-space: nowrap;
    
    span::before {
      content: "a";
      opacity: 0;
      font-size: 0;
    }
}

我们通过伪元素,使用在元素前面添加了一个字母 a,并且设置伪元素的 font-size: 0opacity: 0,从外观上,完全看不出有这么个元素,非常好的隐藏了起来,同时,起到了破坏内容其纯数字的性质。

效果如下:

方案三:通过 \200e LRM 标记位

我们继续优化我们的方案。

上面通过伪元素的方式,已经能够实现在对业务结构影响最小化及代码增量较少的前提下,实现想要的结果。

问题还是在于插入的这个字母 a,一来是不够优雅,二是这种解决方案更像是一种 HACK 的解决方式,随着时间长河的推进,这种代码即便留下了注释,也容易造成可读性上困扰。

所以,我们需要尝试替换掉这个 a 字母。

这里,通过查阅资料,最终找到了这样一个字符 -- \200e

\200e:是左到右标记(Left-to-Right Mark,LRM)的 Unicode 码点。它是 Unicode 字符方向控制工具之一,用于强制将文本的阅读方向指定为从左到右。在前端排版中,特别是处理多语言文本时,由于不同语言书写时有不同的书写方向,因此可以使用 LRM 来指定文本的书写方向,以确保文本能够正确地显示。

这里,通过 \200e 替换掉 a,这里用 \200e 的目的与 a 的目的其实是不一样的:

  1. 在字符串前面通过伪元素添加一个 a,目的是破坏其纯数字的特性
  2. 在字符串前面通过伪元素添加一个 \200e,目的是强制控制接下来文本的排版顺序

添加 a 的方案类似于一种 Hack 技巧,而 \200e 可以理解为就是专门解决这种场景而诞生的特殊字符。

好,看看改造后的代码:

<div class="g-add-letter">
    <span>13993199751_18037893546_4477657</span>
</div>
.g-add-letter {
    overflow: hidden;
    text-overflow: ellipsis;
    direction: rtl;
    white-space: nowrap;
    
    span::before {
    content: "\200e";
    opacity: 0;
    font-size: 0;
  }
}

效果如下:

这样,我们算是比较完美的解决了这个问题。

方案四:通过 <bdi> 标签

那么,上述的方案已经是最佳方案了吗?或者说,还有没有不需要添加伪元素的方式?

在查找解法的过程中,还发现了一个非常有意思的标签 -- <bdi>

<bdi>:是一个 HTML 标签,表示“双向的隔离器”(Bidirectional Isolation)。它是一个比较新的标签,主要用于解决混合显示多个语言文本时的排版问题。

在多语言文本中,由于不同语言之间的书写方向和文本组织方式可能有所不同,如果直接拼合在一起显示,容易导致排版混乱,甚至出现不合法的语言混排现象。而 <bdi> 标签则提供了一种简单的解决方案,可以隔离不同的语言文本,确保它们按照正确的顺序呈现,并避免混乱的语言混排现象。

具体来说,<bdi> 标签可以将一段文本从周围文本隔离开来,创建一个独立的文本环境,使得文本能够按照正确的书写方向呈现。在使用该标签时,可以使用 dir 属性来指定文本的书写方向,可以是从左到右(dir="ltr")或者从右到左(dir="rtl")等。

综上所述,<bdi> 标签的作用是提供一种简单的解决方案来排版混合显示多个语言文本,通过隔离不同的语言文本,确保它们按照正确的顺序呈现,并避免混乱的语言混排现象。

因此,利用 <bdi> 标签,我们可以再进一步省略掉伪元素的部分:

<div class="g-bdi">
    <bdi dir="ltr">13993199751_18037893546_4477657</bdi>
</div>
.g-bdi {
    overflow: hidden;
    text-overflow: ellipsis;
    direction: rtl;
    white-space: nowrap;
}

此种方案就比较纯粹,回归了最初的代码,只是多了一层 <bdi> 并且设置了其内部语言排版方向。

最终,结果如下:

上述四种方案的完整代码,你也可以戳这里:CodePen Demo -- 多种方式解决下划线数字的头部溢出省略打点排版问题

总结一下

本文,我们介绍了一种在头部省略溢出的情境下,对于形如 11111_22222_33333_44444 这种用下划线连接的文本,处理的方式会被对待成 11111 22222 33333 44444 一样的情况,导致了最终排版结果与我们的预期不符。

为了解决这种问题,我们介绍了 4 种不同的解决方案:

  1. 方案一:两次 direction 反转
  2. 方案二:通过伪元素添加字母,破坏其纯数字的性质
  3. 方案三:通过 \200e LRM 标记位
  4. 方案四:通过 <bdi> 标签

上述 4 个方案的思维与处理方式各有优劣。围绕多语言排版涉及了不同的知识,从一个很小的需求中,能够窥探到其中复杂的逻辑。是一个很好的业务实操案例。

最后

好了,本文到此结束,希望对你有帮助 ?

更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。

如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

有关超长溢出头部省略打点,坑这么大,技巧这么多?的更多相关文章

  1. 动漫制作技巧如何制作动漫视频 - 2

    动漫制作技巧是很多新人想了解的问题,今天小编就来解答与大家分享一下动漫制作流程,为了帮助有兴趣的同学理解,大多数人会选择动漫培训机构,那么今天小编就带大家来看看动漫制作要掌握哪些技巧?一、动漫作品首先完成草图设计和原型制作。设计草图要有目的、有对象、有步骤、要形象、要简单、符合实际。设计图要一致性,以保证制作的顺利进行。二、原型制作是根据设计图纸和制作材料,可以是手绘也可以是3d软件创建。在此步骤中,要注意的问题是色彩和平面布局。三、动漫制作制作完成后,加工成型。完成不同的表现形式后,就要对设计稿进行加工处理,使加工的难易度降低,并得到一些基本准确的概念,以便于后续的大样、准确的尺寸制定。四、

  2. ruby - Cucumber/Savon 省略或删除日志输出 - 2

    在运行Cucumber测试时,我得到(除了测试结果)大量调试/日志相关的输出形式:D,[2013-03-06T12:21:38.911829#49031]DEBUG--:SOAPrequest:D,[2013-03-06T12:21:38.911919#49031]DEBUG--:Pragma:no-cache,SOAPAction:"",Content-Type:text/xml;charset=UTF-8,Content-Length:1592W,[2013-03-06T12:21:38.912360#49031]WARN--:HTTPIexecutesHTTPPOSTusingt

  3. Unity Shader 学习笔记(5)Shader变体、Shader属性定义技巧、自定义材质面板 - 2

    写在之前Shader变体、Shader属性定义技巧、自定义材质面板,这三个知识点任何一个单拿出来都是一套知识体系,不能一概而论,本文章目的在于将学习和实际工作中遇见的问题进行总结,类似于网络笔记之用,方便后续回顾查看,如有以偏概全、不祥不尽之处,还望海涵。1、Shader变体先看一段代码......Properties{ [KeywordEnum(on,off)]USL_USE_COL("IsUseColorMixTex?",int)=0 [Toggle(IS_RED_ON)]_IsRed("IsRed?",int)=0}......//中间省略,后续会有完整代码 #pragmamulti_c

  4. ruby - 为什么 ruby​​ 中的变量前缀允许在方法调用中省略括号? - 2

    在DavidFlanagan的TheRubyProgrammingLanguage中;松本幸弘theystatethatthevariableprefixes($,@,@@)areonepricewepayforbeingabletoomitparenthesesaroundmethodinvocations.谁可以给我解释一下这个? 最佳答案 这是我不成熟的意见。如果我错了,请纠正我。假设实例变量没有@前缀,那么我们如何声明一个实例变量?classMyClassdefinitialize#Herefooisaninstanceva

  5. ruby - 如何模拟 Fixnum 变量的整数溢出? - 2

    我目前正在将一种算法从Java转换为Ruby,但由于Ruby中缺少整数溢出,我遇到了一些障碍。假设我的值为2663860877,它大于最大整数2147483648。在Java中,它环绕,我应该得到-1631106419。我找到了这段代码,但它似乎不起作用:defforce_overflow(i)ifi2147483647i&0xffffffffelseiendend并且'ing变量不会像您期望的那样强制它为负。 最佳答案 假设32位整数具有二进制补码负数,这应该可行:defforce_overflow_signed(i)force_

  6. ruby - 省略数组中散列的大括号 - 2

    我意识到如果散列是数组中的最后一个元素,则可以省略散列的花括号。例如,表单:[1,2,3,:a=>'A',:b=>'B'][1,2,3,a:'A',b:'B']似乎等同于:[1,2,3,{:a=>'A',:b=>'B'}][1,2,3,{a:'A',b:'B'}]我知道这种遗漏对于方法的参数是可能的,但没有注意到对于数组也是可能的。我对这条规则的理解是否正确?而且,这在某处有描述吗? 最佳答案 这似乎是1.9的新功能:$rvmuse1.8.7$irbruby-1.8.7-p352:001>x=[1,2,3,:a=>4,:b=>5]S

  7. ruby-on-rails - 将 vim 与 ruby​​/ruby on rails 结合使用的提示和技巧 - 2

    我是那些没有在他的任何Ruby/RubyonRails工作中使用TextMate的开发人员之一。我在这个领域的特别忠诚在于vim。您最喜欢将vim与Ruby和/或RubyonRails结合使用以尽可能提高工作效率的提示/技巧是什么? 最佳答案 最重要获取rails.vim的副本它在数百万级别上很棒。Readthedoc.提示太多了,:Rviewcustomer,:RSmodelfoo,:Rinvert,gf,:Rextract,:Rake等等。您可能需要NERDTree以及轻松导航(您可以使用:Rtree访问)第二重要在推特上关注t

  8. ruby - 为什么 10^9942066 是我可以计算而不会溢出的最大功率? - 2

    在ruby​​中,一些大数大于无穷大。通过二分查找,我发现:(1.0/0)>10**9942066.000000001#=>false(1.0/0)>10**9942066#=>trueRUBY_VERSION#=>"2.3.0"为什么是这样?109942066有什么特别之处?它似乎不是像9999999这样的任意数字,它不接近任何2的幂(它大约等于233026828.36662442)。为什么ruby的无穷大不是无穷大?109942066是怎么参与的?我现在意识到,任何大于109942066的数字都会溢出到无穷大:10**9942066.000000001#=>Infinity10**

  9. ruby - 为什么在 Ruby 中做同样的事情有那么多略有不同的方法? - 2

    我正在学习Ruby。我的背景是C++/Java/C#。总的来说,我喜欢这种语言,但我有点困惑为什么有这么多不同的方法来完成同一件事,每种方法都有自己略微不同的语义。以创建字符串为例。我可以使用''、""、q%、Q%或仅使用%来创建字符串。一些形式支持插值。其他形式允许我指定字符串定界符。为什么有五种创建字符串文字的方法?为什么我会使用非内插字符串?%语法相对于带引号的文字有什么优势?我知道Ruby中的冗余一定是有值(value)的,但我未经训练的眼睛看不清楚。请赐教。 最佳答案 WhywouldIeverusenon-interpo

  10. 嵌入式单元测试工具Tessy的一些测试技巧 - 2

    最近做了一个平台项目,需要进行动态代码测试,入门了嵌入式单元测试工具Tessy,总结了一些简单的测试技巧。当前网上的教程普遍只写内容概要,真正入手还得自己认真摸索一番。为此,特意总结了一些Tessy测试技巧以供有缘人参考。提几个Tessy工具使用的问题。1.如何导入工程的头文件?2.如何解决文件内存在汇编语言代码分析时候报错的问题?3.如何规避本文件创建却不使用的函数,宏和变量,在执行executetest出现的undefinedreferencetoxx的问题?4.如何创建测试用例testcase?5.为什么testcase的结果输出与期望不一致?6.创建testcase的方法有几种?7.C

随机推荐