├── README.md ├── css └── styles.css ├── demo.html └── js └── mm-fontsize.js /README.md: -------------------------------------------------------------------------------- 1 | min-max-font-size 2 | ================= 3 | 4 | Using vw or vh CSS units for font-size? Set a min or max font-size for your type. 5 | 6 | ## Setup 7 | 8 | Add `mm-fontsize.js` at the end of your HTML page, just before the closing `body` tag. 9 | 10 | ```HTML 11 | … 12 | 13 | 14 | 15 | 16 | 17 | ``` 18 | 19 | Now you can start manually adjusting kerning in your own CSS. 20 | 21 | ## CSS Syntax 22 | 23 | To use the min-font-size or max-font-size propery, just write it in your CSS like any other property: 24 | 25 | ```CSS 26 | h1 { 27 | font-size: 4vw 28 | max-font-size: 50px; 29 | min-font-size: 20px; 30 | } 31 | ``` 32 | 33 | Notes: 34 | * This is only for when using vw or vh units for font size. 35 | * Right now, `px` is the only unit accepted for min and max-font-size. (Working on ems.) 36 | 37 | ## This script is a Stylefill 38 | 39 | A ‘Stylefill’ is a way to create new CSS properties using JavaScript. Stylefills are similar in concept to a [polyfill](http://remysharp.com/2010/10/08/what-is-a-polyfill/), but are only focussed on extending CSS in new ways, and [Stylefill.js](https://github.com/nathanford/stylefill/) is a library to help make it much easier. 40 | 41 | ## Support 42 | 43 | mm-fontsize.js will work in any browser that accepts [vw or vh CSS units](http://caniuse.com/#search=viewport%20units). 44 | 45 | ## License 46 | 47 | This script is released under The MIT License (MIT) 48 | 49 | Copyright (c) 2015 Nathan Ford 50 | 51 | Permission is hereby granted, free of charge, to any person obtaining a copy 52 | of this software and associated documentation files (the "Software"), to deal 53 | in the Software without restriction, including without limitation the rights 54 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 55 | copies of the Software, and to permit persons to whom the Software is 56 | furnished to do so, subject to the following conditions: 57 | 58 | The above copyright notice and this permission notice shall be included in 59 | all copies or substantial portions of the Software. 60 | 61 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 62 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 63 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 64 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 65 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 66 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 67 | THE SOFTWARE. 68 | -------------------------------------------------------------------------------- /css/styles.css: -------------------------------------------------------------------------------- 1 | /* Example CSS - external file */ 2 | 3 | p { 4 | min-font-size: 14px; 5 | } 6 | 7 | p, li, h3, dd { 8 | font-size: 2vw; 9 | max-width: 32em; 10 | min-font-size: 12px; 11 | } 12 | 13 | p { 14 | margin: 0; 15 | } 16 | 17 | p + p { 18 | text-indent: 1em; 19 | } -------------------------------------------------------------------------------- /demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Min-Max-Font-Size Demo 10 | 11 | 12 | 13 | 14 | 69 | 70 | 71 | 72 | 73 |
74 | 75 |

Min and Max-font-size demo.

76 | 77 |

Grab the script on github.

78 | 79 |

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.

80 | 81 |

Donec nec justo eget felis facilisis fermentum. Aliquam porttitor mauris sit amet orci. Aenean dignissim pellentesque felis.

82 | 83 |

Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.

84 | 85 |

Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus.

86 | 87 |

Phasellus ultrices nulla quis nibh. Quisque a lectus. Donec consectetuer ligula vulputate sem tristique cursus. Nam nulla quam, gravida non, commodo a, sodales sit amet, nisi.

88 | 89 |

Pellentesque fermentum dolor. Aliquam quam lectus, facilisis auctor, ultrices ut, elementum vulputate, nunc.

90 | 91 |

Sed adipiscing ornare risus. Morbi est est, blandit sit amet, sagittis vel, euismod vel, velit. Pellentesque egestas sem. Suspendisse commodo ullamcorper magna.

