Coder Social home page Coder Social logo

react-textfit's Introduction

react-textfit

npm npm version npm downloads

  • fit headlines and paragraphs into any element
  • fast: uses binary search for efficiently find the correct fit
  • 100% react-goodness
  • works with any style configuration (line-height, padding, ...)
  • check out the demo

Table of Contents

Installation

npm install react-textfit --save

Usage

Headlines

import { Textfit } from 'react-textfit';

class App extends Component {
  render() {
    return (
      <Textfit mode="single">
        Fat headline!
      </Textfit>
    );
  }
}

Respect the element's height when using single lines

import { Textfit } from 'react-textfit';

class App extends Component {
  render() {
    return (
      <Textfit
        mode="single"
        forceSingleModeWidth={false}>
        Fat headline!
      </Textfit>
    );
  }
}

Paragraphs

import { Textfit } from 'react-textfit';

class App extends Component {
  render() {
    return (
      <Textfit mode="multi">
        Lorem <strong>ipsum</strong> dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
      </Textfit>
    );
  }
}

Modes

single

Algorithm steps:

1. binary search to fit the element's width
2. if forceSingleModeWidth=false and text overflows height
    2a. binary search to also fit the elements height

multi

Algorithm steps:

1. binary search to fit the element's height
2. if text overflows width
    2a. binary search to also fit the elements width

API

<Textfit>

Props

  • mode (single|multi) Algorithm to fit the text. Use single for headlines and multi for paragraphs. Default is multi.
  • forceSingleModeWidth (Boolean) When mode is single and forceSingleModeWidth is true, the element's height will be ignored. Default is true.
  • min (Number) Minimum font size in pixel. Default is 1.
  • max (Number) Maximum font size in pixel. Default is 100.
  • throttle (Number) Window resize throttle in milliseconds. Default is 50.
  • onReady (Function) Will be called when text is fitted.

License

MIT

react-textfit's People

Contributors

avocadowastaken avatar chrisdrackett avatar denis-sokolov avatar dependabot[bot] avatar malte-wessel avatar mckenna avatar nghiepdev avatar nomemoryerror avatar valberthe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-textfit's Issues

Font size doesn't update, when the height of the div is reduced.

Demo video:
https://www.loom.com/share/e1a54f0ee4ac4d6c93fedf24c100ec8d

When the text length changes from a length spanning multiple lines, to a smaller text requiring only one line, the font size doesn't update. It will keep its previous font size until the length of the incoming text spans more than one line and shifts the height of the div back to i's maxHeight.

the API is used like this
title={(<Textfit max={20}> {article.title} </Textfit>)}

Multi mode does not appear to work

When I use single mode, the text fits perfectly in a single line. However, when I change the mode to "multi", it no longer seems to resize the text.

Below is an example of my code:


    return(
        <div style={{fontSize: '15px'}}>
            <div style={{margin: '10px', fontFamily: 'Times New Roman', border: 'solid black 2px', width: '200px', height: '80px'}}>
                <Textfit mode="multi">
                    The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.
                </Textfit>
            </div>
        </div>
    )

A screenshot of what I am seeing:

image

Is this a problem with the module, or am I doing something wrong?

Textfit deprecated?

when import Textfit it shows deprecated message
please let me know how to fix this ๐Ÿ˜ญ

Screen Shot 2021-01-08 at 7 47 27 PM

Screen Shot 2021-01-08 at 7 49 13 PM

Example demo is not working

I've tried to run the example demo simple but it doesn't work. It seems some dependencies are missing.

This is the error I have:

ERROR in ./index.js
Module not found: Error: Cannot resolve module 'react/lib/ReactMount' in /Users/able/projects/react-textfit/examples/simple
 @ ./index.js 1:334-365

ERROR in ./components/App.js
Module not found: Error: Cannot resolve module 'react/lib/ReactMount' in /Users/able/projects/react-textfit/examples/simple/components
 @ ./components/App.js 1:334-365

feature request: ellipsis

when in single mode, have an option to show an ellipsis when using a min value in props and the text overflows.

Imperative resize

I am facing a need to force a recalculation on Textfit.
It could be nice if Textfit exposes a ref with a method fitText or something of the sort.

Current Workaround

window.dispatchEvent(new CustomEvent('resize'));

Dynamic text can shrink, but font-size doesn't seem to increase when text changes

Maybe related to #38

I have a div with some dynamic text that the user enters. When the text is too long, react-textfit does a good job of shrinking it to fit. But if the text becomes shorter, it does not increase the size again. Is this the expected behavior?

My workaround is set a key, like <Textfit key={text}>. This means that React will use a new Textfit component whenever the text changes, so it always recalculates the correct size.

But it might be good if react-textfit had an option for this, even if it is not the default behavior.

I want to change px to pt

Hi !
i have fixed height div now i want to print that div but the issue is i want to change the font-size unit into Points in order to maintain font-size in print

Configuring the output HTML element types?

Is there a way to configure or somehow manipulate the HTML wrapper elements that the plugin generates?

The generated markup is div > span

