├── .browserslistrc
├── .gitattributes
├── .github
└── FUNDING.yml
├── .gitignore
├── .npmignore
├── .prettierignore
├── .prettierrc
├── LICENSE
├── README.md
├── assets
├── fitty-share.png
├── fitty.gif
├── logo.png
└── oswald.woff2
├── dist
├── fitty.min.js
└── fitty.module.js
├── header.svg
├── index.d.ts
├── index.html
├── package-lock.json
├── package.json
├── rollup.config.js
├── src
└── fitty.js
└── test.html
/.browserslistrc:
--------------------------------------------------------------------------------
1 | last 2 versions
2 | > 0.5%
3 | ie >= 10
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | test.html linguist-vendored
2 | index.html linguist-documentation
3 | readme.md linguist-documentation
4 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | custom: ['https://www.buymeacoffee.com/rikschennink']
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .idea/
3 | npm-debug.log
4 | .npmrc
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | assets/
2 | src/
3 | .idea/
4 | .gitattributes
5 | .babelrc
6 | gulpfile.babel.js
7 | npm-debug.log
8 | *.html
9 | .npmrc
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | dist/**/*
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "svelteSortOrder": "scripts-markup-styles",
3 | "trailingComma": "es5",
4 | "tabWidth": 4,
5 | "printWidth": 100,
6 | "singleQuote": true,
7 | "semi": true
8 | }
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017-2021 Rik Schennink - All rights reserved.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Fitty, Snugly text resizing
2 |
3 | Scales up (or down) text so it fits perfectly to its parent container.
4 |
5 | Ideal for flexible and responsive websites.
6 |
7 | **[Visit PQINA.nl for other useful Web Components](https://pqina.nl/)**
8 |
9 | [](https://github.com/rikschennink/fitty/blob/gh-pages/LICENSE)
10 | [](https://badge.fury.io/js/fitty)
11 | 
12 |
13 | ---
14 |
15 | [](https://www.buymeacoffee.com/rikschennink/)
16 |
17 | [Buy me a Coffee](https://www.buymeacoffee.com/rikschennink/) / [Dev updates on Twitter](https://twitter.com/rikschennink/)
18 |
19 | ---
20 |
21 | ## Features
22 |
23 | - No dependencies
24 | - Easy setup
25 | - Optimal performance by grouping DOM read and write operations
26 | - Works with WebFonts (see example below)
27 | - Min and max font sizes
28 | - Support for MultiLine
29 | - Auto update when viewport changes
30 | - Monitors element subtree and updates accordingly
31 |
32 | ## Installation
33 |
34 | Install from npm:
35 |
36 | ```
37 | npm install fitty --save
38 | ```
39 |
40 | Or download `dist/fitty.min.js` and include the script on your page like shown below.
41 |
42 | ## Usage
43 |
44 | Run fitty like shown below and pass an element reference or a querySelector. For best performance include the script just before the closing `
` element.
45 |
46 | ```html
47 |
Hello World
48 |
49 |
50 |
53 | ```
54 |
55 | The following options are available to pass to the `fitty` method.
56 |
57 | | Option | Default | Description |
58 | | ------------------ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
59 | | `minSize` | `16` | The minimum font size in pixels |
60 | | `maxSize` | `512` | The maximum font size in pixels |
61 | | `multiLine` | `true` | Wrap lines when using minimum font size. |
62 | | `observeMutations` | `MutationObserverInit` | Rescale when element contents is altered. Is set to false when `MutationObserver` is not supported. Pass a custom MutationObserverInit config to optimize monitoring based on your project. By default contains the MutationObserverInit configuration below or `false` based on browser support. |
63 |
64 | Default MutationObserverInit configuration:
65 |
66 | ```javascript
67 | {
68 | subtree: true,
69 | childList: true,
70 | characterData: true
71 | }
72 | ```
73 |
74 | You can pass custom arguments like this:
75 |
76 | ```javascript
77 | fitty('#my-element', {
78 | minSize: 12,
79 | maxSize: 300,
80 | });
81 | ```
82 |
83 | The `fitty` function returns a single or multiple Fitty instances depending on how it's called. If you pass a query selector it will return an array of Fitty instances, if you pass a single element reference you'll receive back a single Fitty instance.
84 |
85 | | Method | Description |
86 | | --------------- | ---------------------------------------------------------------------------------- |
87 | | `fit(options)` | Force a redraw of the current fitty element |
88 | | `freeze()` | No longer update this fitty on changes |
89 | | `unfreeze()` | Resume updates to this fitty |
90 | | `unsubscribe()` | Remove the fitty element from the redraw loop and restore it to its original state |
91 |
92 | | Properties | Description |
93 | | ---------- | -------------------------------- |
94 | | `element` | Reference to the related element |
95 |
96 | ```javascript
97 | var fitties = fitty('.fit');
98 |
99 | // get element reference of first fitty
100 | var myFittyElement = fitties[0].element;
101 |
102 | // force refit
103 | fitties[0].fit();
104 |
105 | // force synchronous refit
106 | fitties[0].fit({ sync: true });
107 |
108 | // stop updating this fitty and restore to original state
109 | fitties[0].unsubscribe();
110 | ```
111 |
112 | Fitty dispatches an event named `"fit"` when a fitty is fitted.
113 |
114 | | Event | Description |
115 | | ------- | --------------------------------------------------------------- |
116 | | `"fit"` | Fired when the element has been fitted to the parent container. |
117 |
118 | The `detail` property of the event contains an object which exposes the font size `oldValue` the `newValue` and the `scaleFactor`.
119 |
120 | ```js
121 | myFittyElement.addEventListener('fit', function (e) {
122 | // log the detail property to the console
123 | console.log(e.detail);
124 | });
125 | ```
126 |
127 | The `fitty` function itself also exposes some static options and methods:
128 |
129 | | Option | Default | Description |
130 | | -------------------------- | ------- | --------------------------------------------------------------------------------------------------------- |
131 | | `fitty.observeWindow` | `true` | Listen to the "resize" and "orientationchange" event on the window object and update fitties accordingly. |
132 | | `fitty.observeWindowDelay` | `100` | Redraw debounce delay in milliseconds for when above events are triggered. |
133 |
134 | | Method | Description |
135 | | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
136 | | `fitty.fitAll(options)` | Refits all fitty instances to match their parent containers. Essentially a request to redraw all fitties. The `options` object is passed to fitty instance `fit()` method. |
137 |
138 | ## Performance
139 |
140 | For optimal performance add a CSS selector to your stylesheet that sets the elements that will be resized to have `white-space:nowrap` and `display:inline-block`. If not, Fitty will detect this and will have to restyle the elements automatically, resulting in a slight performance penalty.
141 |
142 | Suppose all elements that you apply fitty to are assigned the `fit` class name, add the following CSS selector to your stylesheet:
143 |
144 | ```css
145 | .fit {
146 | display: inline-block;
147 | white-space: nowrap;
148 | }
149 | ```
150 |
151 | Should you only want to do this when JavaScript is available, add the following to the `
` of your web page.
152 |
153 | ```html
154 |
157 | ```
158 |
159 | And change the CSS selector to:
160 |
161 | ```css
162 | .js .fit {
163 | display: inline-block;
164 | white-space: nowrap;
165 | }
166 | ```
167 |
168 | ## Do Not Upscale Text
169 |
170 | Fitty calculates the difference in width between the text container and its parent container. If you use CSS to set the width of the text container to be equal to the parent container it won't scale the text.
171 |
172 | This could be achieved by forcing the text container to be a block level element with `display: block !important` or setting its width to 100% with `width: 100%`.
173 |
174 | ## Custom Fonts
175 |
176 | Fitty does not concern itself with custom fonts. But it will be important to redraw Fitty text after a custom font has loaded (as previous measurements are probably incorrect at that point).
177 |
178 | If you need to use fitty on browsers that don't have [CSS Font Loading](http://caniuse.com/#feat=font-loading) support (Edge and Internet Explorer) you can use the fantastic [FontFaceObserver by Bram Stein](https://github.com/bramstein/fontfaceobserver) to detect when your custom fonts have loaded.
179 |
180 | See an example custom font implementation below. This assumes fitty has already been called on all elements with class name `fit`.
181 |
182 | ```html
183 |
189 |
240 | ```
241 |
242 | ## Notes
243 |
244 | - Will not work if the fitty element is not part of the DOM.
245 |
246 | - If the parent element of the fitty element has horizontal padding the width calculation will be incorrect. You can fix this by wrapping the fitty element in another element.
247 |
248 | ```html
249 |
250 |
The examples below can edited live and will auto update.
264 |
265 |
266 |
The wizard quickly jinxed the gnomes before they vaporized.
267 |
268 |
269 |
270 |
Wizard
271 |
272 |
273 |
Click button below to load a custom font to the fitties above.
274 |
275 |
276 |
277 |
The fields above use contenteditable, this is useful for demo purposes but also a bit buggy, in production I would expect Fitty to be mostly used on headers and taglines.