92 | 93 |
94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /js/mm-fontsize.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | mm-fontsize.js 4 | 5 | This script uses stylfill.js (https://github.com/nathanford/stylefill/) to allow properties to be written in the CSS. 6 | 7 | To use the min-font-size or max-font-size propery, just write it in your CSS like any other property: 8 | 9 | h1 { 10 | font-size: 4vw 11 | max-font-size: 50px; 12 | min-font-size: 20px; 13 | } 14 | 15 | Notes: 16 | * This is only for when using vw or vh units for font size. 17 | * Right now, only px is the only unit accepted for min and max-font-size 18 | 19 | */ 20 | 21 | var stylefill = { 22 | 23 | allRules : new Object(), 24 | 25 | allFills : new Object(), 26 | 27 | objSize : function(obj) { 28 | 29 | var size = 0, key; 30 | 31 | for (key in obj) { 32 | if (obj.hasOwnProperty(key)) size++; 33 | } 34 | 35 | return size; 36 | 37 | }, 38 | 39 | arraySliceShim : function () { // fixes Array.prototype.slice support for IE lt 9 40 | 41 | 'use strict'; 42 | var _slice = Array.prototype.slice; 43 | 44 | try { 45 | _slice.call(document.documentElement); 46 | } 47 | catch (e) { // Fails in IE < 9 48 | 49 | Array.prototype.slice = function (begin, end) { 50 | 51 | var i, arrl = this.length, a = []; 52 | 53 | if (this.charAt) { 54 | 55 | for (i = 0; i < arrl; i++) { 56 | a.push(this.charAt(i)); 57 | } 58 | 59 | } 60 | else { 61 | 62 | for (i = 0; i < this.length; i++) { 63 | a.push(this[i]); 64 | } 65 | 66 | } 67 | 68 | return _slice.call(a, begin, end || a.length); 69 | 70 | }; 71 | 72 | } 73 | 74 | }, 75 | 76 | init : function (params) { 77 | 78 | this.allFills = params; 79 | 80 | this.getStyleSheet(params); 81 | 82 | }, 83 | 84 | loadFile : function(params, url, scount) { 85 | 86 | var req; 87 | 88 | if (window.XMLHttpRequest) req = new XMLHttpRequest(); 89 | else req = new ActiveXObject("Microsoft.XMLHTTP"); 90 | 91 | req.open("GET", url, true); 92 | 93 | req.onreadystatechange = function() { 94 | 95 | if (this.readyState == 4 && this.status == 200) stylefill.findRules(params, this.responseText, scount); 96 | 97 | }; 98 | 99 | req.send(null); 100 | 101 | }, 102 | 103 | getStyleSheet : function (params) { 104 | 105 | var sheetstext = new Array(), 106 | sheets = Array.prototype.slice.call(document.getElementsByTagName('link')); // grab stylesheet links - not used yet 107 | 108 | sheets.push(Array.prototype.slice.call(document.getElementsByTagName('style'))[0]); // add on page CSS 109 | 110 | sheets.reverse(); 111 | 112 | var scount = this.objSize(sheets); 113 | 114 | while (scount-- > 0) { 115 | 116 | var sheet = sheets[scount]; 117 | 118 | if (sheet.innerHTML) this.findRules(params, sheet.innerHTML, scount); 119 | else if (sheet.href.match(document.domain)) this.loadFile(params, sheet.href, scount); 120 | 121 | } 122 | 123 | }, 124 | 125 | checkRule : function (property) { 126 | 127 | var propertyCamel = property.replace(/(^|-)([a-z])/g, function (m1, m2, m3) { return m3.toUpperCase(); }); 128 | 129 | if (('Webkit' + propertyCamel) in document.body.style 130 | || ('Moz' + propertyCamel) in document.body.style 131 | || ('O' + propertyCamel) in document.body.style 132 | || property in document.body.style) return true; 133 | 134 | else return false; 135 | 136 | }, 137 | 138 | findRules : function (params, sheettext, scount) { 139 | 140 | if (sheettext) { 141 | 142 | var pcount = this.objSize(params); 143 | 144 | for (property in params) { 145 | 146 | var selreg = new RegExp('([^}{]+){([^}]+)?' + property.replace('-', '\\-') + '[\\s\\t]*:[\\s\\t]*([^;]+)', 'gi'), 147 | selmatch, 148 | 149 | support = stylefill.checkRule(property); 150 | 151 | while (selmatch = selreg.exec(sheettext)) { 152 | 153 | var sels = selmatch[1].replace(/^([\s\n\r\t]+|\/\*.*?\*\/)+/, '').replace(/[\s\n\r\t]+$/, ''), 154 | val = selmatch[3]; 155 | 156 | sels = sels.split(','); 157 | 158 | for (sel in sels) { 159 | 160 | var s = sels[sel]; 161 | 162 | if (!stylefill.allRules[s]) stylefill.allRules[s] = new Object(); 163 | stylefill.allRules[s][property] = { 164 | 'support': support, 165 | 'value': val 166 | }; 167 | 168 | } 169 | 170 | } 171 | 172 | } 173 | 174 | if (scount == 1) this.runFills(); 175 | 176 | } 177 | 178 | }, 179 | 180 | runFills : function () { 181 | 182 | var allRules = stylefill.allRules, 183 | allFills = stylefill.allFills; 184 | 185 | for (i in allRules) { 186 | 187 | var rules = allRules[i]; 188 | 189 | for (j in rules) { 190 | 191 | var rule = rules[j], 192 | func = allFills[j], 193 | 194 | newrule = { 195 | 196 | support : rule['support'], 197 | selector: i, 198 | property: j, 199 | value: rule['value'] 200 | 201 | }; 202 | 203 | func(newrule); 204 | 205 | } 206 | 207 | } 208 | 209 | }, 210 | 211 | binder : function (object, events, func) { 212 | 213 | var events = events.split(','), 214 | eventscount = events.length; 215 | 216 | while (eventscount-- > 0) { 217 | 218 | if (object.attachEvent) object.attachEvent('on' + events[eventscount].trim(), func); 219 | else object.addEventListener(events[eventscount].trim(), func, false); 220 | 221 | } 222 | 223 | } 224 | 225 | }; 226 | 227 | /* Begin min-max-font-size functions */ 228 | 229 | var typo = { 230 | 231 | minMaxFontSize : function (selector) { 232 | 233 | var eles = document.querySelectorAll(selector), 234 | elescount = eles.length; 235 | 236 | while (elescount-- > 0) { 237 | 238 | var ele = eles[elescount], 239 | 240 | selRules = stylefill.allRules[selector], 241 | max = selRules['max-font-size'] ? selRules['max-font-size']['value'] : false, 242 | min = (selRules['min-font-size']) ? selRules['min-font-size']['value'] : false; 243 | 244 | ele.style.fontSize = ''; 245 | 246 | var eleFontSize = parseFloat(window.getComputedStyle(ele, null).getPropertyValue('font-size')); 247 | 248 | if (min && eleFontSize <= parseFloat(min)) ele.style.fontSize = min; 249 | else if (max && eleFontSize >= parseFloat(max)) ele.style.fontSize = max; 250 | 251 | } 252 | 253 | } 254 | 255 | 256 | }; 257 | 258 | typo.maxFontSize = typo.minFontSize = function (rule) { 259 | 260 | typo.minMaxFontSize(rule.selector); 261 | 262 | stylefill.binder(window, 'resize', function () { typo.minMaxFontSize(rule.selector); }); 263 | 264 | }; 265 | 266 | // assign the CSS property to the function 267 | stylefill.init({ 268 | 'max-font-size' : typo.maxFontSize, 269 | 'min-font-size' : typo.minFontSize 270 | }); --------------------------------------------------------------------------------