GitHub - shuding/react-wrap-balancer: Simple React Component That Makes Titles More Readable
Key Points
- 1React Wrap Balancer is a simple React component designed to improve text readability by optimizing line wrapping, especially for titles, across various viewport sizes.
- 2It prevents situations like single words appearing on the last line, ensuring text content is more "balanced" for enhanced visual presentation.
- 3The library is easily integrated via the `<Balancer>` component, offering configurable props like `ratio` and `preferNative`, and an optional `<Provider>` for global optimization in apps with multiple instances.
The react-wrap-balancer project is a React component library designed to enhance the readability of text, particularly titles, by dynamically optimizing text wrapping to avoid visually unappealing line breaks, such as a single word on the last line, and to achieve a more "balanced" distribution of text across lines.
The core methodology, inferred from its inspirations (Adobe’s balance-text, NYT’s text-balancer, and text-wrap: balance CSS proposal), involves a sophisticated JavaScript-based text re-balancing algorithm. This algorithm aims to minimize the variance in line lengths within a block of text, thereby creating a more aesthetically pleasing rectangular shape. While the exact internal implementation details are not fully exposed in the provided document, such balancing algorithms typically operate by:
- Measuring Text Metrics: Programmatically measuring the width of the container and the individual words or character sequences within the text content. This often requires temporarily rendering the text or using a
canvaselement for accurate font-metric measurements. - Iterative Line Breaking: Exploring various potential line break positions. For a given set of words, the algorithm considers different points where lines could naturally wrap.
- Cost Function Optimization: For each set of potential line breaks, the algorithm calculates a "cost" or "unbalancedness" metric. This metric often quantifies the deviation of individual line lengths from an ideal or average line length. A common cost function might involve:
- Calculating the target line width, often the container width divided by the estimated number of lines.
- Summing the squares of the differences between each actual line length and the target line width : .
- Alternatively, minimizing the maximum line length, or minimizing the difference between the longest and shortest lines.
- Applying Optimal Breaks: Once the optimal set of line breaks that yields the lowest cost is determined, the component manipulates the DOM to apply these breaks. This might involve injecting non-breaking spaces, or rendering words/phrases within elements that are then measured and flowed.
- Dynamic Re-balancing: A critical aspect of this methodology is its responsiveness to layout changes. The library leverages the
ResizeObserverAPI to detect changes in the container's dimensions. Upon such changes, the entire re-balancing algorithm is re-executed, ensuring the text remains optimally wrapped across different viewport sizes and orientations.
The library exposes two primary components:
- : This is the main component that wraps the text content intended for balancing. It accepts several optional props:
as: Specifies the HTML tag to render the wrapped content, defaulting to .ratio: A numerical value between 0 and 1 (defaulting to 1) that controls the "balance-ness." A higher ratio implies a more aggressive attempt to balance the lines, suggesting it might influence the weight given to the cost function in the optimization process.preferNative: A boolean (defaulting totrue) that allows the component to bypass its JavaScript re-balancing logic and utilize the native CSStext-wrap: balanceproperty if supported by the browser, providing a performant native fallback.nonce: An optionalnonceattribute for inline script injection, typically used for Content Security Policy (CSP).
- : For applications using multiple instances, wrapping the entire application with is recommended. This allows all components to share the re-balance logic, potentially optimizing performance and reducing the overall HTML size by centralizing measurement and update mechanisms.
Browser compatibility for react-wrap-balancer is largely dependent on the ResizeObserver API. Modern desktop browsers (Chrome 64+, Edge 79+, Safari 13.1+, Firefox 69+, Opera 51+) and mobile browsers (Chrome 64+, Safari 13.4+, Firefox 69+, Opera 47+, Android WebView 64+) are supported. For older browsers, a polyfill for ResizeObserver is necessary.
The project was created by Shu Ding in 2022 and is released under the MIT license.