So if you use:

<Textfit mode="single">
    <h2>Fat headline!</h2>
</Textfit>

...then the output is div > span > h2
this is invalid markup because block elements (like H2) cannot be nested inside of inline elements (like span)

And if you use:

<h2>
    <Textfit mode="single">
        Fat headline!
    </Textfit>
</h2>

...then the output is h2 > div > span
this is invalid markup because block elements (like div) cannot be nested inside of heading elements (like H2)

Is is possible to either:

  • always use span > span instead of div > span in the generated markup
  • or specify the outer element (for example h2 instead of div)

thanks!

Add option to match line height to font-size

Thanks for this fantastic tool!

I'm using react-textfit to implement the following:
image

The problem is that I end up with a lot of spacing between each word because each one must be an individual <Textfit>. This is resolved by matching the line-height to the font-size.

A nice feature would be something like what's shown below where lineHeight is a percentage adjustment of font-size.

1 = (calculated font size) * 1
0.5 = (calculated font size) * 0.5
1.5 = (calculated font size) * 1.5

<Textfit lineHeight='1'>your next</Textfit>
<Textfit lineHeight='1'>big</Textfit>
<Textfit lineHeight='1'>beverage</Textfit>
<Textfit lineHeight='1'>boost</Textfit>
<Textfit lineHeight='1'>is here</Textfit>

only resize on initial react mount??

Hey guys,
Is there any way the react-textfit component only resizes on the initial mount??

The component is causing a weird side effect where when I scroll really quickly on my phone the component resizes and causes the page to snap to a position on the page.

I think it's because when I scroll really quick the browser's url bar/bottom options bar disappears and that causes react-textfit component to resize, which then causes the page to snap.

Issue calculating the font size

I'm new to react and just started using this component so maybe my observations are far from correct but there we go.

My issue is that sometimes the font-size calculated is by far too small. By adding some logs I've observed that the issue was that the originalWidth calculated at first wasn't correct (it returned a less width of what it should) so the algorithm resulted in an incorrect font-size. I corrected the issue by making sure that every time the algorithm called assertElementFitsHeight and assertElementFitsWidth the innerWidth and innerHeight was retrieved again from the element. Does this make any sense?

Thanks!

Testing in Jest with JSDom throws Cannot read property 'style' of null

This does not seem to happen anywhere outside a test environment.

Full stack trace:

TypeError: Cannot read property 'style' of null

      at Window.getComputedStyle (node_modules/jsdom/lib/jsdom/browser/Window.js:371:20)
      at innerWidth (node_modules/react-textfit/lib/utils/innerSize.js:16:24)
      at TextFit.process (node_modules/react-textfit/lib/Textfit.js:136:59)
      at TextFit.componentDidMount (node_modules/react-textfit/lib/Textfit.js:99:18)
      at commitLifeCycles (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:4553:24)
      at commitAllLifeCycles (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:5729:9)
      at HTMLUnknownElement.callCallback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:1610:14)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:219:27)
      at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:126:9)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:87:17)

React

In react 17.0.1v doesnt work

crash in react-textfit when resizing window

here's the call stack,

KEGo.t.innerWidth (innerSize.js:16)
value (Textfit.js:136)
n.handleWindowResize (Textfit.js:77)
s (throttle.js:26)
setTimeout (async)
(anonymous) (throttle.js:36)

in below function, el is null. according to the code, this el is an intermediate div wrapper that's not from consumer code but inside the library, is this something can be looked at?

I have a very good chance to reproduce this issue when the page is refreshed (just loaded) then resize the window, after that it seems to be fine.

// Calculate width without padding.
function innerWidth(el) {
    var style = window.getComputedStyle(el, null);
    return el.clientWidth - parseInt(style.getPropertyValue('padding-left'), 10) - parseInt(style.getPropertyValue('padding-right'), 10);
}

Resizing window gives warnings to console

When browser window is resized it seems that component still calls setState once it has been unmounted. This causes error prints to console:
Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the Textfit component.

