V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
wuzhanggui
V2EX  ›  程序员

为什么浏览器按 css 渲染好了一个元素,却没法暴露一些属性让开发者知道呢?

  •  
  •   wuzhanggui · 1 天前 · 2263 次点击

    最近有个需求是让超长文本展示有展开,收起的功能,看了很多库,很多都是使用 js 截断文本来实现的,我想用 css 主导,js 辅助来实现,例子

    但是如果是 html 文本的话,浏览器能按设定的行数来显示省略符号,但是我想知道这个省略到底是在哪个字后省略的,哪一行省略的,或者这个省略号的位置是什么。

    为什么浏览器知道但是却没有个啥属性来让开发者知道呢,只能用些曲线救国的方式来获取。或者说有啥属性能获取,求教

    第 1 条附言  ·  23 小时 12 分钟前
    已经用浮动的效果实现了 https://github.com/wurencaideli/smart-text-ellipsis ,但是就是有计算不准确的情况,如果只是文本的话没有问题,html 文本的话也没问题,主要是用来展示 markdonw 就有问题,如果直接能知道省略号的位置就好办了,难。
    24 条回复    2025-08-01 13:49:02 +08:00
    sentinelK
        1
    sentinelK  
       1 天前
    楼主的意思是说,为何 DOM 元素的状态没有 100%的映射到 JS 中?

    我理解的原因很简单,因为当初压根就没想过。当初的 HTML ,就是想当个电子报纸而已。
    然后随着网页越来越复杂,人们对网页的想法越来越多,不得不逐渐增加标准。

    然后因为 HTML 的渲染本身,其实是和 JavaScript 线程分离的(也就是所谓的主线程、渲染线程、合成线程)。
    过于复杂的 DOM 状态回馈,会导致 JS 脚本的执行速度显著下降(因为 JS 本身其实是没有多线程的)。

    举个例子,你可以想象一下,一个 DOM ,从左下角以 60FPS 的帧率飘向右上角。如果你随时可以通过 dom.x/dom.y 来查看坐标,你的 js 要卡成什么样子。
    xiangyuecn
        2
    xiangyuecn  
       1 天前   ❤️ 1
    每个字一个 span 不就完了,直接读每个 span 的 offsetTop 看超过容器高度了没有
    xiaoming1992
        3
    xiaoming1992  
       1 天前 via Android
    看到#2 ,渲染和 js 脚本由不同的引擎负责,通信有成本。
    或许“测不准原理”也是这么个情况,速度是由“js 引擎”负责的,位置也是由“渲染引擎”负责的。我们的每一次测量是取快照。
    卧槽,我发现了宇宙的终极秘密。
    xiaoming1992
        4
    xiaoming1992  
       1 天前 via Android
    错了,是看到#1
    irisdev
        5
    irisdev  
       1 天前
    省略号是伪元素,不如直接问浏览器为啥没有操作伪类元素的 api
    iOCZS
        6
    iOCZS  
       1 天前
    想想原生是怎么实现的。。。
    JasonSi
        7
    JasonSi  
       1 天前
    这个问题真是十年前我就做需求遇到,现在还是这样 想偷懒就跟 UX 讨价还价。。。
    jamesjammy061
        8
    jamesjammy061  
       1 天前
    没办法,实现过这个需求,就是 js 一个字一个字去找到的
    jamesjammy061
        9
    jamesjammy061  
       1 天前
    创建一个隐藏的 div ,加上 getComputedStyle ,硬算
    NewYear
        10
    NewYear  
       1 天前
    需求合理,可以向浏览器标准组织投稿。

    或许下一个版本就支持了
    ggabc
        11
    ggabc  
       1 天前 via Android
    html 设计的 alt ,但是你们不满意
    wuzhanggui
        12
    wuzhanggui  
    OP
       1 天前
    @xiaoming1992 网上说是这个省略号是渲染的时候直接绘制上去的,既然都绘制上去了,并且知道是在哪个元素上绘制的,直接把省略号的一些信息加在这个元素上,感觉很容易呀
    spritecn
        13
    spritecn  
       1 天前
    取舍吧,用处小
    sentinelK
        15
    sentinelK  
       1 天前
    @wuzhanggui 确实很容易。但是:

    首先 html 本身其实没有组件概念。他所有的执行结果都只是为了呈现富文本效果。
    这也就导致,渲染线程先天的没有给主线程高效同步状态的机制。
    从而,基于性能、逻辑链条的角度考虑,导致了 js 只能获取 dom 元素的一部分既定的状态。

    举个不恰当的例子。

    你向你公司的 CEO 报告你手里程序的开发进度。你可以决定你程序的开发、设计。也可以“侧面了解”项目的商业进展。但是 CEO 不会向你汇报合同细节和最终成交价。

    他告诉你也很容易,1 秒钟的事儿,但是 CEO 不会告诉你。
    realpg
        16
    realpg  
    PRO
       1 天前
    @xiaoming1992 #3

    其实物理学到了微观粒子层面 就会出现魔法一般的现象

    而这个现象在宏观世界, 其实是有类似的现象的

    比如 电脑显卡的渲染分辨率能力不足的情况下 就类似其中一种微观现象..
    dfkjgklfdjg
        17
    dfkjgklfdjg  
       1 天前
    不知道这篇文章对大家有没有帮助?

    [CSS 弹性浮动布局应用 - 前端侦探 - SegmentFault 思否]( https://segmentfault.com/a/1190000040172089)
    paloalto
        18
    paloalto  
       19 小时 59 分钟前
    @gp0119 #14 这个解法,没法应对「在文字包含换行的情况下「展开」按钮需要紧跟在文字后面」这个需求。

    codehz
        19
    codehz  
       4 小时 52 分钟前   ❤️ 1
    因为实际上有提供,只是你不知道而已。。。
    就是 getClientRects 这个 api ,直接在行内元素上使用,就可以得到每一行文本(也包含其他元素)的位置了
    codehz
        20
    codehz  
       4 小时 48 分钟前   ❤️ 1
    @sentinelK
    @xiaoming1992
    @realpg
    渲染进程和 js 是同一个,渲染进程就是 js 主进程 https://developer.mozilla.org/zh-CN/docs/Web/Performance/Guides/How_browsers_work 要么你自己盯着 devtools 的性能 tab 看也可以一眼看出。。。双线程的 UI 模型并不是 web 的模型(是 flutter/react-native/小程序的模型),合成可以分开,但那部分也不重要,布局信息都是渲染进程这边提供的,合成就是最后一步生成纹理而已
    sentinelK
        21
    sentinelK  
       4 小时 32 分钟前
    @codehz 感谢指正,学习了。
    xiaoming1992
        22
    xiaoming1992  
       56 分钟前
    @codehz #19 学到了,感谢。
    我写了个 [demo]( https://cdn.16px.cc/public/2025-08-01/ellipsis.html), 确实能获取到文本超出后的省略号的尺寸位置。

    但是如果你慢慢改变页面宽度(浏览器宽度),会发现,省略号所在的 DOMRect 有时候在第三个,有时候在第四个,且有时候与视觉不一致。所以实际用起来可能还需要处理这些问题。
    xiaoming1992
        23
    xiaoming1992  
       51 分钟前
    re #22 ~~"且有时候与视觉不一致"~~
    md 复现不出来了,估计是渲染耗时导致 render 执行时机问题,算我代码 bug 。
    但是“省略号所在的 DOMRect 有时候在第三个,有时候在第四个”这个问题依旧存在
    codehz
        24
    codehz  
       31 分钟前
    @xiaoming1992 不能按位置来算,因为如果里面有存在其他元素的话,就可能单独生成一个 rect ,因此最为推荐的方法就是看那一行能达到的最大宽度,然后在往前数三个点的宽度就是省略号的位置(或者你安排一个比三个点更长的东西盖住也可以)
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5637 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 06:20 · PVG 14:20 · LAX 23:20 · JFK 02:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.