logoAnt Design

⌘ K
  • Design
  • Development
  • Components
  • Blog
  • Resources
5.25.4
  • CSS in v6
  • 👀 Visual Regression Testing
  • Why is it so hard to disable the date?
  • HOC Aggregate FieldItem
  • Line Ellipsis Calculation
  • 📢 v4 surpassed maintenance period
  • Type Util
  • A build ghost
  • Ant Design meets CSS Variables
  • Historical Debt of API
  • Stacked Notification
  • Color Models and Color Picker
  • Extends Theme
  • Virtual Table is here!
  • Happy Work Theme
  • Where is the dynamic style?
  • Suspense breaks styles
  • Bundle Size Optimization
  • Hi, GitHub Actions
  • To be what you see
  • Pain of static methods
  • SSR Static style export
  • Dependency troubleshooting
  • Contributor development maintenance guide
  • Repost: How to submit a riddle
  • Tooltip align update
  • Unnecessary Rerender
  • How to Grow as a Collaborator
  • Funny Modal hook BUG
  • about antd test library migration
  • Tree's check conduction
  • Some change on getContainer
  • Component-level CSS-in-JS
Some issues with CSS
Using JS
Mixed Measurement
Summary

Line Ellipsis Calculation

2024-03-01
@zombieJ
contributors
  • HOC Aggregate FieldItem📢 v4 surpassed maintenance period

    Resources

    Ant Design X
    Ant Design Charts
    Ant Design Pro
    Pro Components
    Ant Design Mobile
    Ant Design Mini
    Ant Design Web3
    Ant Design Landing-Landing Templates
    Scaffolds-Scaffold Market
    Umi-React Application Framework
    dumi-Component doc generator
    qiankun-Micro-Frontends Framework
    Ant Motion-Motion Solution
    China Mirror 🇨🇳

    Community

    Awesome Ant Design
    Medium
    Twitter
    yuque logoAnt Design in YuQue
    Ant Design in Zhihu
    Experience Cloud Blog
    seeconf logoSEE Conf-Experience Tech Conference

    Help

    GitHub
    Change Log
    FAQ
    Bug Report
    Issues
    Discussions
    StackOverflow
    SegmentFault

    Ant XTech logoMore Products

    yuque logoYuQue-Document Collaboration Platform
    AntV logoAntV-Data Visualization
    Egg logoEgg-Enterprise Node.js Framework
    Kitchen logoKitchen-Sketch Toolkit
    Galacean logoGalacean-Interactive Graphics Solution
    xtech logoAnt Financial Experience Tech
    Theme Editor
    Made with ❤ by
    Ant Group and Ant Design Community

    Ant Design's Typography component provides an ellipsis property to display ellipsis when text overflows. It supports limiting the number of displayed lines through the ellipsis.rows configuration. If it is pure text content, it will be implemented through the CSS -webkit-line-clamp property. Although it has a -webkit- prefix, it has been well supported in modern browsers.

    tsx
    <div
    style={{
    display: '-webkit-box',
    overflow: 'hidden',
    WebkitBoxOrient: 'vertical',
    webkitLineClamp: 3,
    }}
    >
    {text}
    </div>

    row ellipsis

    Some issues with CSS

    However, CSS implementation also has limitations, that is, it does not support modifying the ellipsis and supporting additional action buttons (such as copy, edit, expand, etc.):

    with action

    Operational buttons will be truncated together and cannot be displayed.

    ellipsis with action

    Though there are some magic methods to achieve this through styles such as float, this method requires targeted processing in different browsers. In addition, it still cannot solve the problem of custom ellipsis. Therefore, the best implementation method is still through JS.

    Using JS

    With JS, we can quickly find the truncation position of the text through binary search. As long as the height of the text is inferred based on rows, we can traverse and find the maximum number of characters that can be displayed:

    Cell Cut

    And get the line height by simulating an embedded span:

    tsx
    <div>
    {text}
    {measuring && <span ref={measureRef}>&nbsp;</span>}
    </div>

    Measure

    But this method also has some problems, for mixed line height scenarios (such as adding images, embedding different sizes of text, etc.). This calculation method often estimates the wrong total height, making the truncation position inaccurate:

    Mixed Line Height

    Since the height of the image exceeds the line height, the calculation thinks that the image occupies the height of two lines. At the same time, because the image itself cannot be truncated, the final number of ellipsis lines is incorrect (3 lines of ellipsis becomes 2 lines):

    Mixed Line Height Ellipsis

    Even worse, if the image is on the first line, the entire text will be truncated:

    Image on the first line

    But if you use CSS, there will be no such problem:

    CSS Ellipsis

    Mixed Measurement

    To solve this problem, we can use a mixed measurement method. That is, use CSS to measure the total height of the native multi-line ellipsis, and then use JS to perform binary search to ensure that the truncation position of the text does not exceed the total height measured by CSS:

    tsx
    <div ref={measureRef} style={ellipsisStyle}>
    {text}
    </div>;
    const cssHeight = measureRef.current.clientHeight;
    tsx
    // pseudocode. Not used in real world
    <div ref={walkingMeasureRef}>{text.slice(0, walkingMeasureIndex)}</div>;
    if (walkingMeasureRef.current.clientHeight > cssHeight) {
    // Not meet the requirement
    }

    This helps to accurately handle mixed line height scenarios:

    Mixed Line Height Ellipsis

    Summary

    The mixed measurement method allows us to easily use the accuracy of CSS and the flexibility of JS to achieve accurate text truncation even in complex content containing images and other elements with different line heights.

    This refactoring has been released in 5.15.0, welcome to experience it.