Problematic code part is this.
], err => { // err will be true, if another process was triggered if (err) return; this.setState({ ready: true }, () => onReady(mid)); });
Issue gets fixed if shouldCancelProcess is checked before state is updated like this:
], err => { // err will be true, if another process was triggered if (err || shouldCancelProcess()) return; this.setState({ ready: true }, () => onReady(mid)); });

Resizing from a small window doesn't upsize text

Hi, so when my page is first launched, the text fits and is resized properly. When it's made smaller, it resizes accordingly. However, when I increase the size of the window, the text does not scale back up.

Does it work with Next.js

I am trying to use this with Next.js without success. I've thought it might be related to server-side rendering. Could you confirm if if can work on Next?

Thanks!

Italic text doesn't fit into Textfitted element

Looks like the extra slant or overhang from an element having font-style: italic is not accounted for in the font size calculations.

Regular text working properly:
screen shot 2018-06-28 at 13 08 20

Italic text (p cuts off):
screen shot 2018-06-28 at 13 08 38

Unknown Props with React 15.2.1

The React update doesn't allow unofficial props anymore on DOM elements, and is spitting out:

Warning: Unknown props `forceSingleModeWidth`, `perfectFit`, `throttle`, `autoResize`, `onReady` on <div> tag. 
Remove these props from the element. 
For details, see https://fb.me/react-unknown-prop
in div (created by Textfit)

Doesn't work with multiple components

I have two components loaded into the same Container (page).
The first component (top of the page) seems to work.
However, the second doesn't seem to detect componentDidUpdate.

It looks like it is something to do with the ready state not being set.
i.e. The second component process didn't get the initial call, thus the ready state never set to true.

It works when I comment out

//var ready = this.state.ready;
//if (!ready) return;

from the componentDidUpdate function.

I need this fix ASAP, please let me know if there's a quick solution or workaround to this.

Thank you in advance

Question about animation

Hey, would you say this would work well with animation? e.g. for placing text inside of a monotonically increasing circle? does it also have an option to center-align the text?

Thanks!

Consider using vw as underlying font unit

vw lets you specify font-size as a proportion of view width. I suspect that often the font-size will change roughly in proportion to the view width as you resize the browser. If this library used vw instead of px, it might smooth out the transitions by making it relatively rare that the font-size needed to change significantly. There would still need to be a way to select px for when the library is used in fixed-width layouts.

Safari Initial Font Size

I'm getting incorrect sizes on initial page load in Safari. Easy way to reproduce just open the example website in Safari: link

The size gets correctly calculated as soon as you resize the browser a little bit

Can you provide example src code?

I would really need the source code of this example.

image

In fact, it's great if you could provide all your src example with codesandbox.

REM units for max/min values?

Right now it only supports absolute pixels for max/min values. But this is problematic, as my webapp (and most modern webapps) set all sizes in REM units, which makes websites responsive to different display sizes. Having to set absolute pixels for this component only makes the text go out of proportions with the rest of the webapp.

Is it possible to allow setting min/max values in rem units?

Consider height of the container as well

Again thanks a lot for that library, it works like a charm.
But again I'm coming with more question, is it possible to consider the height of the container as well?

I have a component that is fully resizable and that can end up in such situation:
image

Many thanks!

resizing doesn't work in my app

Hi the TextFit is not at all resizing the font. I'm using react v ^0.14.7;
I'm using the Textfit to resize the react-datagrid column heading.

`
render() {
var categoryHeadings = GenerateCategoryHeadingsFromReportColumns(this.props.reportColumns);

    return (
        <div className='react-datagrid-column-category-headings'>
            <div className="category-headings-flex-box">
                {
                    _.map(categoryHeadings, function (columnHeading, key) {
                        if (columnHeading === undefined) {
                            return '';
                        }

                        var divStyle = {
                            width: columnHeading.width,
                            minWidth: columnHeading.width,
                            paddingRight: columnHeading.paddingRight
                        };
                        return (
                            <div className='category-heading' key={key} style={divStyle}>
                                <Textfit style={inlineStyle}
                                                 mode="single"
                                                 forceSingleModeWidth={false}>
                                                 {columnHeading.categoryName}
                                                   </Textfit>

                            </div>
                        );
                    })
                }
            </div>
        </div>
    );
}

`

Support for React 15?

Hello, thanks for this package, very useful!

I'd love to use this on a current project, but we're using React 15.x and the latest published build specifies 14.x in peerDeps. Looks like there's been a recent commit to support 15 as well -- anything holding up publishing the change?

Thanks again!

Compatibility with flexbox

This library just does not work with flex box containers:

export default function Comp() {
    return (
        <div style={{display: 'flex'}}><Textfit mode='single'>This will not resize.</Textfit></div>
    )
}

It would be nice if it worked correctly with flex box, or if the repo at least warned that it does not work with flex box.

I can try to make it work with flex box and submit a pull request if someone can confirm it is a feature that the maintainers would like added.

This can easily be worked around by wrapping the <Textfit> in a <div> that is not display: 'flex'. But, I did waste some time trying to figure out why my text wasn't resizing, and I would imagine future users will have the same problem.

How to manually trigger resize

In my case my div is resizable, so I would like to have a method that I could call on div resize stop that would trigger a resize on the Textfit element

el.clientHeight == 0, preventing resizing

process (Textfit.js:137)
TextFit._this.handleWindowResize (Textfit.js:77)
call (throttle.js:26)
throttled (throttle.js:36)

I have no idea why, but no matter what I do to the parent, or to the Textfit element itself with styles, the element's clientHeight appears to follow a pattern of X, 0, 0, X, 0, 0 etc when resizing a window. Perhaps something to do with the throttler?

maintainer?

@malte-wessel curious what your plans for this package are. I see in the last couple days there has been some activity resulting in pull requests. However, I also see that the project hasn't been updated in quite a while.

I'm also thinking about starting to use the project, but based on the current state think I'll probably be making my own fork so I can pull in fixes from others as well as make my own. Hopefully there is a way to get all these fixes from the community into a canonical repository.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.