├── .gitignore ├── .npmrc ├── .travis.yml ├── LICENSE ├── bin ├── dist.js └── readme │ ├── index.js │ └── index.md ├── dist └── gr8.css ├── index.js ├── package.json ├── readme.md ├── test.js ├── util.js ├── utils.js └── utils ├── background.js ├── column.js ├── dev.js ├── display.js ├── flex.js ├── float.js ├── margin.js ├── misc.js ├── opacity.js ├── overflow.js ├── padding.js ├── positioning.js ├── size.js └── type.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | npm-debug.log 4 | package-lock.json 5 | .npmignore 6 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | node_js: 2 | - '4' 3 | - '6' 4 | - '7' 5 | sudo: false 6 | language: node_js 7 | env: 8 | - CXX=g++-4.8 9 | addons: 10 | apt: 11 | sources: 12 | - ubuntu-toolchain-r-test 13 | packages: 14 | - g++-4.8 15 | - xvfb 16 | script: npm run test 17 | install: 18 | - export DISPLAY=':99.0' 19 | - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & 20 | - npm install 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Jon Gacnik 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /bin/dist.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | var gr8 = require('..') 4 | 5 | var packageInfo = JSON.parse(fs.readFileSync(path.join(__dirname, '/../package.json'), 'utf8')) 6 | 7 | var header = '/*!\n * gr8.css • v' + packageInfo.version + '\n * github.com/jongacnik/gr8\n */\n' 8 | var css = gr8() 9 | 10 | fs.writeFile('dist/gr8.css', header + css, function (err) { 11 | if (err) { 12 | return console.log(err) 13 | } 14 | 15 | console.log('gr8 generated and saved to gr8.css') 16 | }) 17 | -------------------------------------------------------------------------------- /bin/readme/index.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | var gr8utils = require('../../utils') 4 | 5 | var templates = {} 6 | 7 | templates['defaults'] = JSON.stringify(gr8utils.defaults, null, 2) 8 | 9 | templates['utilityKeys'] = Object.keys(gr8utils.utils).map(function (key) { 10 | return '`' + key + '`' 11 | }).join(', ') 12 | 13 | templates['utilityIndex'] = Object.keys(gr8utils.utils).map(function (key) { 14 | return '- [' + key + '](#' + key + ')' 15 | }).join('\n') 16 | 17 | templates['utilitySections'] = Object.keys(gr8utils.utils).map(function (key) { 18 | var utils = {} 19 | utils[key] = gr8utils.utils[key] 20 | var css = gr8utils.generate(utils) 21 | return [ 22 | `
`, 23 | `${key}`, 24 | '', 25 | '```css', 26 | css, 27 | '```', 28 | '', 29 | '
' 30 | ].join('\n') 31 | }).join('\n\n') 32 | 33 | var readme = fs.readFileSync(path.join(__dirname, '/index.md'), 'utf8') 34 | 35 | // d.i.y. {{ templates }} 36 | function tinyBars (str, data) { 37 | var re = /\{\{(.+)\}\}/gi 38 | return str.replace(re, function (match, val) { 39 | return data[val.trim()] || '' 40 | }) 41 | } 42 | 43 | readme = tinyBars(readme, templates) 44 | 45 | fs.writeFile('readme.md', readme, function (err) { 46 | if (err) { 47 | return console.log(err) 48 | } 49 | 50 | console.log('readme generated and saved to readme.md') 51 | }) 52 | -------------------------------------------------------------------------------- /bin/readme/index.md: -------------------------------------------------------------------------------- 1 |

gr8

2 | 3 |
4 | 5 | NPM version 6 | 7 | 8 | NPM version 9 | 10 | 11 | Website 12 | 13 |
14 | 15 |
16 | 17 | Customizable, functional css utilities built using [**gr8-util**](https://github.com/jongacnik/gr8-util). Includes: 18 | 19 | - [**css stylesheet**](#stylesheet-usage) with default utilities 20 | - [**`gr8` function**](#javascript-usage) to generate and customize utilities within javascript 21 | 22 | ## Usage 23 | 24 | ### stylesheet usage 25 | 26 | The simplest way to use `gr8` is to include the [gr8.css](https://github.com/jongacnik/gr8/blob/master/dist/gr8.css) stylesheet in your project: 27 | 28 | ```html 29 | 30 | ``` 31 | 32 | ### javascript usage 33 | 34 | Use the `gr8` function to generate utilities: 35 | 36 | ```js 37 | var gr8 = require('gr8') 38 | var css = gr8() 39 | ``` 40 | 41 | [Detailed usage →](#api) 42 | 43 | ## Utilities 44 | 45 | Default utilities: 46 | 47 | {{ utilitySections }} 48 | 49 | ## API 50 | 51 | ### `css = gr8([opts])` 52 | 53 | Generate utilities and return a string of css. `opts` accepts the following values: 54 | 55 | #### Value Options 56 | 57 | - `opts.spacing` **[Mixed]** values for [margin](#margin) & [padding](#padding) utilities 58 | - `opts.fontSize` **[Mixed]** values for [font-size](#typography) utilities 59 | - `opts.lineHeight` **[Mixed]** values for [line-height](#typography) utilities 60 | - `opts.size` **[Mixed]** values for [width & height](#size) utilities 61 | - `opts.viewport` **[Mixed]** values for [viewport](#size) utilities 62 | - `opts.zIndex` **[Mixed]** values for [zIndex](#positioning) utilities 63 | - `opts.flexOrder` **[Mixed]** values for [flex-order](#flex) utilities 64 | - `opts.opacity` **[Mixed]** values for [opacity](#opacity) utilities 65 | - `opts.aspectRatio` **[Mixed]** values for [aspect ratio](#size) utilities 66 | - `opts.textColumn` **[Mixed]** values for [text columns](#typography) utilities 67 | 68 | #### Selector Options 69 | 70 | - `opts.selector` **[Function]** css selector template function 71 | - `opts.breakpoints` **[Object]** values for breakpoint utilities 72 | - `opts.breakpointSelector` **[String | Function]** selector shortcut or css selector template function 73 | 74 | #### Custom Utilities Options 75 | 76 | - `opts.utils` **[Array]** custom [gr8-util](https://github.com/jongacnik/gr8-util) utilities 77 | - `opts.exclude` **[Array]** keys of default utilities to exclude 78 | 79 | ## Value Options 80 | 81 | Value options customize numeric `gr8` utilities. They accept Numbers, Strings, Arrays, or Objects. Typically Arrays of Numbers will be used. Refer to [gr8-util](https://github.com/jongacnik/gr8-util) for details on all possible ways to format values. 82 | 83 | **Defaults:** 84 | 85 | ```js 86 | var css = gr8({ 87 | spacing: [0, 1, 2, 3, 4], 88 | fontSize: [1, 1.2, 1.6, 2.4, 3.2, 6.4], 89 | lineHeight: [1, 1.5], 90 | size: [0, 100], 91 | viewport: [50, 100], 92 | zIndex: [0, 1, 2, 3, 4], 93 | flexOrder: [0, 1, 2, 3, 4], 94 | opacity: [0, 25, 50, 75, 100], 95 | aspectRatio: [25, 50, 75, 100], 96 | textColumn: [1, 2, 3, 4] 97 | }) 98 | ``` 99 | 100 | ## Selector Options 101 | 102 | Selector options control selectors & breakpoints. 103 | 104 | **Defaults:** 105 | 106 | ```js 107 | var css = gr8({ 108 | selector: s => `.${s}`, 109 | breakpoints: { 110 | sm: 768, 111 | md: 1024, 112 | lg: 1280 113 | }, 114 | breakpointSelector: 'attribute' 115 | }) 116 | ``` 117 | 118 | ### `opts.selector` 119 | 120 | Function expects a selector name as input and returns a css selector string as output. For example, to use an attribute selector instead of classes: 121 | 122 | ```js 123 | var css = gr8({ 124 | selector: s => `[gr8~="${s}"]` 125 | }) 126 | ``` 127 | 128 |
129 | Output 130 | 131 | ```css 132 | [gr8~="fs1"]{font-size:1rem} 133 | [gr8~="fs1-6"]{font-size:1.6rem} 134 | /* etc... */ 135 | ``` 136 | 137 |
138 | 139 | ### `opts.breakpoints` 140 | 141 | Object keys are used in selector names and object values are used to define the media queries. Object values can either be integers (which results in a `min-width` media queries), or object values can be media query strings. Pass `false` to disable breakpoint utilities entirely: 142 | 143 | ```js 144 | var css = gr8({ 145 | breakpoints: { 146 | small: 1024, 147 | medium: '(min-width:768px) and (max-width:1280px)', 148 | 'not-big': '(max-width:1024px)', 149 | portrait: '(orientation:portrait)' 150 | } 151 | }) 152 | ``` 153 | 154 |
155 | Output 156 | 157 | ```css 158 | @media (min-width:1024px) { 159 | [small~="fs1"]{font-size:1rem} 160 | /* etc... */ 161 | } 162 | @media (min-width:768px) and (max-width:1280px) { 163 | [medium~="fs1"]{font-size:1rem} 164 | /* etc... */ 165 | } 166 | @media (max-width:1024px) { 167 | [not-big~="fs1"]{font-size:1rem} 168 | /* etc... */ 169 | } 170 | @media (orientation:portrait) { 171 | [portrait~="fs1"]{font-size:1rem} 172 | /* etc... */ 173 | } 174 | ``` 175 | 176 |

177 | 178 | **Note:** If you care about valid attribute selectors, prepend `data-` to your breakpoint keys. 179 | 180 | ### `opts.breakpointSelector` 181 | 182 | By default, attribute selectors are generated for breakpoint utilities (as seen above). Use prefixed classes instead by passing in the `'class'` shortcut, or provide a selector function for more granular control: 183 | 184 | #### `'class'` Shortcut 185 | 186 | ```js 187 | var css = gr8({ 188 | breakpointSelector: 'class' 189 | }) 190 | ``` 191 | 192 |
193 | Output 194 | 195 | ```css 196 | @media (min-width:768px) { 197 | .sm-fs1{font-size:1rem} 198 | /* etc... */ 199 | } 200 | @media (min-width:1024px) { 201 | .md-fs1{font-size:1rem} 202 | /* etc... */ 203 | } 204 | @media (min-width:1280px) { 205 | .lg-fs1{font-size:1rem} 206 | /* etc... */ 207 | } 208 | ``` 209 | 210 |
211 | 212 | #### Selector Function 213 | 214 | 215 | ```js 216 | var css = gr8({ 217 | breakpointSelector: key => s => `.gr8-${key}-${s}` 218 | }) 219 | ``` 220 | 221 |
222 | Output 223 | 224 | ```css 225 | @media (min-width:768px) { 226 | .gr8-sm-fs1{font-size:1rem} 227 | /* etc... */ 228 | } 229 | @media (min-width:1024px) { 230 | .gr8-md-fs1{font-size:1rem} 231 | /* etc... */ 232 | } 233 | @media (min-width:1280px) { 234 | .gr8-lg-fs1{font-size:1rem} 235 | /* etc... */ 236 | } 237 | ``` 238 | 239 |
240 | 241 | ## Custom Utilities Options 242 | 243 | [gr8-util](https://github.com/jongacnik/gr8-util) is a little function for generating functional css utilities. Given a plain object, concise css utilities are generated. All the utilities in `gr8` are built using this. 244 | 245 | Use the `utils` option to pass an array of `gr8-util` objects to extend the `gr8` output with custom utilities: 246 | 247 | ```js 248 | var bgcolor = { 249 | prop: { 250 | bgc: 'background-color' 251 | }, 252 | vals: ['red', 'blue', 'green'] 253 | } 254 | 255 | var fontcolor = { 256 | prop: { 257 | fc: 'color' 258 | }, 259 | vals: ['red', 'blue', 'green'] 260 | } 261 | 262 | var css = gr8({ 263 | utils: [ 264 | bgcolor, 265 | fontcolor 266 | ] 267 | }) 268 | ``` 269 | 270 |
271 | Output 272 | 273 | ```css 274 | .bgcr{background-color:red} 275 | .bgcb{background-color:blue} 276 | .bgcg{background-color:green} 277 | .fcr{color:red} 278 | .fcb{color:blue} 279 | .fcg{color:green} 280 | /* etc... */ 281 | 282 | @media (min-width:768px) { 283 | [sm~="bgcr"]{background-color:red} 284 | [sm~="bgcb"]{background-color:blue} 285 | [sm~="bgcg"]{background-color:green} 286 | [sm~="fcr"]{color:red} 287 | [sm~="fcb"]{color:blue} 288 | [sm~="fcg"]{color:green} 289 | /* etc... */ 290 | } 291 | 292 | @media (min-width:1024px) { 293 | [md~="bgcr"]{background-color:red} 294 | [md~="bgcb"]{background-color:blue} 295 | [md~="bgcg"]{background-color:green} 296 | [md~="fcr"]{color:red} 297 | [md~="fcb"]{color:blue} 298 | [md~="fcg"]{color:green} 299 | /* etc... */ 300 | } 301 | 302 | @media (min-width:1280px) { 303 | [lg~="bgcr"]{background-color:red} 304 | [lg~="bgcb"]{background-color:blue} 305 | [lg~="bgcg"]{background-color:green} 306 | [lg~="fcr"]{color:red} 307 | [lg~="fcb"]{color:blue} 308 | [lg~="fcg"]{color:green} 309 | /* etc... */ 310 | } 311 | ``` 312 | 313 |

314 | 315 | **[Refer to gr8-util for further documentation on generating custom utilities.](https://github.com/jongacnik/gr8-util)** 316 | 317 | ### `opts.exclude` 318 | 319 | Use the `exclude` option to remove some of the default utilities. Accepts an array with any of the following values: 320 | 321 | {{ utilityKeys }} 322 | 323 | ## Proxies 324 | 325 | For more advanced use cases, some additional methods are proxied: 326 | 327 | ```js 328 | // direct access to gr8-util 329 | var gr8util = require('gr8/util') 330 | var css = gr8util({options}) 331 | ``` 332 | 333 | ```js 334 | // direct access to gr8-utils 335 | var gr8utils = require('gr8/utils') 336 | var css = gr8utils({options}) 337 | 338 | // or even lower level 339 | gr8utils.generate(gr8utils.utils, gr8utils.defaults) 340 | ``` 341 | 342 | ## Notes 343 | 344 | `gr8` is developed and iterated-on primarily for use within projects at [Folder Studio](http://folderstudio.com). It shares similarities with other functional css libraries like [tachyons](https://github.com/tachyons-css/tachyons) or [basscss](https://github.com/basscss/basscss), but diverges in its minimalism and customizability. `gr8` provides no colors, no borders, no font-families, etc out of the box, but instead provides ways to quickly define your own utilities for things like these using plain objects. It facilitates creating coherent design systems without imposing one by default. 345 | 346 | In any case, I hope you like it and perhaps find it useful! 347 | 348 | ## Todo 349 | 350 | - [ ] Advanced documentation 351 | - [ ] Website 352 | 353 | ## See Also 354 | 355 | - [gr8-util](https://github.com/jongacnik/gr8-util) 356 | 357 | ## License 358 | 359 | [MIT](https://github.com/jongacnik/gr8/blob/master/LICENSE) 360 | -------------------------------------------------------------------------------- /dist/gr8.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * gr8.css • v3.1.3 3 | * github.com/jongacnik/gr8 4 | */ 5 | .c1{width:8.33333%} 6 | .c2{width:16.66667%} 7 | .c3{width:25%} 8 | .c4{width:33.33333%} 9 | .c5{width:41.66667%} 10 | .c6{width:50%} 11 | .c7{width:58.33333%} 12 | .c8{width:66.66667%} 13 | .c9{width:75%} 14 | .c10{width:83.33333%} 15 | .c11{width:91.66667%} 16 | .c12{width:100%} 17 | .s1{width:100%} 18 | .s2{width:50%} 19 | .s3{width:33.33333%} 20 | .s4{width:25%} 21 | .s5{width:20%} 22 | .s6{width:16.66667%} 23 | .s7{width:14.28571%} 24 | .s8{width:12.5%} 25 | .s9{width:11.11111%} 26 | .s10{width:10%} 27 | .s11{width:9.09091%} 28 | .s12{width:8.33333%} 29 | .co0{margin-left:0} 30 | .co1{margin-left:8.33333%} 31 | .co2{margin-left:16.66667%} 32 | .co3{margin-left:25%} 33 | .co4{margin-left:33.33333%} 34 | .co5{margin-left:41.66667%} 35 | .co6{margin-left:50%} 36 | .co7{margin-left:58.33333%} 37 | .co8{margin-left:66.66667%} 38 | .co9{margin-left:75%} 39 | .co10{margin-left:83.33333%} 40 | .co11{margin-left:91.66667%} 41 | .co12{margin-left:100%} 42 | .m0{margin:0} 43 | .m1{margin:1rem} 44 | .m2{margin:2rem} 45 | .m3{margin:3rem} 46 | .m4{margin:4rem} 47 | .mt0{margin-top:0} 48 | .mt1{margin-top:1rem} 49 | .mt2{margin-top:2rem} 50 | .mt3{margin-top:3rem} 51 | .mt4{margin-top:4rem} 52 | .mr0{margin-right:0} 53 | .mr1{margin-right:1rem} 54 | .mr2{margin-right:2rem} 55 | .mr3{margin-right:3rem} 56 | .mr4{margin-right:4rem} 57 | .mb0{margin-bottom:0} 58 | .mb1{margin-bottom:1rem} 59 | .mb2{margin-bottom:2rem} 60 | .mb3{margin-bottom:3rem} 61 | .mb4{margin-bottom:4rem} 62 | .ml0{margin-left:0} 63 | .ml1{margin-left:1rem} 64 | .ml2{margin-left:2rem} 65 | .ml3{margin-left:3rem} 66 | .ml4{margin-left:4rem} 67 | .mx0{margin-left:0;margin-right:0} 68 | .mx1{margin-left:1rem;margin-right:1rem} 69 | .mx2{margin-left:2rem;margin-right:2rem} 70 | .mx3{margin-left:3rem;margin-right:3rem} 71 | .mx4{margin-left:4rem;margin-right:4rem} 72 | .my0{margin-top:0;margin-bottom:0} 73 | .my1{margin-top:1rem;margin-bottom:1rem} 74 | .my2{margin-top:2rem;margin-bottom:2rem} 75 | .my3{margin-top:3rem;margin-bottom:3rem} 76 | .my4{margin-top:4rem;margin-bottom:4rem} 77 | .p0{padding:0} 78 | .p1{padding:1rem} 79 | .p2{padding:2rem} 80 | .p3{padding:3rem} 81 | .p4{padding:4rem} 82 | .pt0{padding-top:0} 83 | .pt1{padding-top:1rem} 84 | .pt2{padding-top:2rem} 85 | .pt3{padding-top:3rem} 86 | .pt4{padding-top:4rem} 87 | .pr0{padding-right:0} 88 | .pr1{padding-right:1rem} 89 | .pr2{padding-right:2rem} 90 | .pr3{padding-right:3rem} 91 | .pr4{padding-right:4rem} 92 | .pb0{padding-bottom:0} 93 | .pb1{padding-bottom:1rem} 94 | .pb2{padding-bottom:2rem} 95 | .pb3{padding-bottom:3rem} 96 | .pb4{padding-bottom:4rem} 97 | .pl0{padding-left:0} 98 | .pl1{padding-left:1rem} 99 | .pl2{padding-left:2rem} 100 | .pl3{padding-left:3rem} 101 | .pl4{padding-left:4rem} 102 | .px0{padding-left:0;padding-right:0} 103 | .px1{padding-left:1rem;padding-right:1rem} 104 | .px2{padding-left:2rem;padding-right:2rem} 105 | .px3{padding-left:3rem;padding-right:3rem} 106 | .px4{padding-left:4rem;padding-right:4rem} 107 | .py0{padding-top:0;padding-bottom:0} 108 | .py1{padding-top:1rem;padding-bottom:1rem} 109 | .py2{padding-top:2rem;padding-bottom:2rem} 110 | .py3{padding-top:3rem;padding-bottom:3rem} 111 | .py4{padding-top:4rem;padding-bottom:4rem} 112 | .op0{opacity:0} 113 | .op25{opacity:0.25} 114 | .op50{opacity:0.5} 115 | .op75{opacity:0.75} 116 | .op100{opacity:1} 117 | .bgsc{background-size:cover} 118 | .bgsct{background-size:contain} 119 | .bgpc{background-position:center} 120 | .bgpt{background-position:top} 121 | .bgpr{background-position:right} 122 | .bgpb{background-position:bottom} 123 | .bgpl{background-position:left} 124 | .bgrn{background-repeat:no-repeat} 125 | .bgrx{background-repeat:repeat-x} 126 | .bgry{background-repeat:repeat-y} 127 | .x{display:flex} 128 | .xac{align-items:center} 129 | .xab{align-items:baseline} 130 | .xas{align-items:stretch} 131 | .xafs{align-items:flex-start} 132 | .xafe{align-items:flex-end} 133 | .xdr{flex-direction:row} 134 | .xdrr{flex-direction:row-reverse} 135 | .xdc{flex-direction:column} 136 | .xdcr{flex-direction:column-reverse} 137 | .xjc{justify-content:center} 138 | .xjb{justify-content:space-between} 139 | .xja{justify-content:space-around} 140 | .xjs{justify-content:flex-start} 141 | .xje{justify-content:flex-end} 142 | .xw{flex-wrap:wrap} 143 | .xwr{flex-wrap:wrap-reverse} 144 | .xwn{flex-wrap:nowrap} 145 | .xi{flex:initial} 146 | .xx{flex:1} 147 | .xa{flex:auto} 148 | .xn{flex:none} 149 | .xo0{order:0} 150 | .xo1{order:1} 151 | .xo2{order:2} 152 | .xo3{order:3} 153 | .xo4{order:4} 154 | .xot{order:-1} 155 | .xob{order:99} 156 | .df{display:flex} 157 | .db{display:block} 158 | .dib{display:inline-block} 159 | .di{display:inline} 160 | .dt{display:table} 161 | .dtc{display:table-cell} 162 | .dtr{display:table-row} 163 | .dn{display:none} 164 | .fl{float:left} 165 | .fr{float:right} 166 | .fn{float:none} 167 | .cf:after{content:"";display:block;clear:both} 168 | .oh{overflow:hidden} 169 | .os{overflow:scroll} 170 | .ov{overflow:visible} 171 | .oxh{overflow-x:hidden} 172 | .oxs{overflow-x:scroll} 173 | .oxv{overflow-x:visible} 174 | .oyh{overflow-y:hidden} 175 | .oys{overflow-y:scroll} 176 | .oyv{overflow-y:visible} 177 | .psa{position:absolute} 178 | .psr{position:relative} 179 | .psf{position:fixed} 180 | .pss{position:static} 181 | .t0{top:0} 182 | .r0{right:0} 183 | .b0{bottom:0} 184 | .l0{left:0} 185 | .z0{z-index:0} 186 | .z1{z-index:1} 187 | .z2{z-index:2} 188 | .z3{z-index:3} 189 | .z4{z-index:4} 190 | .w0{width:0} 191 | .w100{width:100%} 192 | .h0{height:0} 193 | .h100{height:100%} 194 | .vw50{width:50vw} 195 | .vw100{width:100vw} 196 | .vwmn50{min-width:50vw} 197 | .vwmn100{min-width:100vw} 198 | .vwmx50{max-width:50vw} 199 | .vwmx100{max-width:100vw} 200 | .vh50{height:50vh} 201 | .vh100{height:100vh} 202 | .vhmn50{min-height:50vh} 203 | .vhmn100{min-height:100vh} 204 | .vhmx50{max-height:50vh} 205 | .vhmx100{max-height:100vh} 206 | .ar25:before{padding-top:25%;content:"";display:block} 207 | .ar50:before{padding-top:50%;content:"";display:block} 208 | .ar75:before{padding-top:75%;content:"";display:block} 209 | .ar100:before{padding-top:100%;content:"";display:block} 210 | .fs1{font-size:1rem} 211 | .fs1-2{font-size:1.2rem} 212 | .fs1-6{font-size:1.6rem} 213 | .fs2-4{font-size:2.4rem} 214 | .fs3-2{font-size:3.2rem} 215 | .fs6-4{font-size:6.4rem} 216 | .lh1{line-height:1} 217 | .lh1-5{line-height:1.5} 218 | .fsn{font-style:normal} 219 | .fsi{font-style:italic} 220 | .fwn{font-weight:normal} 221 | .fwb{font-weight:bold} 222 | .tal{text-align:left} 223 | .tac{text-align:center} 224 | .tar{text-align:right} 225 | .taj{text-align:justify} 226 | .toi{text-overflow:initial} 227 | .toc{text-overflow:clip} 228 | .toe{text-overflow:ellipsis} 229 | .tdu{text-decoration:underline} 230 | .tdo{text-decoration:overline} 231 | .tdlt{text-decoration:line-through} 232 | .tdn{text-decoration:none} 233 | .ttu{text-transform:uppercase} 234 | .ttl{text-transform:lowercase} 235 | .ttc{text-transform:capitalize} 236 | .ttn{text-transform:none} 237 | .vabl{vertical-align:baseline} 238 | .vat{vertical-align:top} 239 | .vam{vertical-align:middle} 240 | .vab{vertical-align:bottom} 241 | .wsn{white-space:normal} 242 | .wsnw{white-space:nowrap} 243 | .wsp{white-space:pre} 244 | .wsi{white-space:inherit} 245 | .tc1{columns:1} 246 | .tc2{columns:2} 247 | .tc3{columns:3} 248 | .tc4{columns:4} 249 | .curp{cursor:pointer} 250 | .curd{cursor:default} 251 | .cura{cursor:alias} 252 | .curzi{cursor:zoom-in} 253 | .curzo{cursor:zoom-out} 254 | .usn{user-select:none} 255 | .usa{user-select:auto} 256 | .ust{user-select:text} 257 | .pen{pointer-events:none} 258 | .pea{pointer-events:auto} 259 | .vh{visibility:hidden} 260 | .vv{visibility:visible} 261 | .dev{outline:1px solid #912eff} 262 | .dev > * {outline:1px solid #5497ff} 263 | .dev > * > * {outline:1px solid #51feff} 264 | .dev > * > * > * {outline:1px solid #ff0000} 265 | .dev > * > * > * * {outline:1px solid #00ff00} 266 | @media (min-width:768px) { 267 | [sm~="c1"]{width:8.33333%} 268 | [sm~="c2"]{width:16.66667%} 269 | [sm~="c3"]{width:25%} 270 | [sm~="c4"]{width:33.33333%} 271 | [sm~="c5"]{width:41.66667%} 272 | [sm~="c6"]{width:50%} 273 | [sm~="c7"]{width:58.33333%} 274 | [sm~="c8"]{width:66.66667%} 275 | [sm~="c9"]{width:75%} 276 | [sm~="c10"]{width:83.33333%} 277 | [sm~="c11"]{width:91.66667%} 278 | [sm~="c12"]{width:100%} 279 | [sm~="s1"]{width:100%} 280 | [sm~="s2"]{width:50%} 281 | [sm~="s3"]{width:33.33333%} 282 | [sm~="s4"]{width:25%} 283 | [sm~="s5"]{width:20%} 284 | [sm~="s6"]{width:16.66667%} 285 | [sm~="s7"]{width:14.28571%} 286 | [sm~="s8"]{width:12.5%} 287 | [sm~="s9"]{width:11.11111%} 288 | [sm~="s10"]{width:10%} 289 | [sm~="s11"]{width:9.09091%} 290 | [sm~="s12"]{width:8.33333%} 291 | [sm~="co0"]{margin-left:0} 292 | [sm~="co1"]{margin-left:8.33333%} 293 | [sm~="co2"]{margin-left:16.66667%} 294 | [sm~="co3"]{margin-left:25%} 295 | [sm~="co4"]{margin-left:33.33333%} 296 | [sm~="co5"]{margin-left:41.66667%} 297 | [sm~="co6"]{margin-left:50%} 298 | [sm~="co7"]{margin-left:58.33333%} 299 | [sm~="co8"]{margin-left:66.66667%} 300 | [sm~="co9"]{margin-left:75%} 301 | [sm~="co10"]{margin-left:83.33333%} 302 | [sm~="co11"]{margin-left:91.66667%} 303 | [sm~="co12"]{margin-left:100%} 304 | [sm~="m0"]{margin:0} 305 | [sm~="m1"]{margin:1rem} 306 | [sm~="m2"]{margin:2rem} 307 | [sm~="m3"]{margin:3rem} 308 | [sm~="m4"]{margin:4rem} 309 | [sm~="mt0"]{margin-top:0} 310 | [sm~="mt1"]{margin-top:1rem} 311 | [sm~="mt2"]{margin-top:2rem} 312 | [sm~="mt3"]{margin-top:3rem} 313 | [sm~="mt4"]{margin-top:4rem} 314 | [sm~="mr0"]{margin-right:0} 315 | [sm~="mr1"]{margin-right:1rem} 316 | [sm~="mr2"]{margin-right:2rem} 317 | [sm~="mr3"]{margin-right:3rem} 318 | [sm~="mr4"]{margin-right:4rem} 319 | [sm~="mb0"]{margin-bottom:0} 320 | [sm~="mb1"]{margin-bottom:1rem} 321 | [sm~="mb2"]{margin-bottom:2rem} 322 | [sm~="mb3"]{margin-bottom:3rem} 323 | [sm~="mb4"]{margin-bottom:4rem} 324 | [sm~="ml0"]{margin-left:0} 325 | [sm~="ml1"]{margin-left:1rem} 326 | [sm~="ml2"]{margin-left:2rem} 327 | [sm~="ml3"]{margin-left:3rem} 328 | [sm~="ml4"]{margin-left:4rem} 329 | [sm~="mx0"]{margin-left:0;margin-right:0} 330 | [sm~="mx1"]{margin-left:1rem;margin-right:1rem} 331 | [sm~="mx2"]{margin-left:2rem;margin-right:2rem} 332 | [sm~="mx3"]{margin-left:3rem;margin-right:3rem} 333 | [sm~="mx4"]{margin-left:4rem;margin-right:4rem} 334 | [sm~="my0"]{margin-top:0;margin-bottom:0} 335 | [sm~="my1"]{margin-top:1rem;margin-bottom:1rem} 336 | [sm~="my2"]{margin-top:2rem;margin-bottom:2rem} 337 | [sm~="my3"]{margin-top:3rem;margin-bottom:3rem} 338 | [sm~="my4"]{margin-top:4rem;margin-bottom:4rem} 339 | [sm~="p0"]{padding:0} 340 | [sm~="p1"]{padding:1rem} 341 | [sm~="p2"]{padding:2rem} 342 | [sm~="p3"]{padding:3rem} 343 | [sm~="p4"]{padding:4rem} 344 | [sm~="pt0"]{padding-top:0} 345 | [sm~="pt1"]{padding-top:1rem} 346 | [sm~="pt2"]{padding-top:2rem} 347 | [sm~="pt3"]{padding-top:3rem} 348 | [sm~="pt4"]{padding-top:4rem} 349 | [sm~="pr0"]{padding-right:0} 350 | [sm~="pr1"]{padding-right:1rem} 351 | [sm~="pr2"]{padding-right:2rem} 352 | [sm~="pr3"]{padding-right:3rem} 353 | [sm~="pr4"]{padding-right:4rem} 354 | [sm~="pb0"]{padding-bottom:0} 355 | [sm~="pb1"]{padding-bottom:1rem} 356 | [sm~="pb2"]{padding-bottom:2rem} 357 | [sm~="pb3"]{padding-bottom:3rem} 358 | [sm~="pb4"]{padding-bottom:4rem} 359 | [sm~="pl0"]{padding-left:0} 360 | [sm~="pl1"]{padding-left:1rem} 361 | [sm~="pl2"]{padding-left:2rem} 362 | [sm~="pl3"]{padding-left:3rem} 363 | [sm~="pl4"]{padding-left:4rem} 364 | [sm~="px0"]{padding-left:0;padding-right:0} 365 | [sm~="px1"]{padding-left:1rem;padding-right:1rem} 366 | [sm~="px2"]{padding-left:2rem;padding-right:2rem} 367 | [sm~="px3"]{padding-left:3rem;padding-right:3rem} 368 | [sm~="px4"]{padding-left:4rem;padding-right:4rem} 369 | [sm~="py0"]{padding-top:0;padding-bottom:0} 370 | [sm~="py1"]{padding-top:1rem;padding-bottom:1rem} 371 | [sm~="py2"]{padding-top:2rem;padding-bottom:2rem} 372 | [sm~="py3"]{padding-top:3rem;padding-bottom:3rem} 373 | [sm~="py4"]{padding-top:4rem;padding-bottom:4rem} 374 | [sm~="op0"]{opacity:0} 375 | [sm~="op25"]{opacity:0.25} 376 | [sm~="op50"]{opacity:0.5} 377 | [sm~="op75"]{opacity:0.75} 378 | [sm~="op100"]{opacity:1} 379 | [sm~="bgsc"]{background-size:cover} 380 | [sm~="bgsct"]{background-size:contain} 381 | [sm~="bgpc"]{background-position:center} 382 | [sm~="bgpt"]{background-position:top} 383 | [sm~="bgpr"]{background-position:right} 384 | [sm~="bgpb"]{background-position:bottom} 385 | [sm~="bgpl"]{background-position:left} 386 | [sm~="bgrn"]{background-repeat:no-repeat} 387 | [sm~="bgrx"]{background-repeat:repeat-x} 388 | [sm~="bgry"]{background-repeat:repeat-y} 389 | [sm~="x"]{display:flex} 390 | [sm~="xac"]{align-items:center} 391 | [sm~="xab"]{align-items:baseline} 392 | [sm~="xas"]{align-items:stretch} 393 | [sm~="xafs"]{align-items:flex-start} 394 | [sm~="xafe"]{align-items:flex-end} 395 | [sm~="xdr"]{flex-direction:row} 396 | [sm~="xdrr"]{flex-direction:row-reverse} 397 | [sm~="xdc"]{flex-direction:column} 398 | [sm~="xdcr"]{flex-direction:column-reverse} 399 | [sm~="xjc"]{justify-content:center} 400 | [sm~="xjb"]{justify-content:space-between} 401 | [sm~="xja"]{justify-content:space-around} 402 | [sm~="xjs"]{justify-content:flex-start} 403 | [sm~="xje"]{justify-content:flex-end} 404 | [sm~="xw"]{flex-wrap:wrap} 405 | [sm~="xwr"]{flex-wrap:wrap-reverse} 406 | [sm~="xwn"]{flex-wrap:nowrap} 407 | [sm~="xi"]{flex:initial} 408 | [sm~="xx"]{flex:1} 409 | [sm~="xa"]{flex:auto} 410 | [sm~="xn"]{flex:none} 411 | [sm~="xo0"]{order:0} 412 | [sm~="xo1"]{order:1} 413 | [sm~="xo2"]{order:2} 414 | [sm~="xo3"]{order:3} 415 | [sm~="xo4"]{order:4} 416 | [sm~="xot"]{order:-1} 417 | [sm~="xob"]{order:99} 418 | [sm~="df"]{display:flex} 419 | [sm~="db"]{display:block} 420 | [sm~="dib"]{display:inline-block} 421 | [sm~="di"]{display:inline} 422 | [sm~="dt"]{display:table} 423 | [sm~="dtc"]{display:table-cell} 424 | [sm~="dtr"]{display:table-row} 425 | [sm~="dn"]{display:none} 426 | [sm~="fl"]{float:left} 427 | [sm~="fr"]{float:right} 428 | [sm~="fn"]{float:none} 429 | [sm~="cf"]:after{content:"";display:block;clear:both} 430 | [sm~="oh"]{overflow:hidden} 431 | [sm~="os"]{overflow:scroll} 432 | [sm~="ov"]{overflow:visible} 433 | [sm~="oxh"]{overflow-x:hidden} 434 | [sm~="oxs"]{overflow-x:scroll} 435 | [sm~="oxv"]{overflow-x:visible} 436 | [sm~="oyh"]{overflow-y:hidden} 437 | [sm~="oys"]{overflow-y:scroll} 438 | [sm~="oyv"]{overflow-y:visible} 439 | [sm~="psa"]{position:absolute} 440 | [sm~="psr"]{position:relative} 441 | [sm~="psf"]{position:fixed} 442 | [sm~="pss"]{position:static} 443 | [sm~="t0"]{top:0} 444 | [sm~="r0"]{right:0} 445 | [sm~="b0"]{bottom:0} 446 | [sm~="l0"]{left:0} 447 | [sm~="z0"]{z-index:0} 448 | [sm~="z1"]{z-index:1} 449 | [sm~="z2"]{z-index:2} 450 | [sm~="z3"]{z-index:3} 451 | [sm~="z4"]{z-index:4} 452 | [sm~="w0"]{width:0} 453 | [sm~="w100"]{width:100%} 454 | [sm~="h0"]{height:0} 455 | [sm~="h100"]{height:100%} 456 | [sm~="vw50"]{width:50vw} 457 | [sm~="vw100"]{width:100vw} 458 | [sm~="vwmn50"]{min-width:50vw} 459 | [sm~="vwmn100"]{min-width:100vw} 460 | [sm~="vwmx50"]{max-width:50vw} 461 | [sm~="vwmx100"]{max-width:100vw} 462 | [sm~="vh50"]{height:50vh} 463 | [sm~="vh100"]{height:100vh} 464 | [sm~="vhmn50"]{min-height:50vh} 465 | [sm~="vhmn100"]{min-height:100vh} 466 | [sm~="vhmx50"]{max-height:50vh} 467 | [sm~="vhmx100"]{max-height:100vh} 468 | [sm~="ar25"]:before{padding-top:25%;content:"";display:block} 469 | [sm~="ar50"]:before{padding-top:50%;content:"";display:block} 470 | [sm~="ar75"]:before{padding-top:75%;content:"";display:block} 471 | [sm~="ar100"]:before{padding-top:100%;content:"";display:block} 472 | [sm~="fs1"]{font-size:1rem} 473 | [sm~="fs1-2"]{font-size:1.2rem} 474 | [sm~="fs1-6"]{font-size:1.6rem} 475 | [sm~="fs2-4"]{font-size:2.4rem} 476 | [sm~="fs3-2"]{font-size:3.2rem} 477 | [sm~="fs6-4"]{font-size:6.4rem} 478 | [sm~="lh1"]{line-height:1} 479 | [sm~="lh1-5"]{line-height:1.5} 480 | [sm~="fsn"]{font-style:normal} 481 | [sm~="fsi"]{font-style:italic} 482 | [sm~="fwn"]{font-weight:normal} 483 | [sm~="fwb"]{font-weight:bold} 484 | [sm~="tal"]{text-align:left} 485 | [sm~="tac"]{text-align:center} 486 | [sm~="tar"]{text-align:right} 487 | [sm~="taj"]{text-align:justify} 488 | [sm~="toi"]{text-overflow:initial} 489 | [sm~="toc"]{text-overflow:clip} 490 | [sm~="toe"]{text-overflow:ellipsis} 491 | [sm~="tdu"]{text-decoration:underline} 492 | [sm~="tdo"]{text-decoration:overline} 493 | [sm~="tdlt"]{text-decoration:line-through} 494 | [sm~="tdn"]{text-decoration:none} 495 | [sm~="ttu"]{text-transform:uppercase} 496 | [sm~="ttl"]{text-transform:lowercase} 497 | [sm~="ttc"]{text-transform:capitalize} 498 | [sm~="ttn"]{text-transform:none} 499 | [sm~="vabl"]{vertical-align:baseline} 500 | [sm~="vat"]{vertical-align:top} 501 | [sm~="vam"]{vertical-align:middle} 502 | [sm~="vab"]{vertical-align:bottom} 503 | [sm~="wsn"]{white-space:normal} 504 | [sm~="wsnw"]{white-space:nowrap} 505 | [sm~="wsp"]{white-space:pre} 506 | [sm~="wsi"]{white-space:inherit} 507 | [sm~="tc1"]{columns:1} 508 | [sm~="tc2"]{columns:2} 509 | [sm~="tc3"]{columns:3} 510 | [sm~="tc4"]{columns:4} 511 | [sm~="curp"]{cursor:pointer} 512 | [sm~="curd"]{cursor:default} 513 | [sm~="cura"]{cursor:alias} 514 | [sm~="curzi"]{cursor:zoom-in} 515 | [sm~="curzo"]{cursor:zoom-out} 516 | [sm~="usn"]{user-select:none} 517 | [sm~="usa"]{user-select:auto} 518 | [sm~="ust"]{user-select:text} 519 | [sm~="pen"]{pointer-events:none} 520 | [sm~="pea"]{pointer-events:auto} 521 | [sm~="vh"]{visibility:hidden} 522 | [sm~="vv"]{visibility:visible} 523 | [sm~="dev"]{outline:1px solid #912eff} 524 | [sm~="dev"] > * {outline:1px solid #5497ff} 525 | [sm~="dev"] > * > * {outline:1px solid #51feff} 526 | [sm~="dev"] > * > * > * {outline:1px solid #ff0000} 527 | [sm~="dev"] > * > * > * * {outline:1px solid #00ff00} 528 | } 529 | @media (min-width:1024px) { 530 | [md~="c1"]{width:8.33333%} 531 | [md~="c2"]{width:16.66667%} 532 | [md~="c3"]{width:25%} 533 | [md~="c4"]{width:33.33333%} 534 | [md~="c5"]{width:41.66667%} 535 | [md~="c6"]{width:50%} 536 | [md~="c7"]{width:58.33333%} 537 | [md~="c8"]{width:66.66667%} 538 | [md~="c9"]{width:75%} 539 | [md~="c10"]{width:83.33333%} 540 | [md~="c11"]{width:91.66667%} 541 | [md~="c12"]{width:100%} 542 | [md~="s1"]{width:100%} 543 | [md~="s2"]{width:50%} 544 | [md~="s3"]{width:33.33333%} 545 | [md~="s4"]{width:25%} 546 | [md~="s5"]{width:20%} 547 | [md~="s6"]{width:16.66667%} 548 | [md~="s7"]{width:14.28571%} 549 | [md~="s8"]{width:12.5%} 550 | [md~="s9"]{width:11.11111%} 551 | [md~="s10"]{width:10%} 552 | [md~="s11"]{width:9.09091%} 553 | [md~="s12"]{width:8.33333%} 554 | [md~="co0"]{margin-left:0} 555 | [md~="co1"]{margin-left:8.33333%} 556 | [md~="co2"]{margin-left:16.66667%} 557 | [md~="co3"]{margin-left:25%} 558 | [md~="co4"]{margin-left:33.33333%} 559 | [md~="co5"]{margin-left:41.66667%} 560 | [md~="co6"]{margin-left:50%} 561 | [md~="co7"]{margin-left:58.33333%} 562 | [md~="co8"]{margin-left:66.66667%} 563 | [md~="co9"]{margin-left:75%} 564 | [md~="co10"]{margin-left:83.33333%} 565 | [md~="co11"]{margin-left:91.66667%} 566 | [md~="co12"]{margin-left:100%} 567 | [md~="m0"]{margin:0} 568 | [md~="m1"]{margin:1rem} 569 | [md~="m2"]{margin:2rem} 570 | [md~="m3"]{margin:3rem} 571 | [md~="m4"]{margin:4rem} 572 | [md~="mt0"]{margin-top:0} 573 | [md~="mt1"]{margin-top:1rem} 574 | [md~="mt2"]{margin-top:2rem} 575 | [md~="mt3"]{margin-top:3rem} 576 | [md~="mt4"]{margin-top:4rem} 577 | [md~="mr0"]{margin-right:0} 578 | [md~="mr1"]{margin-right:1rem} 579 | [md~="mr2"]{margin-right:2rem} 580 | [md~="mr3"]{margin-right:3rem} 581 | [md~="mr4"]{margin-right:4rem} 582 | [md~="mb0"]{margin-bottom:0} 583 | [md~="mb1"]{margin-bottom:1rem} 584 | [md~="mb2"]{margin-bottom:2rem} 585 | [md~="mb3"]{margin-bottom:3rem} 586 | [md~="mb4"]{margin-bottom:4rem} 587 | [md~="ml0"]{margin-left:0} 588 | [md~="ml1"]{margin-left:1rem} 589 | [md~="ml2"]{margin-left:2rem} 590 | [md~="ml3"]{margin-left:3rem} 591 | [md~="ml4"]{margin-left:4rem} 592 | [md~="mx0"]{margin-left:0;margin-right:0} 593 | [md~="mx1"]{margin-left:1rem;margin-right:1rem} 594 | [md~="mx2"]{margin-left:2rem;margin-right:2rem} 595 | [md~="mx3"]{margin-left:3rem;margin-right:3rem} 596 | [md~="mx4"]{margin-left:4rem;margin-right:4rem} 597 | [md~="my0"]{margin-top:0;margin-bottom:0} 598 | [md~="my1"]{margin-top:1rem;margin-bottom:1rem} 599 | [md~="my2"]{margin-top:2rem;margin-bottom:2rem} 600 | [md~="my3"]{margin-top:3rem;margin-bottom:3rem} 601 | [md~="my4"]{margin-top:4rem;margin-bottom:4rem} 602 | [md~="p0"]{padding:0} 603 | [md~="p1"]{padding:1rem} 604 | [md~="p2"]{padding:2rem} 605 | [md~="p3"]{padding:3rem} 606 | [md~="p4"]{padding:4rem} 607 | [md~="pt0"]{padding-top:0} 608 | [md~="pt1"]{padding-top:1rem} 609 | [md~="pt2"]{padding-top:2rem} 610 | [md~="pt3"]{padding-top:3rem} 611 | [md~="pt4"]{padding-top:4rem} 612 | [md~="pr0"]{padding-right:0} 613 | [md~="pr1"]{padding-right:1rem} 614 | [md~="pr2"]{padding-right:2rem} 615 | [md~="pr3"]{padding-right:3rem} 616 | [md~="pr4"]{padding-right:4rem} 617 | [md~="pb0"]{padding-bottom:0} 618 | [md~="pb1"]{padding-bottom:1rem} 619 | [md~="pb2"]{padding-bottom:2rem} 620 | [md~="pb3"]{padding-bottom:3rem} 621 | [md~="pb4"]{padding-bottom:4rem} 622 | [md~="pl0"]{padding-left:0} 623 | [md~="pl1"]{padding-left:1rem} 624 | [md~="pl2"]{padding-left:2rem} 625 | [md~="pl3"]{padding-left:3rem} 626 | [md~="pl4"]{padding-left:4rem} 627 | [md~="px0"]{padding-left:0;padding-right:0} 628 | [md~="px1"]{padding-left:1rem;padding-right:1rem} 629 | [md~="px2"]{padding-left:2rem;padding-right:2rem} 630 | [md~="px3"]{padding-left:3rem;padding-right:3rem} 631 | [md~="px4"]{padding-left:4rem;padding-right:4rem} 632 | [md~="py0"]{padding-top:0;padding-bottom:0} 633 | [md~="py1"]{padding-top:1rem;padding-bottom:1rem} 634 | [md~="py2"]{padding-top:2rem;padding-bottom:2rem} 635 | [md~="py3"]{padding-top:3rem;padding-bottom:3rem} 636 | [md~="py4"]{padding-top:4rem;padding-bottom:4rem} 637 | [md~="op0"]{opacity:0} 638 | [md~="op25"]{opacity:0.25} 639 | [md~="op50"]{opacity:0.5} 640 | [md~="op75"]{opacity:0.75} 641 | [md~="op100"]{opacity:1} 642 | [md~="bgsc"]{background-size:cover} 643 | [md~="bgsct"]{background-size:contain} 644 | [md~="bgpc"]{background-position:center} 645 | [md~="bgpt"]{background-position:top} 646 | [md~="bgpr"]{background-position:right} 647 | [md~="bgpb"]{background-position:bottom} 648 | [md~="bgpl"]{background-position:left} 649 | [md~="bgrn"]{background-repeat:no-repeat} 650 | [md~="bgrx"]{background-repeat:repeat-x} 651 | [md~="bgry"]{background-repeat:repeat-y} 652 | [md~="x"]{display:flex} 653 | [md~="xac"]{align-items:center} 654 | [md~="xab"]{align-items:baseline} 655 | [md~="xas"]{align-items:stretch} 656 | [md~="xafs"]{align-items:flex-start} 657 | [md~="xafe"]{align-items:flex-end} 658 | [md~="xdr"]{flex-direction:row} 659 | [md~="xdrr"]{flex-direction:row-reverse} 660 | [md~="xdc"]{flex-direction:column} 661 | [md~="xdcr"]{flex-direction:column-reverse} 662 | [md~="xjc"]{justify-content:center} 663 | [md~="xjb"]{justify-content:space-between} 664 | [md~="xja"]{justify-content:space-around} 665 | [md~="xjs"]{justify-content:flex-start} 666 | [md~="xje"]{justify-content:flex-end} 667 | [md~="xw"]{flex-wrap:wrap} 668 | [md~="xwr"]{flex-wrap:wrap-reverse} 669 | [md~="xwn"]{flex-wrap:nowrap} 670 | [md~="xi"]{flex:initial} 671 | [md~="xx"]{flex:1} 672 | [md~="xa"]{flex:auto} 673 | [md~="xn"]{flex:none} 674 | [md~="xo0"]{order:0} 675 | [md~="xo1"]{order:1} 676 | [md~="xo2"]{order:2} 677 | [md~="xo3"]{order:3} 678 | [md~="xo4"]{order:4} 679 | [md~="xot"]{order:-1} 680 | [md~="xob"]{order:99} 681 | [md~="df"]{display:flex} 682 | [md~="db"]{display:block} 683 | [md~="dib"]{display:inline-block} 684 | [md~="di"]{display:inline} 685 | [md~="dt"]{display:table} 686 | [md~="dtc"]{display:table-cell} 687 | [md~="dtr"]{display:table-row} 688 | [md~="dn"]{display:none} 689 | [md~="fl"]{float:left} 690 | [md~="fr"]{float:right} 691 | [md~="fn"]{float:none} 692 | [md~="cf"]:after{content:"";display:block;clear:both} 693 | [md~="oh"]{overflow:hidden} 694 | [md~="os"]{overflow:scroll} 695 | [md~="ov"]{overflow:visible} 696 | [md~="oxh"]{overflow-x:hidden} 697 | [md~="oxs"]{overflow-x:scroll} 698 | [md~="oxv"]{overflow-x:visible} 699 | [md~="oyh"]{overflow-y:hidden} 700 | [md~="oys"]{overflow-y:scroll} 701 | [md~="oyv"]{overflow-y:visible} 702 | [md~="psa"]{position:absolute} 703 | [md~="psr"]{position:relative} 704 | [md~="psf"]{position:fixed} 705 | [md~="pss"]{position:static} 706 | [md~="t0"]{top:0} 707 | [md~="r0"]{right:0} 708 | [md~="b0"]{bottom:0} 709 | [md~="l0"]{left:0} 710 | [md~="z0"]{z-index:0} 711 | [md~="z1"]{z-index:1} 712 | [md~="z2"]{z-index:2} 713 | [md~="z3"]{z-index:3} 714 | [md~="z4"]{z-index:4} 715 | [md~="w0"]{width:0} 716 | [md~="w100"]{width:100%} 717 | [md~="h0"]{height:0} 718 | [md~="h100"]{height:100%} 719 | [md~="vw50"]{width:50vw} 720 | [md~="vw100"]{width:100vw} 721 | [md~="vwmn50"]{min-width:50vw} 722 | [md~="vwmn100"]{min-width:100vw} 723 | [md~="vwmx50"]{max-width:50vw} 724 | [md~="vwmx100"]{max-width:100vw} 725 | [md~="vh50"]{height:50vh} 726 | [md~="vh100"]{height:100vh} 727 | [md~="vhmn50"]{min-height:50vh} 728 | [md~="vhmn100"]{min-height:100vh} 729 | [md~="vhmx50"]{max-height:50vh} 730 | [md~="vhmx100"]{max-height:100vh} 731 | [md~="ar25"]:before{padding-top:25%;content:"";display:block} 732 | [md~="ar50"]:before{padding-top:50%;content:"";display:block} 733 | [md~="ar75"]:before{padding-top:75%;content:"";display:block} 734 | [md~="ar100"]:before{padding-top:100%;content:"";display:block} 735 | [md~="fs1"]{font-size:1rem} 736 | [md~="fs1-2"]{font-size:1.2rem} 737 | [md~="fs1-6"]{font-size:1.6rem} 738 | [md~="fs2-4"]{font-size:2.4rem} 739 | [md~="fs3-2"]{font-size:3.2rem} 740 | [md~="fs6-4"]{font-size:6.4rem} 741 | [md~="lh1"]{line-height:1} 742 | [md~="lh1-5"]{line-height:1.5} 743 | [md~="fsn"]{font-style:normal} 744 | [md~="fsi"]{font-style:italic} 745 | [md~="fwn"]{font-weight:normal} 746 | [md~="fwb"]{font-weight:bold} 747 | [md~="tal"]{text-align:left} 748 | [md~="tac"]{text-align:center} 749 | [md~="tar"]{text-align:right} 750 | [md~="taj"]{text-align:justify} 751 | [md~="toi"]{text-overflow:initial} 752 | [md~="toc"]{text-overflow:clip} 753 | [md~="toe"]{text-overflow:ellipsis} 754 | [md~="tdu"]{text-decoration:underline} 755 | [md~="tdo"]{text-decoration:overline} 756 | [md~="tdlt"]{text-decoration:line-through} 757 | [md~="tdn"]{text-decoration:none} 758 | [md~="ttu"]{text-transform:uppercase} 759 | [md~="ttl"]{text-transform:lowercase} 760 | [md~="ttc"]{text-transform:capitalize} 761 | [md~="ttn"]{text-transform:none} 762 | [md~="vabl"]{vertical-align:baseline} 763 | [md~="vat"]{vertical-align:top} 764 | [md~="vam"]{vertical-align:middle} 765 | [md~="vab"]{vertical-align:bottom} 766 | [md~="wsn"]{white-space:normal} 767 | [md~="wsnw"]{white-space:nowrap} 768 | [md~="wsp"]{white-space:pre} 769 | [md~="wsi"]{white-space:inherit} 770 | [md~="tc1"]{columns:1} 771 | [md~="tc2"]{columns:2} 772 | [md~="tc3"]{columns:3} 773 | [md~="tc4"]{columns:4} 774 | [md~="curp"]{cursor:pointer} 775 | [md~="curd"]{cursor:default} 776 | [md~="cura"]{cursor:alias} 777 | [md~="curzi"]{cursor:zoom-in} 778 | [md~="curzo"]{cursor:zoom-out} 779 | [md~="usn"]{user-select:none} 780 | [md~="usa"]{user-select:auto} 781 | [md~="ust"]{user-select:text} 782 | [md~="pen"]{pointer-events:none} 783 | [md~="pea"]{pointer-events:auto} 784 | [md~="vh"]{visibility:hidden} 785 | [md~="vv"]{visibility:visible} 786 | [md~="dev"]{outline:1px solid #912eff} 787 | [md~="dev"] > * {outline:1px solid #5497ff} 788 | [md~="dev"] > * > * {outline:1px solid #51feff} 789 | [md~="dev"] > * > * > * {outline:1px solid #ff0000} 790 | [md~="dev"] > * > * > * * {outline:1px solid #00ff00} 791 | } 792 | @media (min-width:1280px) { 793 | [lg~="c1"]{width:8.33333%} 794 | [lg~="c2"]{width:16.66667%} 795 | [lg~="c3"]{width:25%} 796 | [lg~="c4"]{width:33.33333%} 797 | [lg~="c5"]{width:41.66667%} 798 | [lg~="c6"]{width:50%} 799 | [lg~="c7"]{width:58.33333%} 800 | [lg~="c8"]{width:66.66667%} 801 | [lg~="c9"]{width:75%} 802 | [lg~="c10"]{width:83.33333%} 803 | [lg~="c11"]{width:91.66667%} 804 | [lg~="c12"]{width:100%} 805 | [lg~="s1"]{width:100%} 806 | [lg~="s2"]{width:50%} 807 | [lg~="s3"]{width:33.33333%} 808 | [lg~="s4"]{width:25%} 809 | [lg~="s5"]{width:20%} 810 | [lg~="s6"]{width:16.66667%} 811 | [lg~="s7"]{width:14.28571%} 812 | [lg~="s8"]{width:12.5%} 813 | [lg~="s9"]{width:11.11111%} 814 | [lg~="s10"]{width:10%} 815 | [lg~="s11"]{width:9.09091%} 816 | [lg~="s12"]{width:8.33333%} 817 | [lg~="co0"]{margin-left:0} 818 | [lg~="co1"]{margin-left:8.33333%} 819 | [lg~="co2"]{margin-left:16.66667%} 820 | [lg~="co3"]{margin-left:25%} 821 | [lg~="co4"]{margin-left:33.33333%} 822 | [lg~="co5"]{margin-left:41.66667%} 823 | [lg~="co6"]{margin-left:50%} 824 | [lg~="co7"]{margin-left:58.33333%} 825 | [lg~="co8"]{margin-left:66.66667%} 826 | [lg~="co9"]{margin-left:75%} 827 | [lg~="co10"]{margin-left:83.33333%} 828 | [lg~="co11"]{margin-left:91.66667%} 829 | [lg~="co12"]{margin-left:100%} 830 | [lg~="m0"]{margin:0} 831 | [lg~="m1"]{margin:1rem} 832 | [lg~="m2"]{margin:2rem} 833 | [lg~="m3"]{margin:3rem} 834 | [lg~="m4"]{margin:4rem} 835 | [lg~="mt0"]{margin-top:0} 836 | [lg~="mt1"]{margin-top:1rem} 837 | [lg~="mt2"]{margin-top:2rem} 838 | [lg~="mt3"]{margin-top:3rem} 839 | [lg~="mt4"]{margin-top:4rem} 840 | [lg~="mr0"]{margin-right:0} 841 | [lg~="mr1"]{margin-right:1rem} 842 | [lg~="mr2"]{margin-right:2rem} 843 | [lg~="mr3"]{margin-right:3rem} 844 | [lg~="mr4"]{margin-right:4rem} 845 | [lg~="mb0"]{margin-bottom:0} 846 | [lg~="mb1"]{margin-bottom:1rem} 847 | [lg~="mb2"]{margin-bottom:2rem} 848 | [lg~="mb3"]{margin-bottom:3rem} 849 | [lg~="mb4"]{margin-bottom:4rem} 850 | [lg~="ml0"]{margin-left:0} 851 | [lg~="ml1"]{margin-left:1rem} 852 | [lg~="ml2"]{margin-left:2rem} 853 | [lg~="ml3"]{margin-left:3rem} 854 | [lg~="ml4"]{margin-left:4rem} 855 | [lg~="mx0"]{margin-left:0;margin-right:0} 856 | [lg~="mx1"]{margin-left:1rem;margin-right:1rem} 857 | [lg~="mx2"]{margin-left:2rem;margin-right:2rem} 858 | [lg~="mx3"]{margin-left:3rem;margin-right:3rem} 859 | [lg~="mx4"]{margin-left:4rem;margin-right:4rem} 860 | [lg~="my0"]{margin-top:0;margin-bottom:0} 861 | [lg~="my1"]{margin-top:1rem;margin-bottom:1rem} 862 | [lg~="my2"]{margin-top:2rem;margin-bottom:2rem} 863 | [lg~="my3"]{margin-top:3rem;margin-bottom:3rem} 864 | [lg~="my4"]{margin-top:4rem;margin-bottom:4rem} 865 | [lg~="p0"]{padding:0} 866 | [lg~="p1"]{padding:1rem} 867 | [lg~="p2"]{padding:2rem} 868 | [lg~="p3"]{padding:3rem} 869 | [lg~="p4"]{padding:4rem} 870 | [lg~="pt0"]{padding-top:0} 871 | [lg~="pt1"]{padding-top:1rem} 872 | [lg~="pt2"]{padding-top:2rem} 873 | [lg~="pt3"]{padding-top:3rem} 874 | [lg~="pt4"]{padding-top:4rem} 875 | [lg~="pr0"]{padding-right:0} 876 | [lg~="pr1"]{padding-right:1rem} 877 | [lg~="pr2"]{padding-right:2rem} 878 | [lg~="pr3"]{padding-right:3rem} 879 | [lg~="pr4"]{padding-right:4rem} 880 | [lg~="pb0"]{padding-bottom:0} 881 | [lg~="pb1"]{padding-bottom:1rem} 882 | [lg~="pb2"]{padding-bottom:2rem} 883 | [lg~="pb3"]{padding-bottom:3rem} 884 | [lg~="pb4"]{padding-bottom:4rem} 885 | [lg~="pl0"]{padding-left:0} 886 | [lg~="pl1"]{padding-left:1rem} 887 | [lg~="pl2"]{padding-left:2rem} 888 | [lg~="pl3"]{padding-left:3rem} 889 | [lg~="pl4"]{padding-left:4rem} 890 | [lg~="px0"]{padding-left:0;padding-right:0} 891 | [lg~="px1"]{padding-left:1rem;padding-right:1rem} 892 | [lg~="px2"]{padding-left:2rem;padding-right:2rem} 893 | [lg~="px3"]{padding-left:3rem;padding-right:3rem} 894 | [lg~="px4"]{padding-left:4rem;padding-right:4rem} 895 | [lg~="py0"]{padding-top:0;padding-bottom:0} 896 | [lg~="py1"]{padding-top:1rem;padding-bottom:1rem} 897 | [lg~="py2"]{padding-top:2rem;padding-bottom:2rem} 898 | [lg~="py3"]{padding-top:3rem;padding-bottom:3rem} 899 | [lg~="py4"]{padding-top:4rem;padding-bottom:4rem} 900 | [lg~="op0"]{opacity:0} 901 | [lg~="op25"]{opacity:0.25} 902 | [lg~="op50"]{opacity:0.5} 903 | [lg~="op75"]{opacity:0.75} 904 | [lg~="op100"]{opacity:1} 905 | [lg~="bgsc"]{background-size:cover} 906 | [lg~="bgsct"]{background-size:contain} 907 | [lg~="bgpc"]{background-position:center} 908 | [lg~="bgpt"]{background-position:top} 909 | [lg~="bgpr"]{background-position:right} 910 | [lg~="bgpb"]{background-position:bottom} 911 | [lg~="bgpl"]{background-position:left} 912 | [lg~="bgrn"]{background-repeat:no-repeat} 913 | [lg~="bgrx"]{background-repeat:repeat-x} 914 | [lg~="bgry"]{background-repeat:repeat-y} 915 | [lg~="x"]{display:flex} 916 | [lg~="xac"]{align-items:center} 917 | [lg~="xab"]{align-items:baseline} 918 | [lg~="xas"]{align-items:stretch} 919 | [lg~="xafs"]{align-items:flex-start} 920 | [lg~="xafe"]{align-items:flex-end} 921 | [lg~="xdr"]{flex-direction:row} 922 | [lg~="xdrr"]{flex-direction:row-reverse} 923 | [lg~="xdc"]{flex-direction:column} 924 | [lg~="xdcr"]{flex-direction:column-reverse} 925 | [lg~="xjc"]{justify-content:center} 926 | [lg~="xjb"]{justify-content:space-between} 927 | [lg~="xja"]{justify-content:space-around} 928 | [lg~="xjs"]{justify-content:flex-start} 929 | [lg~="xje"]{justify-content:flex-end} 930 | [lg~="xw"]{flex-wrap:wrap} 931 | [lg~="xwr"]{flex-wrap:wrap-reverse} 932 | [lg~="xwn"]{flex-wrap:nowrap} 933 | [lg~="xi"]{flex:initial} 934 | [lg~="xx"]{flex:1} 935 | [lg~="xa"]{flex:auto} 936 | [lg~="xn"]{flex:none} 937 | [lg~="xo0"]{order:0} 938 | [lg~="xo1"]{order:1} 939 | [lg~="xo2"]{order:2} 940 | [lg~="xo3"]{order:3} 941 | [lg~="xo4"]{order:4} 942 | [lg~="xot"]{order:-1} 943 | [lg~="xob"]{order:99} 944 | [lg~="df"]{display:flex} 945 | [lg~="db"]{display:block} 946 | [lg~="dib"]{display:inline-block} 947 | [lg~="di"]{display:inline} 948 | [lg~="dt"]{display:table} 949 | [lg~="dtc"]{display:table-cell} 950 | [lg~="dtr"]{display:table-row} 951 | [lg~="dn"]{display:none} 952 | [lg~="fl"]{float:left} 953 | [lg~="fr"]{float:right} 954 | [lg~="fn"]{float:none} 955 | [lg~="cf"]:after{content:"";display:block;clear:both} 956 | [lg~="oh"]{overflow:hidden} 957 | [lg~="os"]{overflow:scroll} 958 | [lg~="ov"]{overflow:visible} 959 | [lg~="oxh"]{overflow-x:hidden} 960 | [lg~="oxs"]{overflow-x:scroll} 961 | [lg~="oxv"]{overflow-x:visible} 962 | [lg~="oyh"]{overflow-y:hidden} 963 | [lg~="oys"]{overflow-y:scroll} 964 | [lg~="oyv"]{overflow-y:visible} 965 | [lg~="psa"]{position:absolute} 966 | [lg~="psr"]{position:relative} 967 | [lg~="psf"]{position:fixed} 968 | [lg~="pss"]{position:static} 969 | [lg~="t0"]{top:0} 970 | [lg~="r0"]{right:0} 971 | [lg~="b0"]{bottom:0} 972 | [lg~="l0"]{left:0} 973 | [lg~="z0"]{z-index:0} 974 | [lg~="z1"]{z-index:1} 975 | [lg~="z2"]{z-index:2} 976 | [lg~="z3"]{z-index:3} 977 | [lg~="z4"]{z-index:4} 978 | [lg~="w0"]{width:0} 979 | [lg~="w100"]{width:100%} 980 | [lg~="h0"]{height:0} 981 | [lg~="h100"]{height:100%} 982 | [lg~="vw50"]{width:50vw} 983 | [lg~="vw100"]{width:100vw} 984 | [lg~="vwmn50"]{min-width:50vw} 985 | [lg~="vwmn100"]{min-width:100vw} 986 | [lg~="vwmx50"]{max-width:50vw} 987 | [lg~="vwmx100"]{max-width:100vw} 988 | [lg~="vh50"]{height:50vh} 989 | [lg~="vh100"]{height:100vh} 990 | [lg~="vhmn50"]{min-height:50vh} 991 | [lg~="vhmn100"]{min-height:100vh} 992 | [lg~="vhmx50"]{max-height:50vh} 993 | [lg~="vhmx100"]{max-height:100vh} 994 | [lg~="ar25"]:before{padding-top:25%;content:"";display:block} 995 | [lg~="ar50"]:before{padding-top:50%;content:"";display:block} 996 | [lg~="ar75"]:before{padding-top:75%;content:"";display:block} 997 | [lg~="ar100"]:before{padding-top:100%;content:"";display:block} 998 | [lg~="fs1"]{font-size:1rem} 999 | [lg~="fs1-2"]{font-size:1.2rem} 1000 | [lg~="fs1-6"]{font-size:1.6rem} 1001 | [lg~="fs2-4"]{font-size:2.4rem} 1002 | [lg~="fs3-2"]{font-size:3.2rem} 1003 | [lg~="fs6-4"]{font-size:6.4rem} 1004 | [lg~="lh1"]{line-height:1} 1005 | [lg~="lh1-5"]{line-height:1.5} 1006 | [lg~="fsn"]{font-style:normal} 1007 | [lg~="fsi"]{font-style:italic} 1008 | [lg~="fwn"]{font-weight:normal} 1009 | [lg~="fwb"]{font-weight:bold} 1010 | [lg~="tal"]{text-align:left} 1011 | [lg~="tac"]{text-align:center} 1012 | [lg~="tar"]{text-align:right} 1013 | [lg~="taj"]{text-align:justify} 1014 | [lg~="toi"]{text-overflow:initial} 1015 | [lg~="toc"]{text-overflow:clip} 1016 | [lg~="toe"]{text-overflow:ellipsis} 1017 | [lg~="tdu"]{text-decoration:underline} 1018 | [lg~="tdo"]{text-decoration:overline} 1019 | [lg~="tdlt"]{text-decoration:line-through} 1020 | [lg~="tdn"]{text-decoration:none} 1021 | [lg~="ttu"]{text-transform:uppercase} 1022 | [lg~="ttl"]{text-transform:lowercase} 1023 | [lg~="ttc"]{text-transform:capitalize} 1024 | [lg~="ttn"]{text-transform:none} 1025 | [lg~="vabl"]{vertical-align:baseline} 1026 | [lg~="vat"]{vertical-align:top} 1027 | [lg~="vam"]{vertical-align:middle} 1028 | [lg~="vab"]{vertical-align:bottom} 1029 | [lg~="wsn"]{white-space:normal} 1030 | [lg~="wsnw"]{white-space:nowrap} 1031 | [lg~="wsp"]{white-space:pre} 1032 | [lg~="wsi"]{white-space:inherit} 1033 | [lg~="tc1"]{columns:1} 1034 | [lg~="tc2"]{columns:2} 1035 | [lg~="tc3"]{columns:3} 1036 | [lg~="tc4"]{columns:4} 1037 | [lg~="curp"]{cursor:pointer} 1038 | [lg~="curd"]{cursor:default} 1039 | [lg~="cura"]{cursor:alias} 1040 | [lg~="curzi"]{cursor:zoom-in} 1041 | [lg~="curzo"]{cursor:zoom-out} 1042 | [lg~="usn"]{user-select:none} 1043 | [lg~="usa"]{user-select:auto} 1044 | [lg~="ust"]{user-select:text} 1045 | [lg~="pen"]{pointer-events:none} 1046 | [lg~="pea"]{pointer-events:auto} 1047 | [lg~="vh"]{visibility:hidden} 1048 | [lg~="vv"]{visibility:visible} 1049 | [lg~="dev"]{outline:1px solid #912eff} 1050 | [lg~="dev"] > * {outline:1px solid #5497ff} 1051 | [lg~="dev"] > * > * {outline:1px solid #51feff} 1052 | [lg~="dev"] > * > * > * {outline:1px solid #ff0000} 1053 | [lg~="dev"] > * > * > * * {outline:1px solid #00ff00} 1054 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var x = require('xtend') 2 | var gr8util = require('gr8-util') 3 | var gr8utils = require('./utils') 4 | 5 | module.exports = gr8 6 | 7 | var defaults = { 8 | breakpoints: { 9 | sm: 768, 10 | md: 1024, 11 | lg: 1280 12 | }, 13 | breakpointSelector: 'attribute', 14 | utils: [], 15 | exclude: [] 16 | } 17 | 18 | function gr8 (options) { 19 | options = x(defaults, options) 20 | 21 | var cssString = '' 22 | 23 | cssString += defaultUtils(options) 24 | cssString += customUtils(options.utils) 25 | 26 | Object.keys(options.breakpoints).forEach(function (key) { 27 | var selector = breakpointSelectorShortcut(options.breakpointSelector)(key) 28 | cssString += `\n@media ${breakpointShortcut(options.breakpoints[key])} {\n` 29 | cssString += defaultUtils(options, { selector: selector }) 30 | cssString += customUtils(options.utils, { selector: selector }) 31 | cssString += '\n}' 32 | }) 33 | 34 | return cssString 35 | } 36 | 37 | function defaultUtils (defaults, options) { 38 | options = options || {} 39 | return gr8utils(x(defaults, options)) 40 | } 41 | 42 | function customUtils (utils, options) { 43 | options = options || {} 44 | return utils.map(function (util) { 45 | return gr8util(x(util, options)) 46 | }).join('\n') 47 | } 48 | 49 | function breakpointShortcut (value) { 50 | return Number.isInteger(value) 51 | ? `(min-width:${value}px)` 52 | : value 53 | } 54 | 55 | function breakpointSelectorShortcut (selector) { 56 | return selector === 'attribute' 57 | ? key => s => `[${key}~="${s}"]` 58 | : selector === 'class' 59 | ? key => s => `.${key}-${s}` 60 | : selector 61 | } 62 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gr8", 3 | "version": "3.1.5", 4 | "description": "Functional css utilities", 5 | "main": "index.js", 6 | "style": "dist/gr8.css", 7 | "devDependencies": { 8 | "colortape": "^0.1.2", 9 | "onchange": "^6.0.0", 10 | "standard": "^11.0.0", 11 | "tape": "^5.0.0" 12 | }, 13 | "scripts": { 14 | "test": "standard --fix && node test.js | colortape", 15 | "build-css": "node bin/dist.js", 16 | "build-readme": "node bin/readme/index.js", 17 | "watch-readme": "onchange 'bin/readme/' -- npm run build-readme", 18 | "dist": "npm run test && npm run build-css && npm run build-readme" 19 | }, 20 | "standard": { 21 | "ignore": [ 22 | "postcss.js" 23 | ] 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "git+https://github.com/jongacnik/gr8.git" 28 | }, 29 | "keywords": [ 30 | "functional", 31 | "css", 32 | "utilities" 33 | ], 34 | "author": "Jon Gacnik (http://jongacnik.com)", 35 | "license": "MIT", 36 | "homepage": "https://github.com/jongacnik/gr8#readme", 37 | "dependencies": { 38 | "gr8-util": "^1.3.0", 39 | "object-values": "^2.0.0", 40 | "xtend": "^4.0.1" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 |

gr8

2 | 3 |
4 | 5 | NPM version 6 | 7 | 8 | NPM version 9 | 10 | 11 | Website 12 | 13 |
14 | 15 |
16 | 17 | Customizable, functional css utilities built using [**gr8-util**](https://github.com/jongacnik/gr8-util). Includes: 18 | 19 | - [**css stylesheet**](#stylesheet-usage) with default utilities 20 | - [**`gr8` function**](#javascript-usage) to generate and customize utilities within javascript 21 | 22 | ## Usage 23 | 24 | ### stylesheet usage 25 | 26 | The simplest way to use `gr8` is to include the [gr8.css](https://github.com/jongacnik/gr8/blob/master/dist/gr8.css) stylesheet in your project: 27 | 28 | ```html 29 | 30 | ``` 31 | 32 | ### javascript usage 33 | 34 | Use the `gr8` function to generate utilities: 35 | 36 | ```js 37 | var gr8 = require('gr8') 38 | var css = gr8() 39 | ``` 40 | 41 | [Detailed usage →](#api) 42 | 43 | ## Utilities 44 | 45 | Default utilities: 46 | 47 |
48 | column 49 | 50 | ```css 51 | .c1{width:8.33333%} 52 | .c2{width:16.66667%} 53 | .c3{width:25%} 54 | .c4{width:33.33333%} 55 | .c5{width:41.66667%} 56 | .c6{width:50%} 57 | .c7{width:58.33333%} 58 | .c8{width:66.66667%} 59 | .c9{width:75%} 60 | .c10{width:83.33333%} 61 | .c11{width:91.66667%} 62 | .c12{width:100%} 63 | .s1{width:100%} 64 | .s2{width:50%} 65 | .s3{width:33.33333%} 66 | .s4{width:25%} 67 | .s5{width:20%} 68 | .s6{width:16.66667%} 69 | .s7{width:14.28571%} 70 | .s8{width:12.5%} 71 | .s9{width:11.11111%} 72 | .s10{width:10%} 73 | .s11{width:9.09091%} 74 | .s12{width:8.33333%} 75 | .co0{margin-left:0} 76 | .co1{margin-left:8.33333%} 77 | .co2{margin-left:16.66667%} 78 | .co3{margin-left:25%} 79 | .co4{margin-left:33.33333%} 80 | .co5{margin-left:41.66667%} 81 | .co6{margin-left:50%} 82 | .co7{margin-left:58.33333%} 83 | .co8{margin-left:66.66667%} 84 | .co9{margin-left:75%} 85 | .co10{margin-left:83.33333%} 86 | .co11{margin-left:91.66667%} 87 | .co12{margin-left:100%} 88 | ``` 89 | 90 |
91 | 92 |
93 | margin 94 | 95 | ```css 96 | .m0{margin:0} 97 | .m1{margin:1rem} 98 | .m2{margin:2rem} 99 | .m3{margin:3rem} 100 | .m4{margin:4rem} 101 | .mt0{margin-top:0} 102 | .mt1{margin-top:1rem} 103 | .mt2{margin-top:2rem} 104 | .mt3{margin-top:3rem} 105 | .mt4{margin-top:4rem} 106 | .mr0{margin-right:0} 107 | .mr1{margin-right:1rem} 108 | .mr2{margin-right:2rem} 109 | .mr3{margin-right:3rem} 110 | .mr4{margin-right:4rem} 111 | .mb0{margin-bottom:0} 112 | .mb1{margin-bottom:1rem} 113 | .mb2{margin-bottom:2rem} 114 | .mb3{margin-bottom:3rem} 115 | .mb4{margin-bottom:4rem} 116 | .ml0{margin-left:0} 117 | .ml1{margin-left:1rem} 118 | .ml2{margin-left:2rem} 119 | .ml3{margin-left:3rem} 120 | .ml4{margin-left:4rem} 121 | .mx0{margin-left:0;margin-right:0} 122 | .mx1{margin-left:1rem;margin-right:1rem} 123 | .mx2{margin-left:2rem;margin-right:2rem} 124 | .mx3{margin-left:3rem;margin-right:3rem} 125 | .mx4{margin-left:4rem;margin-right:4rem} 126 | .my0{margin-top:0;margin-bottom:0} 127 | .my1{margin-top:1rem;margin-bottom:1rem} 128 | .my2{margin-top:2rem;margin-bottom:2rem} 129 | .my3{margin-top:3rem;margin-bottom:3rem} 130 | .my4{margin-top:4rem;margin-bottom:4rem} 131 | ``` 132 | 133 |
134 | 135 |
136 | padding 137 | 138 | ```css 139 | .p0{padding:0} 140 | .p1{padding:1rem} 141 | .p2{padding:2rem} 142 | .p3{padding:3rem} 143 | .p4{padding:4rem} 144 | .pt0{padding-top:0} 145 | .pt1{padding-top:1rem} 146 | .pt2{padding-top:2rem} 147 | .pt3{padding-top:3rem} 148 | .pt4{padding-top:4rem} 149 | .pr0{padding-right:0} 150 | .pr1{padding-right:1rem} 151 | .pr2{padding-right:2rem} 152 | .pr3{padding-right:3rem} 153 | .pr4{padding-right:4rem} 154 | .pb0{padding-bottom:0} 155 | .pb1{padding-bottom:1rem} 156 | .pb2{padding-bottom:2rem} 157 | .pb3{padding-bottom:3rem} 158 | .pb4{padding-bottom:4rem} 159 | .pl0{padding-left:0} 160 | .pl1{padding-left:1rem} 161 | .pl2{padding-left:2rem} 162 | .pl3{padding-left:3rem} 163 | .pl4{padding-left:4rem} 164 | .px0{padding-left:0;padding-right:0} 165 | .px1{padding-left:1rem;padding-right:1rem} 166 | .px2{padding-left:2rem;padding-right:2rem} 167 | .px3{padding-left:3rem;padding-right:3rem} 168 | .px4{padding-left:4rem;padding-right:4rem} 169 | .py0{padding-top:0;padding-bottom:0} 170 | .py1{padding-top:1rem;padding-bottom:1rem} 171 | .py2{padding-top:2rem;padding-bottom:2rem} 172 | .py3{padding-top:3rem;padding-bottom:3rem} 173 | .py4{padding-top:4rem;padding-bottom:4rem} 174 | ``` 175 | 176 |
177 | 178 |
179 | opacity 180 | 181 | ```css 182 | .op0{opacity:0} 183 | .op25{opacity:0.25} 184 | .op50{opacity:0.5} 185 | .op75{opacity:0.75} 186 | .op100{opacity:1} 187 | ``` 188 | 189 |
190 | 191 |
192 | background 193 | 194 | ```css 195 | .bgsc{background-size:cover} 196 | .bgsct{background-size:contain} 197 | .bgpc{background-position:center} 198 | .bgpt{background-position:top} 199 | .bgpr{background-position:right} 200 | .bgpb{background-position:bottom} 201 | .bgpl{background-position:left} 202 | .bgrn{background-repeat:no-repeat} 203 | .bgrx{background-repeat:repeat-x} 204 | .bgry{background-repeat:repeat-y} 205 | ``` 206 | 207 |
208 | 209 |
210 | flex 211 | 212 | ```css 213 | .x{display:flex} 214 | .xac{align-items:center} 215 | .xab{align-items:baseline} 216 | .xas{align-items:stretch} 217 | .xafs{align-items:flex-start} 218 | .xafe{align-items:flex-end} 219 | .xdr{flex-direction:row} 220 | .xdrr{flex-direction:row-reverse} 221 | .xdc{flex-direction:column} 222 | .xdcr{flex-direction:column-reverse} 223 | .xjc{justify-content:center} 224 | .xjb{justify-content:space-between} 225 | .xja{justify-content:space-around} 226 | .xjs{justify-content:flex-start} 227 | .xje{justify-content:flex-end} 228 | .xw{flex-wrap:wrap} 229 | .xwr{flex-wrap:wrap-reverse} 230 | .xwn{flex-wrap:nowrap} 231 | .xi{flex:initial} 232 | .xx{flex:1} 233 | .xa{flex:auto} 234 | .xn{flex:none} 235 | .xo0{order:0} 236 | .xo1{order:1} 237 | .xo2{order:2} 238 | .xo3{order:3} 239 | .xo4{order:4} 240 | .xot{order:-1} 241 | .xob{order:99} 242 | ``` 243 | 244 |
245 | 246 |
247 | display 248 | 249 | ```css 250 | .df{display:flex} 251 | .db{display:block} 252 | .dib{display:inline-block} 253 | .di{display:inline} 254 | .dt{display:table} 255 | .dtc{display:table-cell} 256 | .dtr{display:table-row} 257 | .dn{display:none} 258 | ``` 259 | 260 |
261 | 262 |
263 | float 264 | 265 | ```css 266 | .fl{float:left} 267 | .fr{float:right} 268 | .fn{float:none} 269 | .cf:after{content:"";display:block;clear:both} 270 | ``` 271 | 272 |
273 | 274 |
275 | overflow 276 | 277 | ```css 278 | .oh{overflow:hidden} 279 | .os{overflow:scroll} 280 | .ov{overflow:visible} 281 | .oxh{overflow-x:hidden} 282 | .oxs{overflow-x:scroll} 283 | .oxv{overflow-x:visible} 284 | .oyh{overflow-y:hidden} 285 | .oys{overflow-y:scroll} 286 | .oyv{overflow-y:visible} 287 | ``` 288 | 289 |
290 | 291 |
292 | positioning 293 | 294 | ```css 295 | .psa{position:absolute} 296 | .psr{position:relative} 297 | .psf{position:fixed} 298 | .pss{position:static} 299 | .t0{top:0} 300 | .r0{right:0} 301 | .b0{bottom:0} 302 | .l0{left:0} 303 | .z0{z-index:0} 304 | .z1{z-index:1} 305 | .z2{z-index:2} 306 | .z3{z-index:3} 307 | .z4{z-index:4} 308 | ``` 309 | 310 |
311 | 312 |
313 | size 314 | 315 | ```css 316 | .w0{width:0} 317 | .w100{width:100%} 318 | .h0{height:0} 319 | .h100{height:100%} 320 | .vw50{width:50vw} 321 | .vw100{width:100vw} 322 | .vwmn50{min-width:50vw} 323 | .vwmn100{min-width:100vw} 324 | .vwmx50{max-width:50vw} 325 | .vwmx100{max-width:100vw} 326 | .vh50{height:50vh} 327 | .vh100{height:100vh} 328 | .vhmn50{min-height:50vh} 329 | .vhmn100{min-height:100vh} 330 | .vhmx50{max-height:50vh} 331 | .vhmx100{max-height:100vh} 332 | .ar25:before{padding-top:25%;content:"";display:block} 333 | .ar50:before{padding-top:50%;content:"";display:block} 334 | .ar75:before{padding-top:75%;content:"";display:block} 335 | .ar100:before{padding-top:100%;content:"";display:block} 336 | ``` 337 | 338 |
339 | 340 |
341 | typography 342 | 343 | ```css 344 | .fs1{font-size:1rem} 345 | .fs1-2{font-size:1.2rem} 346 | .fs1-6{font-size:1.6rem} 347 | .fs2-4{font-size:2.4rem} 348 | .fs3-2{font-size:3.2rem} 349 | .fs6-4{font-size:6.4rem} 350 | .lh1{line-height:1} 351 | .lh1-5{line-height:1.5} 352 | .fsn{font-style:normal} 353 | .fsi{font-style:italic} 354 | .fwn{font-weight:normal} 355 | .fwb{font-weight:bold} 356 | .tal{text-align:left} 357 | .tac{text-align:center} 358 | .tar{text-align:right} 359 | .taj{text-align:justify} 360 | .toi{text-overflow:initial} 361 | .toc{text-overflow:clip} 362 | .toe{text-overflow:ellipsis} 363 | .tdu{text-decoration:underline} 364 | .tdo{text-decoration:overline} 365 | .tdlt{text-decoration:line-through} 366 | .tdn{text-decoration:none} 367 | .ttu{text-transform:uppercase} 368 | .ttl{text-transform:lowercase} 369 | .ttc{text-transform:capitalize} 370 | .ttn{text-transform:none} 371 | .vabl{vertical-align:baseline} 372 | .vat{vertical-align:top} 373 | .vam{vertical-align:middle} 374 | .vab{vertical-align:bottom} 375 | .wsn{white-space:normal} 376 | .wsnw{white-space:nowrap} 377 | .wsp{white-space:pre} 378 | .wsi{white-space:inherit} 379 | .tc1{columns:1} 380 | .tc2{columns:2} 381 | .tc3{columns:3} 382 | .tc4{columns:4} 383 | ``` 384 | 385 |
386 | 387 |
388 | miscellaneous 389 | 390 | ```css 391 | .curp{cursor:pointer} 392 | .curd{cursor:default} 393 | .cura{cursor:alias} 394 | .curzi{cursor:zoom-in} 395 | .curzo{cursor:zoom-out} 396 | .usn{user-select:none} 397 | .usa{user-select:auto} 398 | .ust{user-select:text} 399 | .pen{pointer-events:none} 400 | .pea{pointer-events:auto} 401 | .vh{visibility:hidden} 402 | .vv{visibility:visible} 403 | ``` 404 | 405 |
406 | 407 |
408 | development 409 | 410 | ```css 411 | .dev{outline:1px solid #912eff} 412 | .dev > * {outline:1px solid #5497ff} 413 | .dev > * > * {outline:1px solid #51feff} 414 | .dev > * > * > * {outline:1px solid #ff0000} 415 | .dev > * > * > * * {outline:1px solid #00ff00} 416 | ``` 417 | 418 |
419 | 420 | ## API 421 | 422 | ### `css = gr8([opts])` 423 | 424 | Generate utilities and return a string of css. `opts` accepts the following values: 425 | 426 | #### Value Options 427 | 428 | - `opts.spacing` **[Mixed]** values for [margin](#margin) & [padding](#padding) utilities 429 | - `opts.fontSize` **[Mixed]** values for [font-size](#typography) utilities 430 | - `opts.lineHeight` **[Mixed]** values for [line-height](#typography) utilities 431 | - `opts.size` **[Mixed]** values for [width & height](#size) utilities 432 | - `opts.viewport` **[Mixed]** values for [viewport](#size) utilities 433 | - `opts.zIndex` **[Mixed]** values for [zIndex](#positioning) utilities 434 | - `opts.flexOrder` **[Mixed]** values for [flex-order](#flex) utilities 435 | - `opts.opacity` **[Mixed]** values for [opacity](#opacity) utilities 436 | - `opts.aspectRatio` **[Mixed]** values for [aspect ratio](#size) utilities 437 | - `opts.textColumn` **[Mixed]** values for [text columns](#typography) utilities 438 | 439 | #### Selector Options 440 | 441 | - `opts.selector` **[Function]** css selector template function 442 | - `opts.breakpoints` **[Object]** values for breakpoint utilities 443 | - `opts.breakpointSelector` **[String | Function]** selector shortcut or css selector template function 444 | 445 | #### Custom Utilities Options 446 | 447 | - `opts.utils` **[Array]** custom [gr8-util](https://github.com/jongacnik/gr8-util) utilities 448 | - `opts.exclude` **[Array]** keys of default utilities to exclude 449 | 450 | ## Value Options 451 | 452 | Value options customize numeric `gr8` utilities. They accept Numbers, Strings, Arrays, or Objects. Typically Arrays of Numbers will be used. Refer to [gr8-util](https://github.com/jongacnik/gr8-util) for details on all possible ways to format values. 453 | 454 | **Defaults:** 455 | 456 | ```js 457 | var css = gr8({ 458 | spacing: [0, 1, 2, 3, 4], 459 | fontSize: [1, 1.2, 1.6, 2.4, 3.2, 6.4], 460 | lineHeight: [1, 1.5], 461 | size: [0, 100], 462 | viewport: [50, 100], 463 | zIndex: [0, 1, 2, 3, 4], 464 | flexOrder: [0, 1, 2, 3, 4], 465 | opacity: [0, 25, 50, 75, 100], 466 | aspectRatio: [25, 50, 75, 100], 467 | textColumn: [1, 2, 3, 4] 468 | }) 469 | ``` 470 | 471 | ## Selector Options 472 | 473 | Selector options control selectors & breakpoints. 474 | 475 | **Defaults:** 476 | 477 | ```js 478 | var css = gr8({ 479 | selector: s => `.${s}`, 480 | breakpoints: { 481 | sm: 768, 482 | md: 1024, 483 | lg: 1280 484 | }, 485 | breakpointSelector: 'attribute' 486 | }) 487 | ``` 488 | 489 | ### `opts.selector` 490 | 491 | Function expects a selector name as input and returns a css selector string as output. For example, to use an attribute selector instead of classes: 492 | 493 | ```js 494 | var css = gr8({ 495 | selector: s => `[gr8~="${s}"]` 496 | }) 497 | ``` 498 | 499 |
500 | Output 501 | 502 | ```css 503 | [gr8~="fs1"]{font-size:1rem} 504 | [gr8~="fs1-6"]{font-size:1.6rem} 505 | /* etc... */ 506 | ``` 507 | 508 |
509 | 510 | ### `opts.breakpoints` 511 | 512 | Object keys are used in selector names and object values are used to define the media queries. Object values can either be integers (which results in a `min-width` media queries), or object values can be media query strings. Pass `false` to disable breakpoint utilities entirely: 513 | 514 | ```js 515 | var css = gr8({ 516 | breakpoints: { 517 | small: 1024, 518 | medium: '(min-width:768px) and (max-width:1280px)', 519 | 'not-big': '(max-width:1024px)', 520 | portrait: '(orientation:portrait)' 521 | } 522 | }) 523 | ``` 524 | 525 |
526 | Output 527 | 528 | ```css 529 | @media (min-width:1024px) { 530 | [small~="fs1"]{font-size:1rem} 531 | /* etc... */ 532 | } 533 | @media (min-width:768px) and (max-width:1280px) { 534 | [medium~="fs1"]{font-size:1rem} 535 | /* etc... */ 536 | } 537 | @media (max-width:1024px) { 538 | [not-big~="fs1"]{font-size:1rem} 539 | /* etc... */ 540 | } 541 | @media (orientation:portrait) { 542 | [portrait~="fs1"]{font-size:1rem} 543 | /* etc... */ 544 | } 545 | ``` 546 | 547 |

548 | 549 | **Note:** If you care about valid attribute selectors, prepend `data-` to your breakpoint keys. 550 | 551 | ### `opts.breakpointSelector` 552 | 553 | By default, attribute selectors are generated for breakpoint utilities (as seen above). Use prefixed classes instead by passing in the `'class'` shortcut, or provide a selector function for more granular control: 554 | 555 | #### `'class'` Shortcut 556 | 557 | ```js 558 | var css = gr8({ 559 | breakpointSelector: 'class' 560 | }) 561 | ``` 562 | 563 |
564 | Output 565 | 566 | ```css 567 | @media (min-width:768px) { 568 | .sm-fs1{font-size:1rem} 569 | /* etc... */ 570 | } 571 | @media (min-width:1024px) { 572 | .md-fs1{font-size:1rem} 573 | /* etc... */ 574 | } 575 | @media (min-width:1280px) { 576 | .lg-fs1{font-size:1rem} 577 | /* etc... */ 578 | } 579 | ``` 580 | 581 |
582 | 583 | #### Selector Function 584 | 585 | 586 | ```js 587 | var css = gr8({ 588 | breakpointSelector: key => s => `.gr8-${key}-${s}` 589 | }) 590 | ``` 591 | 592 |
593 | Output 594 | 595 | ```css 596 | @media (min-width:768px) { 597 | .gr8-sm-fs1{font-size:1rem} 598 | /* etc... */ 599 | } 600 | @media (min-width:1024px) { 601 | .gr8-md-fs1{font-size:1rem} 602 | /* etc... */ 603 | } 604 | @media (min-width:1280px) { 605 | .gr8-lg-fs1{font-size:1rem} 606 | /* etc... */ 607 | } 608 | ``` 609 | 610 |
611 | 612 | ## Custom Utilities Options 613 | 614 | [gr8-util](https://github.com/jongacnik/gr8-util) is a little function for generating functional css utilities. Given a plain object, concise css utilities are generated. All the utilities in `gr8` are built using this. 615 | 616 | Use the `utils` option to pass an array of `gr8-util` objects to extend the `gr8` output with custom utilities: 617 | 618 | ```js 619 | var bgcolor = { 620 | prop: { 621 | bgc: 'background-color' 622 | }, 623 | vals: ['red', 'blue', 'green'] 624 | } 625 | 626 | var fontcolor = { 627 | prop: { 628 | fc: 'color' 629 | }, 630 | vals: ['red', 'blue', 'green'] 631 | } 632 | 633 | var css = gr8({ 634 | utils: [ 635 | bgcolor, 636 | fontcolor 637 | ] 638 | }) 639 | ``` 640 | 641 |
642 | Output 643 | 644 | ```css 645 | .bgcr{background-color:red} 646 | .bgcb{background-color:blue} 647 | .bgcg{background-color:green} 648 | .fcr{color:red} 649 | .fcb{color:blue} 650 | .fcg{color:green} 651 | /* etc... */ 652 | 653 | @media (min-width:768px) { 654 | [sm~="bgcr"]{background-color:red} 655 | [sm~="bgcb"]{background-color:blue} 656 | [sm~="bgcg"]{background-color:green} 657 | [sm~="fcr"]{color:red} 658 | [sm~="fcb"]{color:blue} 659 | [sm~="fcg"]{color:green} 660 | /* etc... */ 661 | } 662 | 663 | @media (min-width:1024px) { 664 | [md~="bgcr"]{background-color:red} 665 | [md~="bgcb"]{background-color:blue} 666 | [md~="bgcg"]{background-color:green} 667 | [md~="fcr"]{color:red} 668 | [md~="fcb"]{color:blue} 669 | [md~="fcg"]{color:green} 670 | /* etc... */ 671 | } 672 | 673 | @media (min-width:1280px) { 674 | [lg~="bgcr"]{background-color:red} 675 | [lg~="bgcb"]{background-color:blue} 676 | [lg~="bgcg"]{background-color:green} 677 | [lg~="fcr"]{color:red} 678 | [lg~="fcb"]{color:blue} 679 | [lg~="fcg"]{color:green} 680 | /* etc... */ 681 | } 682 | ``` 683 | 684 |

685 | 686 | **[Refer to gr8-util for further documentation on generating custom utilities.](https://github.com/jongacnik/gr8-util)** 687 | 688 | ### `opts.exclude` 689 | 690 | Use the `exclude` option to remove some of the default utilities. Accepts an array with any of the following values: 691 | 692 | `column`, `margin`, `padding`, `opacity`, `background`, `flex`, `display`, `float`, `overflow`, `positioning`, `size`, `typography`, `miscellaneous`, `development` 693 | 694 | ## Proxies 695 | 696 | For more advanced use cases, some additional methods are proxied: 697 | 698 | ```js 699 | // direct access to gr8-util 700 | var gr8util = require('gr8/util') 701 | var css = gr8util({options}) 702 | ``` 703 | 704 | ```js 705 | // direct access to gr8-utils 706 | var gr8utils = require('gr8/utils') 707 | var css = gr8utils({options}) 708 | 709 | // or even lower level 710 | gr8utils.generate(gr8utils.utils, gr8utils.defaults) 711 | ``` 712 | 713 | ## Notes 714 | 715 | `gr8` is developed and iterated-on primarily for use within projects at [Folder Studio](http://folderstudio.com). It shares similarities with other functional css libraries like [tachyons](https://github.com/tachyons-css/tachyons) or [basscss](https://github.com/basscss/basscss), but diverges in its minimalism and customizability. `gr8` provides no colors, no borders, no font-families, etc out of the box, but instead provides ways to quickly define your own utilities for things like these using plain objects. It facilitates creating coherent design systems without imposing one by default. 716 | 717 | In any case, I hope you like it and perhaps find it useful! 718 | 719 | ## Todo 720 | 721 | - [ ] Advanced documentation 722 | - [ ] Website 723 | 724 | ## See Also 725 | 726 | - [gr8-util](https://github.com/jongacnik/gr8-util) 727 | 728 | ## License 729 | 730 | [MIT](https://github.com/jongacnik/gr8/blob/master/LICENSE) 731 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | var gr8 = require('.') 3 | 4 | test('output', function (t) { 5 | t.ok(typeof gr8() === 'string', 'outputs string') 6 | t.end() 7 | }) 8 | 9 | test('selector', function (t) { 10 | var css = gr8({ 11 | selector: s => `.gr8-${s}` 12 | }) 13 | t.ok(css.indexOf('.gr8-') >= 0, 'supports custom selector') 14 | t.end() 15 | }) 16 | 17 | test('disable breakpoints', function (t) { 18 | var css = gr8({ 19 | breakpoints: false 20 | }) 21 | t.ok(css.indexOf('@media') < 0, 'supports disabling breakpoints') 22 | t.end() 23 | }) 24 | 25 | test('breakpoint selector', function (t) { 26 | var cssA = gr8({ 27 | breakpointSelector: 'attribute' 28 | }) 29 | t.ok(cssA.indexOf('[sm~=') >= 0, 'supports attribute breakpoint selector shortcut') 30 | 31 | var cssB = gr8({ 32 | breakpointSelector: 'class' 33 | }) 34 | t.ok(cssB.indexOf('.sm-') >= 0, 'supports class breakpoint selector shortcut') 35 | 36 | var cssC = gr8({ 37 | breakpointSelector: key => s => `.gr8 [${key}~="${s}"]` 38 | }) 39 | t.ok(cssC.indexOf('.gr8 [sm~=') >= 0, 'supports custom breakpoint selector') 40 | 41 | t.end() 42 | }) 43 | 44 | test('custom breakpoints', function (t) { 45 | var css = gr8({ 46 | breakpoints: { 47 | a: '(max-width:768px)', 48 | b: 1024, 49 | c: '(orientation:landscape)' 50 | } 51 | }) 52 | 53 | t.ok(css.indexOf('@media (max-width:768px)') >= 0, 'supports custom breakpoints A') 54 | t.ok(css.indexOf('@media (min-width:1024px)') >= 0, 'supports custom breakpoints B') 55 | t.ok(css.indexOf('@media (orientation:landscape)') >= 0, 'supports custom breakpoints C') 56 | 57 | t.end() 58 | }) 59 | 60 | test('unit', function (t) { 61 | var css = gr8({ 62 | unit: 'px' 63 | }) 64 | 65 | t.ok(css.indexOf('.fs6-4{font-size:6.4px}') >= 0, 'supports unit option') 66 | t.end() 67 | }) 68 | 69 | test('values', function (t) { 70 | var css = gr8({ 71 | spacing: [99], 72 | fontSize: [99], 73 | lineHeight: [99], 74 | size: [99], 75 | viewport: [99], 76 | zIndex: [99], 77 | flexOrder: [99], 78 | opacity: [99], 79 | aspectRatio: [99], 80 | textColumn: [99] 81 | }) 82 | 83 | var hasAll = css.indexOf('.p99') >= 0 && 84 | css.indexOf('.fs99') >= 0 && 85 | css.indexOf('.lh99') >= 0 && 86 | css.indexOf('.w99') >= 0 && 87 | css.indexOf('.vw99') >= 0 && 88 | css.indexOf('.z99') >= 0 && 89 | css.indexOf('.xo99') >= 0 && 90 | css.indexOf('.op99') >= 0 && 91 | css.indexOf('.ar99') >= 0 && 92 | css.indexOf('.tc99') >= 0 93 | 94 | t.ok(hasAll, 'custom values succesfully passed to gr8-util') 95 | t.end() 96 | }) 97 | 98 | test('custom util', function (t) { 99 | var css = gr8({ 100 | utils: [ 101 | { 102 | prop: 'foo', 103 | vals: 'bar' 104 | } 105 | ] 106 | }) 107 | 108 | t.ok(css.indexOf('.fb{foo:bar}') >= 0, 'custom utils succesfully generated') 109 | t.ok(css.indexOf('[sm~="fb"]{foo:bar}') >= 0, 'custom utils succesfully generated per breakpoint') 110 | 111 | t.end() 112 | }) 113 | 114 | test('custom raw util', function (t) { 115 | var css = gr8({ 116 | utils: [ 117 | { 118 | raw: { 119 | 'trans-center-x': 'left:50%;transform:translateX(-50%)', 120 | 'trans-center-y': 'top:50%;transform:translateY(-50%)' 121 | } 122 | } 123 | ] 124 | }) 125 | 126 | t.ok(css.indexOf('.trans-center-x{left:50%;transform:translateX(-50%)}') >= 0, 'custom raw utils succesfully generated') 127 | t.ok(css.indexOf('[sm~="trans-center-x"]{left:50%;transform:translateX(-50%)}') >= 0, 'custom raw utils succesfully generated per breakpoint') 128 | 129 | t.end() 130 | }) 131 | -------------------------------------------------------------------------------- /util.js: -------------------------------------------------------------------------------- 1 | module.exports = require('gr8-util') 2 | -------------------------------------------------------------------------------- /utils.js: -------------------------------------------------------------------------------- 1 | var x = require('xtend') 2 | var gr8util = require('gr8-util') 3 | var objectValues = require('object-values') 4 | 5 | module.exports = gr8utils 6 | 7 | var defaults = { 8 | spacing: [0, 1, 2, 3, 4], 9 | fontSize: [1, 1.2, 1.6, 2.4, 3.2, 6.4], 10 | lineHeight: [1, 1.5], 11 | size: [0, 100], 12 | viewport: [50, 100], 13 | zIndex: [0, 1, 2, 3, 4], 14 | flexOrder: [0, 1, 2, 3, 4], 15 | opacity: [0, 25, 50, 75, 100], 16 | aspectRatio: [25, 50, 75, 100], 17 | textColumn: [1, 2, 3, 4], 18 | unit: 'rem' 19 | } 20 | 21 | var utils = { 22 | column: require('./utils/column'), 23 | margin: require('./utils/margin'), 24 | padding: require('./utils/padding'), 25 | opacity: require('./utils/opacity'), 26 | background: require('./utils/background'), 27 | flex: require('./utils/flex'), 28 | display: require('./utils/display'), 29 | float: require('./utils/float'), 30 | overflow: require('./utils/overflow'), 31 | positioning: require('./utils/positioning'), 32 | size: require('./utils/size'), 33 | typography: require('./utils/type'), 34 | miscellaneous: require('./utils/misc'), 35 | development: require('./utils/dev') 36 | } 37 | 38 | function gr8utils (options) { 39 | return generate(filter(utils, options.exclude), options) 40 | } 41 | 42 | // public 43 | gr8utils.defaults = defaults 44 | gr8utils.utils = utils 45 | gr8utils.generate = generate 46 | 47 | function filter (utils, keys) { 48 | if (!Array.isArray(keys)) return utils 49 | var allKeys = Object.keys(utils) 50 | keys.forEach(function (key) { 51 | var isMatch = allKeys.indexOf(key) >= 0 52 | if (isMatch) { 53 | delete utils[key] 54 | } 55 | }) 56 | return utils 57 | } 58 | 59 | function generate (utils, options) { 60 | options = x(defaults, options) 61 | return objectValues(utils).map(function (util) { 62 | return generateEach(objectValues(util), options) 63 | }).join('\n') 64 | } 65 | 66 | function generateEach (utils, options) { 67 | return utils.map(function (util) { 68 | if (typeof util === 'function') { 69 | util = util(options) 70 | } 71 | 72 | if (typeof util === 'string') { 73 | return util 74 | } else { 75 | util.selector = options.selector 76 | return gr8util(util) 77 | } 78 | }).join('\n') 79 | } 80 | -------------------------------------------------------------------------------- /utils/background.js: -------------------------------------------------------------------------------- 1 | exports.size = { 2 | prop: { 3 | bgs: 'background-size' 4 | }, 5 | vals: { 6 | c: 'cover', 7 | ct: 'contain' 8 | } 9 | } 10 | 11 | exports.position = { 12 | prop: { 13 | bgp: 'background-position' 14 | }, 15 | vals: [ 16 | 'center', 17 | 'top', 18 | 'right', 19 | 'bottom', 20 | 'left' 21 | ] 22 | } 23 | 24 | exports.repeat = { 25 | prop: { 26 | bgr: 'background-repeat' 27 | }, 28 | vals: { 29 | n: 'no-repeat', 30 | x: 'repeat-x', 31 | y: 'repeat-y' 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /utils/column.js: -------------------------------------------------------------------------------- 1 | exports.column = { 2 | prop: { 3 | c: 'width' 4 | }, 5 | vals: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 6 | transform: v => Math.round((v / 12 * 100) * 100000) / 100000, 7 | unit: '%' 8 | } 9 | 10 | exports.split = { 11 | prop: { 12 | s: 'width' 13 | }, 14 | vals: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 15 | transform: v => Math.round((1 / v * 100) * 100000) / 100000, 16 | unit: '%' 17 | } 18 | 19 | exports.offset = { 20 | prop: { 21 | co: 'margin-left' 22 | }, 23 | vals: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 24 | transform: v => Math.round((v / 12 * 100) * 100000) / 100000, 25 | unit: '%' 26 | } 27 | -------------------------------------------------------------------------------- /utils/dev.js: -------------------------------------------------------------------------------- 1 | var colors = { 2 | purp: '#912eff', 3 | blue: '#5497ff', 4 | teal: '#51feff', 5 | red: '#ff0000', 6 | lime: '#00ff00' 7 | } 8 | 9 | exports.dev = function (options) { 10 | var selector = options.selector || (s => `.${s}`) 11 | return [ 12 | `${selector('dev')}{outline:1px solid ${colors.purp}}`, 13 | `${selector('dev')} > * {outline:1px solid ${colors.blue}}`, 14 | `${selector('dev')} > * > * {outline:1px solid ${colors.teal}}`, 15 | `${selector('dev')} > * > * > * {outline:1px solid ${colors.red}}`, 16 | `${selector('dev')} > * > * > * * {outline:1px solid ${colors.lime}}` 17 | ].join('\n') 18 | } 19 | -------------------------------------------------------------------------------- /utils/display.js: -------------------------------------------------------------------------------- 1 | exports.display = { 2 | prop: 'display', 3 | vals: [ 4 | 'flex', 5 | 'block', 6 | 'inline-block', 7 | 'inline', 8 | 'table', 9 | 'table-cell', 10 | 'table-row', 11 | 'none' 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /utils/flex.js: -------------------------------------------------------------------------------- 1 | exports.display = function (options) { 2 | var selector = options.selector || (s => `.${s}`) 3 | return `${selector('x')}{display:flex}` 4 | } 5 | 6 | exports.align = { 7 | prop: { 8 | xa: 'align-items' 9 | }, 10 | vals: [ 11 | 'center', 12 | 'baseline', 13 | 'stretch', 14 | 'flex-start', 15 | 'flex-end' 16 | ] 17 | } 18 | 19 | exports.direction = { 20 | prop: { 21 | xd: 'flex-direction' 22 | }, 23 | vals: [ 24 | 'row', 25 | 'row-reverse', 26 | 'column', 27 | 'column-reverse' 28 | ] 29 | } 30 | 31 | exports.justify = { 32 | prop: { 33 | xj: 'justify-content' 34 | }, 35 | vals: { 36 | c: 'center', 37 | b: 'space-between', 38 | a: 'space-around', 39 | s: 'flex-start', 40 | e: 'flex-end' 41 | } 42 | } 43 | 44 | exports.wrap = { 45 | prop: { 46 | x: 'flex-wrap' 47 | }, 48 | vals: [ 49 | 'wrap', 50 | 'wrap-reverse', 51 | { wn: 'nowrap' } 52 | ] 53 | } 54 | 55 | exports.flex = { 56 | prop: { 57 | x: 'flex' 58 | }, 59 | vals: [ 60 | 'initial', 61 | { x: '1' }, 62 | 'auto', 63 | 'none' 64 | ] 65 | } 66 | 67 | exports.order = function (options) { 68 | var values = Array.isArray(options.flexOrder) 69 | ? options.flexOrder 70 | : [options.flexOrder] 71 | return { 72 | prop: { 73 | xo: 'order' 74 | }, 75 | vals: values.concat([ 76 | { t: -1 }, 77 | { b: 99 } 78 | ]) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /utils/float.js: -------------------------------------------------------------------------------- 1 | exports.float = { 2 | prop: 'float', 3 | vals: [ 4 | 'left', 5 | 'right', 6 | 'none' 7 | ] 8 | } 9 | 10 | exports.clear = function (options) { 11 | var selector = options.selector || (s => `.${s}`) 12 | return `${selector('cf')}:after{content:"";display:block;clear:both}` 13 | } 14 | -------------------------------------------------------------------------------- /utils/margin.js: -------------------------------------------------------------------------------- 1 | exports.margin = function (options) { 2 | return { 3 | prop: [ 4 | 'margin', 5 | 'margin-top', 6 | 'margin-right', 7 | 'margin-bottom', 8 | 'margin-left', 9 | { 10 | mx: [ 11 | 'margin-left', 12 | 'margin-right' 13 | ] 14 | }, 15 | { 16 | my: [ 17 | 'margin-top', 18 | 'margin-bottom' 19 | ] 20 | } 21 | ], 22 | vals: options.spacing, 23 | unit: options.unit 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /utils/misc.js: -------------------------------------------------------------------------------- 1 | exports.cursor = { 2 | prop: { 3 | cur: 'cursor' 4 | }, 5 | vals: [ 6 | 'pointer', 7 | 'default', 8 | 'alias', 9 | 'zoom-in', 10 | 'zoom-out' 11 | ] 12 | } 13 | 14 | exports.userSelect = { 15 | prop: 'user-select', 16 | vals: [ 17 | 'none', 18 | 'auto', 19 | 'text' 20 | ] 21 | } 22 | 23 | exports.pointerEvents = { 24 | prop: 'pointer-events', 25 | vals: [ 26 | 'none', 27 | 'auto' 28 | ] 29 | } 30 | 31 | exports.visibility = { 32 | prop: 'visibility', 33 | vals: [ 34 | 'hidden', 35 | 'visible' 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /utils/opacity.js: -------------------------------------------------------------------------------- 1 | exports.opacity = function (options) { 2 | return { 3 | prop: { 4 | op: 'opacity' 5 | }, 6 | vals: options.opacity, 7 | transform: v => v / 100 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /utils/overflow.js: -------------------------------------------------------------------------------- 1 | exports.overflow = { 2 | prop: [ 3 | 'overflow', 4 | 'overflow-x', 5 | 'overflow-y' 6 | ], 7 | vals: [ 8 | 'hidden', 9 | 'scroll', 10 | 'visible' 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /utils/padding.js: -------------------------------------------------------------------------------- 1 | exports.padding = function (options) { 2 | return { 3 | prop: [ 4 | 'padding', 5 | 'padding-top', 6 | 'padding-right', 7 | 'padding-bottom', 8 | 'padding-left', 9 | { 10 | px: [ 11 | 'padding-left', 12 | 'padding-right' 13 | ] 14 | }, 15 | { 16 | py: [ 17 | 'padding-top', 18 | 'padding-bottom' 19 | ] 20 | } 21 | ], 22 | vals: options.spacing, 23 | unit: options.unit 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /utils/positioning.js: -------------------------------------------------------------------------------- 1 | exports.position = { 2 | prop: { 3 | ps: 'position' 4 | }, 5 | vals: [ 6 | 'absolute', 7 | 'relative', 8 | 'fixed', 9 | 'static' 10 | ] 11 | } 12 | 13 | exports.placement = { 14 | prop: [ 15 | 'top', 16 | 'right', 17 | 'bottom', 18 | 'left' 19 | ], 20 | vals: 0 21 | } 22 | 23 | exports.zindex = function (options) { 24 | return { 25 | prop: { 26 | z: 'z-index' 27 | }, 28 | vals: options.zIndex 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /utils/size.js: -------------------------------------------------------------------------------- 1 | exports.size = function (options) { 2 | return { 3 | prop: ['width', 'height'], 4 | vals: options.size, 5 | unit: '%' 6 | } 7 | } 8 | 9 | exports.viewportWidth = function (options) { 10 | return { 11 | prop: { 12 | vw: 'width', 13 | vwmn: 'min-width', 14 | vwmx: 'max-width' 15 | }, 16 | vals: options.viewport, 17 | unit: 'vw' 18 | } 19 | } 20 | 21 | exports.viewportHeight = function (options) { 22 | return { 23 | prop: { 24 | vh: 'height', 25 | vhmn: 'min-height', 26 | vhmx: 'max-height' 27 | }, 28 | vals: options.viewport, 29 | unit: 'vh' 30 | } 31 | } 32 | 33 | exports.aspect = function (options) { 34 | return { 35 | prop: { 36 | ar: 'padding-top' 37 | }, 38 | vals: options.aspectRatio, 39 | transform: v => v + '%;content:"";display:block', 40 | tail: ':before' 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /utils/type.js: -------------------------------------------------------------------------------- 1 | exports.fontSize = function (options) { 2 | return { 3 | prop: 'font-size', 4 | vals: options.fontSize, 5 | unit: options.unit 6 | } 7 | } 8 | 9 | exports.lineHeight = function (options) { 10 | return { 11 | prop: 'line-height', 12 | vals: options.lineHeight 13 | } 14 | } 15 | 16 | exports.fontStyle = { 17 | prop: 'font-style', 18 | vals: [ 19 | 'normal', 20 | 'italic' 21 | ] 22 | } 23 | 24 | exports.fontWeight = { 25 | prop: 'font-weight', 26 | vals: [ 27 | 'normal', 28 | 'bold' 29 | ] 30 | } 31 | 32 | exports.textAlign = { 33 | prop: 'text-align', 34 | vals: [ 35 | 'left', 36 | 'center', 37 | 'right', 38 | 'justify' 39 | ] 40 | } 41 | 42 | exports.textOverflow = { 43 | prop: 'text-overflow', 44 | vals: [ 45 | 'initial', 46 | 'clip', 47 | 'ellipsis' 48 | ] 49 | } 50 | 51 | exports.textDecoration = { 52 | prop: 'text-decoration', 53 | vals: [ 54 | 'underline', 55 | 'overline', 56 | 'line-through', 57 | 'none' 58 | ] 59 | } 60 | 61 | exports.textTransform = { 62 | prop: 'text-transform', 63 | vals: [ 64 | 'uppercase', 65 | 'lowercase', 66 | 'capitalize', 67 | 'none' 68 | ] 69 | } 70 | 71 | exports.verticalAlign = { 72 | prop: 'vertical-align', 73 | vals: [ 74 | { bl: 'baseline' }, 75 | 'top', 76 | 'middle', 77 | 'bottom' 78 | ] 79 | } 80 | 81 | exports.whiteSpace = { 82 | prop: 'white-space', 83 | vals: [ 84 | 'normal', 85 | { nw: 'nowrap' }, 86 | 'pre', 87 | 'inherit' 88 | ] 89 | } 90 | 91 | exports.textColumn = function (options) { 92 | return { 93 | prop: { 94 | tc: 'columns' 95 | }, 96 | vals: options.textColumn 97 | } 98 | } 99 | --------------------------------------------------------------------------------