├── .editorconfig ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── SUPPORT.md ├── bower.json ├── flexibility.js ├── lib ├── README.md ├── flexbox │ ├── README.md │ ├── align-content │ │ ├── README.md │ │ └── index.js │ ├── align-items │ │ ├── README.md │ │ └── index.js │ ├── flex-direction │ │ ├── README.md │ │ └── index.js │ ├── flex-grow │ │ ├── README.md │ │ └── index.js │ ├── flex-shrink │ │ ├── README.md │ │ └── index.js │ ├── flexbox-lines │ │ ├── README.md │ │ └── index.js │ ├── index.js │ ├── justify-content │ │ ├── README.md │ │ └── index.js │ ├── margin-cross │ │ ├── README.md │ │ └── index.js │ ├── margin-main │ │ ├── README.md │ │ └── index.js │ ├── order │ │ ├── README.md │ │ └── index.js │ └── reduce │ │ └── index.js ├── index.js ├── read │ ├── README.md │ ├── getComputedLength.js │ └── index.js ├── readAll │ ├── README.md │ └── index.js ├── write │ ├── README.md │ └── index.js └── writeAll │ ├── README.md │ └── index.js ├── package.json └── test ├── flex-direction-column.control.html ├── flex-direction-column.html ├── flex-direction-row.control.html ├── flex-direction-row.html ├── flex-within-flex.html ├── negative-margin.control.html ├── negative-margin.html ├── shared ├── flex-direction-column.html ├── flex-direction-row.html ├── flex-within-flex.html ├── negative-margin.html ├── script.js ├── style.css └── svg.html ├── svg.control.html └── svg.html /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_style = tab 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [*.{json,yml}] 11 | indent_size = 2 12 | indent_style = space 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | .map 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - stable 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | Flexibility Logo 4 | 5 | [![npm][npm-image]][npm-url] [![bower][bower-image]][bower-url] 6 | [![ci][ci-image]][ci-url] [![gitter][gitter-image]][gitter-url] 7 | 8 | ## 2.0.1 (2016-06-29) 9 | 10 | - Added: Support border widths in relation to border styles 11 | 12 | ## 2.0.0 (2016-06-28) 13 | 14 | - Added: Support for flexboxes directly nested within flexboxes 15 | - Added: Support for `box-sizing`, `flex-basis`, `flex-shrink` and `margin` 16 | properties 17 | - Updated: Complete rewrite 18 | 19 | ## 1.0.6 (2016-01-18) 20 | 21 | - Updated: Improved handling of css-layout 22 | - Updated: Cleanup length caching 23 | 24 | ## 1.0.5 (2016-01-18) 25 | 26 | - Updated: Height calculation on flex container 27 | 28 | ## 1.0.4 (2016-01-18) 29 | 30 | - Added: Watch task for development 31 | - Added: onresize response to viewport height changes 32 | - Updated: Length calculations for percentages 33 | - Updated: Tests 34 | 35 | ## 1.0.3 (2016-01-18) 36 | 37 | - Added: Support for `flex-grow` and partial support for `flex`. 38 | - Added: Support for `flex-flow`. 39 | - Updated: Improved support for IE9 inline styles 40 | - Updated: Documentation and tests 41 | - Updated: Build process 42 | 43 | ## 1.0.2 (2016-01-14) 44 | 45 | - Updated: Percentage calculations support 46 | - Updated: Tests 47 | - Updated: Build process 48 | 49 | ## 1.0.1 (2016-01-14) 50 | 51 | - Updated: Reduced resize and length calculations 52 | - Updated: Tests and documentation 53 | 54 | ## 1.0.0 (2016-01-14) 55 | 56 | - Added: Use CSS Layout for Flexbox positioning (https://github.com/facebook/css-layout) 57 | - Added: Support for all longhand Flexbox properties 58 | - Added: Automatic display updates during window resize 59 | - Added: Ability to manually toggle display updates (useful during CSS changes) 60 | - Added: Visual tests 61 | - Updated: Documentation 62 | 63 | ## 0.3.0 (2016-01-08) 64 | 65 | - Added: Bower configuration 66 | - Updated: Fallback for objects without currentStyle (``) 67 | - Updated: White-spacing handling in IE9 68 | - Updated: Lint and test configurations 69 | 70 | ## 0.2.3 (2015-12-30) 71 | 72 | - Updated: License updated in README.md 73 | 74 | ## 0.2.2 (2015-12-30) 75 | 76 | - Updated: License updated from GPL to MIT 77 | 78 | ## 0.2.1 (2015-12-14) 79 | 80 | - Updated: Only allow elements as children of flex at this time 81 | 82 | ## 0.2.0 (2015-12-08) 83 | 84 | - Added: Initial release 85 | 86 | --- 87 | 88 | To learn more about [Flexibility], read the [support] section. 89 | 90 | If you experience an issue, read the [contributing] section before creating an issue. 91 | 92 | [bower-image]: https://img.shields.io/bower/v/flexibility.svg?style=flat-square 93 | [bower-url]: https://libraries.io/bower/flexibility 94 | [ci-image]: https://img.shields.io/travis/jonathantneal/flexibility.svg?style=flat-square 95 | [ci-url]: https://travis-ci.org/jonathantneal/flexibility 96 | [gitter-image]: https://img.shields.io/gitter/room/jonathantneal/flexibility.svg?style=flat-square 97 | [gitter-url]: https://gitter.im/jonathantneal/flexibility 98 | [npm-image]: https://img.shields.io/npm/v/flexibility.svg?style=flat-square 99 | [npm-url]: https://www.npmjs.com/package/flexibility 100 | 101 | [Flexibility]: https://github.com/jonathantneal/flexibility 102 | 103 | [contributing]: CONTRIBUTING.md 104 | [support]: SUPPORT.md 105 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Flexibility Logo 4 | 5 | [![npm][npm-image]][npm-url] [![bower][bower-image]][bower-url] 6 | [![ci][ci-image]][ci-url] [![gitter][gitter-image]][gitter-url] 7 | 8 | You want to help? You rock! Now, take a moment to be sure your contributions 9 | make sense to everyone else. 10 | 11 | ## Reporting Issues 12 | 13 | Found a problem? Want a new feature? 14 | 15 | - See if your issue or idea has [already been reported]. 16 | - Provide a [reduced test case] or a [live example]. 17 | 18 | These are as easy to do as they are to forget. So, to keep things moving along, 19 | issues that do not meet these standards will be removed after 1 day. 20 | 21 | And remember, a bug is a _demonstrable problem_ caused by _our_ code. 22 | 23 | ## Submitting Pull Requests 24 | 25 | Pull requests are the greatest contributions, so be sure they are focused in 26 | scope, and do avoid unrelated commits. 27 | 28 | 1. To begin, [fork this project], clone your fork, and add our upstream. 29 | ```bash 30 | # Clone your fork of the repo into the current directory 31 | git clone https://github.com//flexibility 32 | # Navigate to the newly cloned directory 33 | cd flexibility 34 | # Assign the original repo to a remote called "upstream" 35 | git remote add upstream https://github.com/jonathantneal/flexibility 36 | # Install the tools necessary for development 37 | npm install 38 | ``` 39 | 40 | 2. Create a branch for your feature or fix: 41 | ```bash 42 | # Move into a new branch for a feature 43 | git checkout -b feature/thing 44 | ``` 45 | ```bash 46 | # Move into a new branch for a fix 47 | git checkout -b fix/something 48 | ``` 49 | 50 | 3. Be sure your code follows our practices. 51 | ```bash 52 | # Test current code 53 | npm run test 54 | ``` 55 | 56 | 4. Push your branch up to your fork: 57 | ```bash 58 | # Push a feature branch 59 | git push origin feature/thing 60 | ``` 61 | ```bash 62 | # Push a fix branch 63 | git push origin fix/something 64 | ``` 65 | 66 | 5. Now [open a pull request] with a clear title and description. 67 | 68 | --- 69 | 70 | To learn more about [Flexibility], read the [support] section. 71 | 72 | If you experience an issue, read the [contributing] section before creating an 73 | issue. 74 | 75 | [bower-image]: https://img.shields.io/bower/v/flexibility.svg?style=flat-square 76 | [bower-url]: https://libraries.io/bower/flexibility 77 | [ci-image]: https://img.shields.io/travis/jonathantneal/flexibility.svg?style=flat-square 78 | [ci-url]: https://travis-ci.org/jonathantneal/flexibility 79 | [gitter-image]: https://img.shields.io/gitter/room/jonathantneal/flexibility.svg?style=flat-square 80 | [gitter-url]: https://gitter.im/jonathantneal/flexibility 81 | [npm-image]: https://img.shields.io/npm/v/flexibility.svg?style=flat-square 82 | [npm-url]: https://www.npmjs.com/package/flexibility 83 | 84 | [Flexibility]: https://github.com/jonathantneal/flexibility 85 | 86 | [contributing]: CONTRIBUTING.md 87 | [support]: SUPPORT.md 88 | 89 | [already been reported]: https://github.com/jonathantneal/flexibility/issues 90 | [fork this project]: https://github.com/jonathantneal/flexibility/fork 91 | [live example]: http://codepen.io/pen 92 | [open a pull request]: https://help.github.com/articles/using-pull-requests/ 93 | [reduced test case]: https://css-tricks.com/reduced-test-cases/ 94 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright © 2015 Jonathan Neal, 10up 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # flexibility 2 | 3 | Flexibility Logo 4 | 5 | > A JavaScript polyfill for Flexbox 6 | 7 | [![npm][npm-image]][npm-url] [![bower][bower-image]][bower-url] 8 | [![ci][ci-image]][ci-url] [![gitter][gitter-image]][gitter-url] 9 | 10 | [Flexibility] is a polyfill for the [Flexible Box Layout], commonly known as 11 | Flexbox. With Flexibility, you get to design beautiful, flexible layouts on the 12 | web without sacrificing the experience in older browsers. 13 | 14 | Flexbox lays out, aligns, and distributes elements in a container, even 15 | when their size is unknown or dynamic. To better understand Flexbox, read 16 | [Chris Coyier]’s excellent [Complete Guide to Flexbox]. 17 | 18 | To start using Flexbox in Internet Explorer 8 & 9 or any older browser, download the 19 | [flexibility.js] script and include it anywhere on your page. 20 | 21 | ```html 22 | 23 | ``` 24 | 25 | If you’re only targeting Internet Explorer 10 and lower, add a 26 | `-js-display: flex` declaration before any `display: flex` declarations in your 27 | CSS, or use [PostCSS Flexibility] to automate this during your build process. 28 | 29 | ```css 30 | .container { 31 | -js-display: flex; 32 | display: flex; 33 | } 34 | ``` 35 | 36 | If you’re targeting other browsers, use the `data-style` attribute to alert these browsers to your changes. 37 | 38 | ```html 39 |
40 | ``` 41 | 42 | When you’re ready to polyfill flexbox with JavaScript, use the `flexibility` 43 | method on the outermost element you would like to polyfill. 44 | 45 | ```js 46 | flexibility(document.documentElement); 47 | ``` 48 | 49 | ## API 50 | 51 | The global `flexibility` method contains child functions for use within your 52 | own framework. 53 | 54 | ##### `flexibility.read` 55 | 56 | Argument: `Element` 57 | 58 | Return flexbox related styles from an element. 59 | 60 | ##### `flexibility.readAll` 61 | 62 | Argument: `Element` 63 | 64 | Return a list of flexbox details from a matching element or its descendants. 65 | 66 | ##### `flexibility.write` 67 | 68 | Argument: `Details` 69 | 70 | Writes flexbox details back to their respective elements. 71 | 72 | ##### `flexibility.writeAll` 73 | 74 | Argument: `Array` 75 | 76 | Writes a list of flexbox details back to their respective elements. 77 | 78 | --- 79 | 80 | To learn more about [Flexibility], read the [support] section. 81 | 82 | If you experience an issue, read the [contributing] section before creating an 83 | issue. 84 | 85 | [bower-image]: https://img.shields.io/bower/v/flexibility.svg?style=flat-square 86 | [bower-url]: https://libraries.io/bower/flexibility 87 | [ci-image]: https://img.shields.io/travis/jonathantneal/flexibility.svg?style=flat-square 88 | [ci-url]: https://travis-ci.org/jonathantneal/flexibility 89 | [gitter-image]: https://img.shields.io/gitter/room/jonathantneal/flexibility.svg?style=flat-square 90 | [gitter-url]: https://gitter.im/jonathantneal/flexibility 91 | [npm-image]: https://img.shields.io/npm/v/flexibility.svg?style=flat-square 92 | [npm-url]: https://www.npmjs.com/package/flexibility 93 | 94 | [contributing]: CONTRIBUTING.md 95 | [Flexibility]: https://github.com/jonathantneal/flexibility 96 | [flexibility.js]: flexibility.js 97 | [support]: SUPPORT.md 98 | 99 | [Chris Coyier]: https://twitter.com/chriscoyier 100 | [Complete Guide to Flexbox]: https://css-tricks.com/snippets/css/a-guide-to-flexbox/ 101 | [Flexible Box Layout]: http://www.w3.org/TR/css3-flexbox/ 102 | [PostCSS Flexibility]: https://github.com/7rulnik/postcss-flexibility 103 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | Flexibility Logo 4 | 5 | [![npm][npm-image]][npm-url] [![bower][bower-image]][bower-url] 6 | [![ci][ci-image]][ci-url] [![gitter][gitter-image]][gitter-url] 7 | 8 | ## Supported Features 9 | 10 | Name | Value 11 | ----:|------ 12 | `display` | flex \| inline-flex 13 | `flex-direction` | column \| row 14 | `justify-content` | flex-start \| center \| flex-end \| space-between \| space-around 15 | `align-items`, align-self | flex-start \| center \| flex-end \| stretch 16 | `flex` | [flex-grow] 17 | `flex-flow` | `flex-direction` + `flex-wrap` 18 | `flex-grow` | [CSS Number] 19 | `flex-wrap` | wrap \| nowrap 20 | `order` | [CSS Integer] 21 | `width`, `min-width`, `max-width` | [CSS Length] 22 | `height`, `min-height`, `max-height` | [CSS Length] 23 | `margin`, `margin-left`, `margin-right`, `margin-top`, `margin-bottom` | [CSS Length] 24 | `padding`, `padding-left`, `padding-right`, `padding-top`, `padding-bottom` | [CSS Length] 25 | `border-width`, `border-left-width`, `border-right-width`, `border-top-width`, `border-bottom-width` | [CSS Length] 26 | 27 | ## Known Issues 28 | 29 | - The `flex` shorthand only supports `flex-grow` at this time. 30 | - Changing an `align-items: stretch` container from `flex-direction: row` to 31 | `flex-direction: column` on the fly will sometimes fail to stretch the newly 32 | columned items. 33 | - IE8 believes everything is `margin: auto` unless you first set `* { margin: 0; }`. Afterward, `margin: auto` will work as expected. 34 | - In IE8, flex items whose widths are determined by inline text don’t alway 35 | resize on resize. 36 | 37 | ### How Flexibility Works 38 | 39 | Flexibility uses `data-style` attributes, inline and computed styles, and the 40 | proprietary Internet Explorer `currentStyle` property to determine the current 41 | flex styles of an element. 42 | 43 | Internet Explorer’s proprietary [`currentStyle`] property returns the raw CSS 44 | applied to an element. While known properties (like `display`) are sanitized to 45 | return only valid values, “unknown” properties like `align-contents`, 46 | `justify-content`, and `flex` return exactly what they received. As a result, 47 | “unknown” flex properties can be easily read from any element without fetching 48 | or parsing stylesheets. In short, your cross domain CSS is safe. 49 | 50 | Once all of the flex values are processed, basic flex display is applied to the 51 | document. Then, [CSS Layout] calculates the positions for elements to simulate 52 | Flexbox. 53 | 54 | ### Detecting Flexbox Support 55 | 56 | Flexibility does not include a detection script. You may already have one if 57 | you use Modernizr. 58 | 59 | ```js 60 | if (Modernizr.flexbox && Modernizr.flexwrap) { 61 | // Modern Flexbox with `flex-wrap` is supported 62 | } else { 63 | flexibility(document.documentElement); 64 | } 65 | ``` 66 | 67 | You could also include your basic test. 68 | 69 | ```js 70 | function supportsFlexBox() { 71 | var test = document.createElement('test'); 72 | 73 | test.style.display = 'flex'; 74 | 75 | return test.style.display === 'flex'; 76 | } 77 | 78 | if (supportsFlexBox()) { 79 | // Modern Flexbox is supported 80 | } else { 81 | flexibility(document.documentElement); 82 | } 83 | ``` 84 | 85 | ### Responding to Window Resize 86 | 87 | If recalculating Flexbox on resizes, be mindful of infinite loops caused by 88 | Flexbox itself triggering a resize. A small debounce will resolve this. 89 | 90 | ```js 91 | var onresizeTimeout; 92 | 93 | window.onresize = onresize; 94 | 95 | function onresize() { 96 | window.onresize = null; 97 | 98 | if (!onresizeTimeout) { 99 | onresizeTimeout = setTimeout(function () { 100 | onresizeTimeout = null; 101 | 102 | flexibility(container); 103 | 104 | window.onresize = onresize; 105 | }, 1000 / 60); 106 | } 107 | } 108 | ``` 109 | 110 | --- 111 | 112 | If you experience an issue, read the [contributing] section before creating an 113 | issue. 114 | 115 | [bower-image]: https://img.shields.io/bower/v/flexibility.svg?style=flat-square 116 | [bower-url]: https://libraries.io/bower/flexibility 117 | [ci-image]: https://img.shields.io/travis/jonathantneal/flexibility.svg?style=flat-square 118 | [ci-url]: https://travis-ci.org/jonathantneal/flexibility 119 | [gitter-image]: https://img.shields.io/gitter/room/jonathantneal/flexibility.svg?style=flat-square 120 | [gitter-url]: https://gitter.im/jonathantneal/flexibility 121 | [npm-image]: https://img.shields.io/npm/v/flexibility.svg?style=flat-square 122 | [npm-url]: https://www.npmjs.com/package/flexibility 123 | 124 | [Flexibility]: https://github.com/jonathantneal/flexibility 125 | 126 | [contributing]: CONTRIBUTING.md 127 | 128 | [CSS Integer]: https://developer.mozilla.org/en-US/docs/Web/CSS/integer#Interpolation 129 | [CSS Layout]: https://github.com/jonathantneal/flexibility/tree/css-layout 130 | [CSS Length]: https://developer.mozilla.org/en-US/docs/Web/CSS/length 131 | 132 | [`currentStyle`]: http://help.dottoro.com/ljqkvomc.php 133 | [`runtimeStyle`]: http://help.dottoro.com/ljhddfwr.php 134 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flexibility", 3 | "description": "Use Flexbox while supporting older Internet Explorers", 4 | "main": "flexibility.js", 5 | "authors": [ 6 | "Jonathan Neal (http://jonathantneal.com)" 7 | ], 8 | "license": "MIT", 9 | "keywords": [ 10 | "flex", 11 | "display", 12 | "direction", 13 | "wrap", 14 | "flow", 15 | "justify", 16 | "content", 17 | "align", 18 | "items", 19 | "content", 20 | "order", 21 | "grow", 22 | "shrink", 23 | "basis", 24 | "self", 25 | "auto", 26 | "start", 27 | "end", 28 | "center", 29 | "baseline", 30 | "stretch", 31 | "space", 32 | "between", 33 | "around", 34 | "polyfill", 35 | "ie", 36 | "internet", 37 | "explorer", 38 | "layout" 39 | ], 40 | "homepage": "https://github.com/jonathantneal/flexibility.git", 41 | "moduleType": [], 42 | "ignore": [ 43 | "bower_components", 44 | "lib", 45 | "node_modules", 46 | "tests" 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /flexibility.js: -------------------------------------------------------------------------------- 1 | !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.flexibility=e()}}(function(){return function e(t,r,l){function n(f,i){if(!r[f]){if(!t[f]){var s="function"==typeof require&&require;if(!i&&s)return s(f,!0);if(o)return o(f,!0);var a=new Error("Cannot find module '"+f+"'");throw a.code="MODULE_NOT_FOUND",a}var c=r[f]={exports:{}};t[f][0].call(c.exports,function(e){var r=t[f][1][e];return n(r?r:e)},c,c.exports,e,t,r,l)}return r[f].exports}for(var o="function"==typeof require&&require,f=0;f1&&"flex-start"===e.style.alignContent)for(t=0;l=e.lines[++n];)l.crossStart=t,t+=l.cross;else if(e.lines.length>1&&"flex-end"===e.style.alignContent)for(t=e.flexStyle.crossSpace;l=e.lines[++n];)l.crossStart=t,t+=l.cross;else if(e.lines.length>1&&"center"===e.style.alignContent)for(t=e.flexStyle.crossSpace/2;l=e.lines[++n];)l.crossStart=t,t+=l.cross;else if(e.lines.length>1&&"space-between"===e.style.alignContent)for(r=e.flexStyle.crossSpace/(e.lines.length-1),t=0;l=e.lines[++n];)l.crossStart=t,t+=l.cross+r;else if(e.lines.length>1&&"space-around"===e.style.alignContent)for(r=2*e.flexStyle.crossSpace/(2*e.lines.length),t=r/2;l=e.lines[++n];)l.crossStart=t,t+=l.cross+r;else for(r=e.flexStyle.crossSpace/e.lines.length,t=e.flexStyle.crossInnerBefore;l=e.lines[++n];)l.crossStart=t,l.cross+=r,t+=l.cross}},{}],2:[function(e,t,r){t.exports=function(e){for(var t,r=-1;line=e.lines[++r];)for(t=-1;child=line.children[++t];){var l=child.style.alignSelf;"auto"===l&&(l=e.style.alignItems),"flex-start"===l?child.flexStyle.crossStart=line.crossStart:"flex-end"===l?child.flexStyle.crossStart=line.crossStart+line.cross-child.flexStyle.crossOuter:"center"===l?child.flexStyle.crossStart=line.crossStart+(line.cross-child.flexStyle.crossOuter)/2:(child.flexStyle.crossStart=line.crossStart,child.flexStyle.crossOuter=line.cross,child.flexStyle.cross=child.flexStyle.crossOuter-child.flexStyle.crossBefore-child.flexStyle.crossAfter)}}},{}],3:[function(e,t,r){t.exports=function l(e,l){var t="row"===l||"row-reverse"===l,r=e.mainAxis;if(r){var n=t&&"inline"===r||!t&&"block"===r;n||(e.flexStyle={main:e.flexStyle.cross,cross:e.flexStyle.main,mainOffset:e.flexStyle.crossOffset,crossOffset:e.flexStyle.mainOffset,mainBefore:e.flexStyle.crossBefore,mainAfter:e.flexStyle.crossAfter,crossBefore:e.flexStyle.mainBefore,crossAfter:e.flexStyle.mainAfter,mainInnerBefore:e.flexStyle.crossInnerBefore,mainInnerAfter:e.flexStyle.crossInnerAfter,crossInnerBefore:e.flexStyle.mainInnerBefore,crossInnerAfter:e.flexStyle.mainInnerAfter,mainBorderBefore:e.flexStyle.crossBorderBefore,mainBorderAfter:e.flexStyle.crossBorderAfter,crossBorderBefore:e.flexStyle.mainBorderBefore,crossBorderAfter:e.flexStyle.mainBorderAfter})}else t?e.flexStyle={main:e.style.width,cross:e.style.height,mainOffset:e.style.offsetWidth,crossOffset:e.style.offsetHeight,mainBefore:e.style.marginLeft,mainAfter:e.style.marginRight,crossBefore:e.style.marginTop,crossAfter:e.style.marginBottom,mainInnerBefore:e.style.paddingLeft,mainInnerAfter:e.style.paddingRight,crossInnerBefore:e.style.paddingTop,crossInnerAfter:e.style.paddingBottom,mainBorderBefore:e.style.borderLeftWidth,mainBorderAfter:e.style.borderRightWidth,crossBorderBefore:e.style.borderTopWidth,crossBorderAfter:e.style.borderBottomWidth}:e.flexStyle={main:e.style.height,cross:e.style.width,mainOffset:e.style.offsetHeight,crossOffset:e.style.offsetWidth,mainBefore:e.style.marginTop,mainAfter:e.style.marginBottom,crossBefore:e.style.marginLeft,crossAfter:e.style.marginRight,mainInnerBefore:e.style.paddingTop,mainInnerAfter:e.style.paddingBottom,crossInnerBefore:e.style.paddingLeft,crossInnerAfter:e.style.paddingRight,mainBorderBefore:e.style.borderTopWidth,mainBorderAfter:e.style.borderBottomWidth,crossBorderBefore:e.style.borderLeftWidth,crossBorderAfter:e.style.borderRightWidth},"content-box"===e.style.boxSizing&&("number"==typeof e.flexStyle.main&&(e.flexStyle.main+=e.flexStyle.mainInnerBefore+e.flexStyle.mainInnerAfter+e.flexStyle.mainBorderBefore+e.flexStyle.mainBorderAfter),"number"==typeof e.flexStyle.cross&&(e.flexStyle.cross+=e.flexStyle.crossInnerBefore+e.flexStyle.crossInnerAfter+e.flexStyle.crossBorderBefore+e.flexStyle.crossBorderAfter));e.mainAxis=t?"inline":"block",e.crossAxis=t?"block":"inline","number"==typeof e.style.flexBasis&&(e.flexStyle.main=e.style.flexBasis+e.flexStyle.mainInnerBefore+e.flexStyle.mainInnerAfter+e.flexStyle.mainBorderBefore+e.flexStyle.mainBorderAfter),e.flexStyle.mainOuter=e.flexStyle.main,e.flexStyle.crossOuter=e.flexStyle.cross,"auto"===e.flexStyle.mainOuter&&(e.flexStyle.mainOuter=e.flexStyle.mainOffset),"auto"===e.flexStyle.crossOuter&&(e.flexStyle.crossOuter=e.flexStyle.crossOffset),"number"==typeof e.flexStyle.mainBefore&&(e.flexStyle.mainOuter+=e.flexStyle.mainBefore),"number"==typeof e.flexStyle.mainAfter&&(e.flexStyle.mainOuter+=e.flexStyle.mainAfter),"number"==typeof e.flexStyle.crossBefore&&(e.flexStyle.crossOuter+=e.flexStyle.crossBefore),"number"==typeof e.flexStyle.crossAfter&&(e.flexStyle.crossOuter+=e.flexStyle.crossAfter)}},{}],4:[function(e,t,r){var l=e("../reduce");t.exports=function(e){if(e.mainSpace>0){var t=l(e.children,function(e,t){return e+parseFloat(t.style.flexGrow)},0);t>0&&(e.main=l(e.children,function(r,l){return"auto"===l.flexStyle.main?l.flexStyle.main=l.flexStyle.mainOffset+parseFloat(l.style.flexGrow)/t*e.mainSpace:l.flexStyle.main+=parseFloat(l.style.flexGrow)/t*e.mainSpace,l.flexStyle.mainOuter=l.flexStyle.main+l.flexStyle.mainBefore+l.flexStyle.mainAfter,r+l.flexStyle.mainOuter},0),e.mainSpace=0)}}},{"../reduce":12}],5:[function(e,t,r){var l=e("../reduce");t.exports=function(e){if(e.mainSpace<0){var t=l(e.children,function(e,t){return e+parseFloat(t.style.flexShrink)},0);t>0&&(e.main=l(e.children,function(r,l){return l.flexStyle.main+=parseFloat(l.style.flexShrink)/t*e.mainSpace,l.flexStyle.mainOuter=l.flexStyle.main+l.flexStyle.mainBefore+l.flexStyle.mainAfter,r+l.flexStyle.mainOuter},0),e.mainSpace=0)}}},{"../reduce":12}],6:[function(e,t,r){var l=e("../reduce");t.exports=function(e){var t;e.lines=[t={main:0,cross:0,children:[]}];for(var r,n=-1;r=e.children[++n];)"nowrap"===e.style.flexWrap||0===t.children.length||"auto"===e.flexStyle.main||e.flexStyle.main-e.flexStyle.mainInnerBefore-e.flexStyle.mainInnerAfter-e.flexStyle.mainBorderBefore-e.flexStyle.mainBorderAfter>=t.main+r.flexStyle.mainOuter?(t.main+=r.flexStyle.mainOuter,t.cross=Math.max(t.cross,r.flexStyle.crossOuter)):e.lines.push(t={main:r.flexStyle.mainOuter,cross:r.flexStyle.crossOuter,children:[]}),t.children.push(r);e.flexStyle.mainLines=l(e.lines,function(e,t){return Math.max(e,t.main)},0),e.flexStyle.crossLines=l(e.lines,function(e,t){return e+t.cross},0),"auto"===e.flexStyle.main&&(e.flexStyle.main=Math.max(e.flexStyle.mainOffset,e.flexStyle.mainLines+e.flexStyle.mainInnerBefore+e.flexStyle.mainInnerAfter+e.flexStyle.mainBorderBefore+e.flexStyle.mainBorderAfter)),"auto"===e.flexStyle.cross&&(e.flexStyle.cross=Math.max(e.flexStyle.crossOffset,e.flexStyle.crossLines+e.flexStyle.crossInnerBefore+e.flexStyle.crossInnerAfter+e.flexStyle.crossBorderBefore+e.flexStyle.crossBorderAfter)),e.flexStyle.crossSpace=e.flexStyle.cross-e.flexStyle.crossInnerBefore-e.flexStyle.crossInnerAfter-e.flexStyle.crossBorderBefore-e.flexStyle.crossBorderAfter-e.flexStyle.crossLines,e.flexStyle.mainOuter=e.flexStyle.main+e.flexStyle.mainBefore+e.flexStyle.mainAfter,e.flexStyle.crossOuter=e.flexStyle.cross+e.flexStyle.crossBefore+e.flexStyle.crossAfter}},{"../reduce":12}],7:[function(e,t,r){function l(t){for(var r,l=-1;r=t.children[++l];)e("./flex-direction")(r,t.style.flexDirection);e("./flex-direction")(t,t.style.flexDirection),e("./order")(t),e("./flexbox-lines")(t),e("./align-content")(t),l=-1;for(var n;n=t.lines[++l];)n.mainSpace=t.flexStyle.main-t.flexStyle.mainInnerBefore-t.flexStyle.mainInnerAfter-t.flexStyle.mainBorderBefore-t.flexStyle.mainBorderAfter-n.main,e("./flex-grow")(n),e("./flex-shrink")(n),e("./margin-main")(n),e("./margin-cross")(n),e("./justify-content")(n,t.style.justifyContent,t);e("./align-items")(t)}t.exports=l},{"./align-content":1,"./align-items":2,"./flex-direction":3,"./flex-grow":4,"./flex-shrink":5,"./flexbox-lines":6,"./justify-content":8,"./margin-cross":9,"./margin-main":10,"./order":11}],8:[function(e,t,r){t.exports=function(e,t,r){var l,n,o,f=r.flexStyle.mainInnerBefore,i=-1;if("flex-end"===t)for(l=e.mainSpace,l+=f;o=e.children[++i];)o.flexStyle.mainStart=l,l+=o.flexStyle.mainOuter;else if("center"===t)for(l=e.mainSpace/2,l+=f;o=e.children[++i];)o.flexStyle.mainStart=l,l+=o.flexStyle.mainOuter;else if("space-between"===t)for(n=e.mainSpace/(e.children.length-1),l=0,l+=f;o=e.children[++i];)o.flexStyle.mainStart=l,l+=o.flexStyle.mainOuter+n;else if("space-around"===t)for(n=2*e.mainSpace/(2*e.children.length),l=n/2,l+=f;o=e.children[++i];)o.flexStyle.mainStart=l,l+=o.flexStyle.mainOuter+n;else for(l=0,l+=f;o=e.children[++i];)o.flexStyle.mainStart=l,l+=o.flexStyle.mainOuter}},{}],9:[function(e,t,r){t.exports=function(e){for(var t,r=-1;t=e.children[++r];){var l=0;"auto"===t.flexStyle.crossBefore&&++l,"auto"===t.flexStyle.crossAfter&&++l;var n=e.cross-t.flexStyle.crossOuter;"auto"===t.flexStyle.crossBefore&&(t.flexStyle.crossBefore=n/l),"auto"===t.flexStyle.crossAfter&&(t.flexStyle.crossAfter=n/l),"auto"===t.flexStyle.cross?t.flexStyle.crossOuter=t.flexStyle.crossOffset+t.flexStyle.crossBefore+t.flexStyle.crossAfter:t.flexStyle.crossOuter=t.flexStyle.cross+t.flexStyle.crossBefore+t.flexStyle.crossAfter}}},{}],10:[function(e,t,r){t.exports=function(e){for(var t,r=0,l=-1;t=e.children[++l];)"auto"===t.flexStyle.mainBefore&&++r,"auto"===t.flexStyle.mainAfter&&++r;if(r>0){for(l=-1;t=e.children[++l];)"auto"===t.flexStyle.mainBefore&&(t.flexStyle.mainBefore=e.mainSpace/r),"auto"===t.flexStyle.mainAfter&&(t.flexStyle.mainAfter=e.mainSpace/r),"auto"===t.flexStyle.main?t.flexStyle.mainOuter=t.flexStyle.mainOffset+t.flexStyle.mainBefore+t.flexStyle.mainAfter:t.flexStyle.mainOuter=t.flexStyle.main+t.flexStyle.mainBefore+t.flexStyle.mainAfter;e.mainSpace=0}}},{}],11:[function(e,t,r){var l=/^(column|row)-reverse$/;t.exports=function(e){e.children.sort(function(e,t){return e.style.order-t.style.order||e.index-t.index}),l.test(e.style.flexDirection)&&e.children.reverse()}},{}],12:[function(e,t,r){function l(e,t,r){for(var l=e.length,n=-1;++n https://drafts.csswg.org/css-flexbox-1/ 8 | -------------------------------------------------------------------------------- /lib/flexbox/align-content/README.md: -------------------------------------------------------------------------------- 1 | # align-content 2 | 3 | The `align-content` method calculates the position of flex lines along the cross axis. 4 | 5 | ```js 6 | alignContent( target, target.alignContent ) 7 | ``` 8 | 9 | ### Specification 10 | 11 | > https://drafts.csswg.org/css-flexbox-1/#propdef-align-content 12 | 13 | 1. If the count of `target.lines` is less than `2`, or; 14 | if `target.align-content` is `"stretch"`; 15 | 1. Let `factor` be `target.cross-space` divided by the length of `target.lines`. 16 | - Let `start` be `0`. 17 | - For each `line` in `target.lines`; 18 | 1. Let `line.cross-start` be `start`. 19 | - Let `line.cross` be itself and `factor`. 20 | - Let `start` be itself and `line.cross`. 21 | - If `target.align-content` is `"flex-start"`; 22 | 1. Let `start` be `0`. 23 | - For each `line` in `target.lines`; 24 | 1. Let `line.cross-start` be `start`. 25 | - Let `start` be itself and `line.cross`. 26 | - If `target.align-content` is `"flex-end"`; 27 | 1. Let `start` be `target.cross-space`. 28 | - For each `line` in `target.lines`; 29 | 1. Let `line.cross-start` be `start`. 30 | - Let `start` be itself and `line.cross`. 31 | - If `target.align-content` is `"center"`; 32 | 1. Let `start` be `target.cross-space` divided by `2`. 33 | - For each `line` in `target.lines`; 34 | 1. Let `line.cross-start` be `start`. 35 | - Let `start` be itself and `line.cross`. 36 | - If `target.align-content` is `"space-between"`; 37 | 1. Let `factor` be `target.cross-space` divided by; the length of `lines` sans `1`. 38 | - Let `start` be `0`. 39 | - For each `line` in `target.lines`; 40 | 1. Let `line.cross-start` be `start`. 41 | - Let `start` be itself and `line.cross` and `factor`. 42 | - If `target.align-content` is `"space-around"`; 43 | 1. Let `factor` be `target.cross-space` multiplied by `2` divided by; the length of `lines` multiplied by `2`. 44 | - Let `start` be `factor` divided by `2`. 45 | - For each `line` in `target.lines`; 46 | 1. Let `line.cross-start` be `start`. 47 | - Let `start` be itself and `line.cross` and `factor`. 48 | - If `target.align-content` is `"stretch"`; 49 | 1. Let `factor` be `target.cross-space` divided by the length of `target.lines`. 50 | 1. Let `start` be `0`. 51 | - For each `line` in `target.lines`; 52 | 1. Let `line.cross-start` be `start`. 53 | - Line `line.cross` be `factor`. 54 | - Let `start` be itself and `line.cross` and `factor`. 55 | 56 | [Implementation](index.js) [Tests](test.js) 57 | -------------------------------------------------------------------------------- /lib/flexbox/align-content/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function alignContent(details) { 2 | var start; 3 | var factor; 4 | 5 | var index = -1; 6 | var line; 7 | 8 | if (details.lines.length > 1 && details.style.alignContent === 'flex-start') { 9 | start = 0; 10 | 11 | while (line = details.lines[++index]) { 12 | line.crossStart = start; 13 | 14 | start += line.cross; 15 | } 16 | } else if (details.lines.length > 1 && details.style.alignContent === 'flex-end') { 17 | start = details.flexStyle.crossSpace; 18 | 19 | while (line = details.lines[++index]) { 20 | line.crossStart = start; 21 | 22 | start += line.cross; 23 | } 24 | } else if (details.lines.length > 1 && details.style.alignContent === 'center') { 25 | start = details.flexStyle.crossSpace / 2; 26 | 27 | while (line = details.lines[++index]) { 28 | line.crossStart = start; 29 | 30 | start += line.cross; 31 | } 32 | } else if (details.lines.length > 1 && details.style.alignContent === 'space-between') { 33 | factor = details.flexStyle.crossSpace / (details.lines.length - 1); 34 | start = 0; 35 | 36 | while (line = details.lines[++index]) { 37 | line.crossStart = start; 38 | 39 | start += line.cross + factor; 40 | } 41 | } else if (details.lines.length > 1 && details.style.alignContent === 'space-around') { 42 | factor = details.flexStyle.crossSpace * 2 / (details.lines.length * 2); 43 | start = factor / 2; 44 | 45 | while (line = details.lines[++index]) { 46 | line.crossStart = start; 47 | 48 | start += line.cross + factor; 49 | } 50 | } else { 51 | factor = details.flexStyle.crossSpace / details.lines.length; 52 | start = details.flexStyle.crossInnerBefore; 53 | 54 | while (line = details.lines[++index]) { 55 | line.crossStart = start; 56 | line.cross += factor; 57 | 58 | start += line.cross; 59 | } 60 | } 61 | }; 62 | -------------------------------------------------------------------------------- /lib/flexbox/align-items/README.md: -------------------------------------------------------------------------------- 1 | # align-items 2 | 3 | The `align-self` method calculates the position of flex items along the cross axis. 4 | 5 | ```js 6 | alignItems( target ) 7 | ``` 8 | 9 | ### Specification 10 | 11 | > https://drafts.csswg.org/css-flexbox-1/#propdef-align-items 12 | 13 | 1. For each `line` in `target.lines`; 14 | 1. For each `child` in `line.children`; 15 | - If `child.align-self` is `"flex-start"`; 16 | 1. Let `child.cross-start` be itself. 17 | - Otherwise, if `child.align-self` is `"flex-end"`; 18 | 1. Let `child.cross-start` be `line.cross-start` and `line.cross` sans `child.cross-around`. 19 | - Otherwise, if `child.align-self` is `"center"`; 20 | 1. Let `child.cross-start` be `line.cross-start` and; `line.cross` sans `child.cross-around`; divided by `2`. 21 | - Otherwise, if `child.align-self` is `"stretch"`; 22 | 1. Let `child.cross-start` be `line.cross-start`. 23 | - Let `child.cross` be `line.cross`. 24 | 25 | [Implementation](index.js) [Tests](test.js) 26 | -------------------------------------------------------------------------------- /lib/flexbox/align-items/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function alignItems(details) { 2 | var indexA = -1; 3 | var indexB; 4 | var line; 5 | 6 | while (line = details.lines[++indexA]) { 7 | indexB = -1; 8 | 9 | var child; 10 | 11 | while (child = line.children[++indexB]) { 12 | var alignSelf = child.style.alignSelf; 13 | 14 | if (alignSelf === 'auto') { 15 | alignSelf = details.style.alignItems; 16 | } 17 | 18 | if (alignSelf === 'flex-start') { 19 | child.flexStyle.crossStart = line.crossStart; 20 | } else if (alignSelf === 'flex-end') { 21 | child.flexStyle.crossStart = line.crossStart + line.cross - child.flexStyle.crossOuter; 22 | } else if (alignSelf === 'center') { 23 | child.flexStyle.crossStart = line.crossStart + (line.cross - child.flexStyle.crossOuter) / 2; 24 | } else { 25 | child.flexStyle.crossStart = line.crossStart; 26 | child.flexStyle.crossOuter = line.cross; 27 | 28 | child.flexStyle.cross = child.flexStyle.crossOuter - child.flexStyle.crossBefore - child.flexStyle.crossAfter; 29 | } 30 | } 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /lib/flexbox/flex-direction/README.md: -------------------------------------------------------------------------------- 1 | # flex-direction 2 | 3 | The `flex-direction` methods calculates the axis and lengths of a flex container or item. 4 | 5 | ```js 6 | flexDirection( child, target.flexDirection, target.alignItems ) 7 | ``` 8 | 9 | ### Specification 10 | 11 | > https://drafts.csswg.org/css-flexbox-1/#propdef-flex-direction 12 | 13 | 1. If `display` is `"flex"`; 14 | 1. For each `child` in `target.children`; 15 | 1. Let `child.node.style.display` be `"inline-block"`; 16 | - Perform `flex-direction( child, target.flex-direction, target.align-items )`. 17 | 1. If `flex-direction` is `"row"` or `"row-reverse"`; 18 | 1. Let `target.main-axis` be `"inline"`. 19 | - Let `target.cross-axis` be `"block"`. 20 | - Let `target.main` be `target.width`. 21 | - Let `target.cross` be `target.height`. 22 | - Let `target.main-client` be `target.rectangle-width`. 23 | - Let `target.cross-client` be `target.rectangle-height`. 24 | - Let `target.main-before` be `target.margin-left`. 25 | - Let `target.main-after` be `target.margin-right`. 26 | - Let `target.cross-before` be `target.margin-top`. 27 | - Let `target.cross-after` be `target.margin-bottom`. 28 | - Otherwise, if `target.flex-direction` is `column` or `column-reverse`; 29 | 1. Let `target.main-axis` be `"block"`. 30 | - Let `target.cross-axis` be `"inline"`. 31 | - Let `target.main` be `target.height`. 32 | - Let `target.cross` be `target.width`. 33 | - Let `target.main-client` be `target.rectangle-height`. 34 | - Let `target.cross-client` be `target.rectangle-width`. 35 | - Let `target.main-before` be `target.margin-top`. 36 | - Let `target.main-after` be `target.margin-bottom`. 37 | - Let `target.cross-before` be `target.margin-left`. 38 | - Let `target.cross-after` be `target.margin-right`. 39 | - If `target.flex-basis` is a `Number`; 40 | 1. Let `target.main` is `target.flex-basis`. 41 | - If `target.main` is `"auto"`; 42 | 1. Let `target.main-around` be `target.main-client`. 43 | - Otherwise; 44 | 1. Let `target.main-around` be `target.main`. 45 | - If `target.cross` is `"auto"`; 46 | 1. Let `target.cross-around` be `target.cross-client`. 47 | - Otherwise; 48 | 1. Let `target.cross-around` be `target.cross`. 49 | - If `target.main-before` is a `Number`; 50 | 1. Let `target.main-around` be itself and `target.main-before`. 51 | - If `target.main-after` is a `Number`; 52 | 1. Let `target.main-around` be itself and `target.main-after`. 53 | - If `target.cross-before` is a `Number`; 54 | 1. Let `target.cross-around` be itself and `target.cross-before`. 55 | - If `target.cross-after` is a `Number`; 56 | 1. Let `target.cross-around` be itself and `target.cross-after`. 57 | - If `target.align-self` is `"auto"`; 58 | 1. Let `target.align-self` be `align-items`. 59 | 60 | [Implementation](index.js) [Tests](test.js) 61 | -------------------------------------------------------------------------------- /lib/flexbox/flex-direction/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function flexDirection(target, flexDirectionArg) { 2 | var isInline = flexDirectionArg === 'row' || flexDirectionArg === 'row-reverse'; 3 | var existingAxis = target.mainAxis; 4 | 5 | if (existingAxis) { 6 | var isMatchingInline = isInline && existingAxis === 'inline' || !isInline && existingAxis === 'block'; 7 | 8 | if (!isMatchingInline) { 9 | target.flexStyle = { 10 | main: target.flexStyle.cross, 11 | cross: target.flexStyle.main, 12 | 13 | mainOffset: target.flexStyle.crossOffset, 14 | crossOffset: target.flexStyle.mainOffset, 15 | 16 | mainBefore: target.flexStyle.crossBefore, 17 | mainAfter: target.flexStyle.crossAfter, 18 | crossBefore: target.flexStyle.mainBefore, 19 | crossAfter: target.flexStyle.mainAfter, 20 | 21 | mainInnerBefore: target.flexStyle.crossInnerBefore, 22 | mainInnerAfter: target.flexStyle.crossInnerAfter, 23 | crossInnerBefore: target.flexStyle.mainInnerBefore, 24 | crossInnerAfter: target.flexStyle.mainInnerAfter, 25 | 26 | mainBorderBefore: target.flexStyle.crossBorderBefore, 27 | mainBorderAfter: target.flexStyle.crossBorderAfter, 28 | crossBorderBefore: target.flexStyle.mainBorderBefore, 29 | crossBorderAfter: target.flexStyle.mainBorderAfter 30 | }; 31 | } 32 | } else { 33 | if (isInline) { 34 | target.flexStyle = { 35 | main: target.style.width, 36 | cross: target.style.height, 37 | 38 | mainOffset: target.style.offsetWidth, 39 | crossOffset: target.style.offsetHeight, 40 | 41 | mainBefore: target.style.marginLeft, 42 | mainAfter: target.style.marginRight, 43 | crossBefore: target.style.marginTop, 44 | crossAfter: target.style.marginBottom, 45 | 46 | mainInnerBefore: target.style.paddingLeft, 47 | mainInnerAfter: target.style.paddingRight, 48 | crossInnerBefore: target.style.paddingTop, 49 | crossInnerAfter: target.style.paddingBottom, 50 | 51 | mainBorderBefore: target.style.borderLeftWidth, 52 | mainBorderAfter: target.style.borderRightWidth, 53 | crossBorderBefore: target.style.borderTopWidth, 54 | crossBorderAfter: target.style.borderBottomWidth 55 | }; 56 | } else { 57 | target.flexStyle = { 58 | main: target.style.height, 59 | cross: target.style.width, 60 | 61 | mainOffset: target.style.offsetHeight, 62 | crossOffset: target.style.offsetWidth, 63 | 64 | mainBefore: target.style.marginTop, 65 | mainAfter: target.style.marginBottom, 66 | crossBefore: target.style.marginLeft, 67 | crossAfter: target.style.marginRight, 68 | 69 | mainInnerBefore: target.style.paddingTop, 70 | mainInnerAfter: target.style.paddingBottom, 71 | crossInnerBefore: target.style.paddingLeft, 72 | crossInnerAfter: target.style.paddingRight, 73 | 74 | mainBorderBefore: target.style.borderTopWidth, 75 | mainBorderAfter: target.style.borderBottomWidth, 76 | crossBorderBefore: target.style.borderLeftWidth, 77 | crossBorderAfter: target.style.borderRightWidth 78 | }; 79 | } 80 | 81 | if (target.style.boxSizing === 'content-box') { 82 | if (typeof target.flexStyle.main === 'number') { 83 | target.flexStyle.main += target.flexStyle.mainInnerBefore + target.flexStyle.mainInnerAfter + target.flexStyle.mainBorderBefore + target.flexStyle.mainBorderAfter; 84 | } 85 | 86 | if (typeof target.flexStyle.cross === 'number') { 87 | target.flexStyle.cross += target.flexStyle.crossInnerBefore + target.flexStyle.crossInnerAfter + target.flexStyle.crossBorderBefore + target.flexStyle.crossBorderAfter; 88 | } 89 | } 90 | } 91 | 92 | target.mainAxis = isInline ? 'inline' : 'block'; 93 | target.crossAxis = isInline ? 'block' : 'inline'; 94 | 95 | if (typeof target.style.flexBasis === 'number') { 96 | target.flexStyle.main = target.style.flexBasis + target.flexStyle.mainInnerBefore + target.flexStyle.mainInnerAfter + target.flexStyle.mainBorderBefore + target.flexStyle.mainBorderAfter; 97 | } 98 | 99 | target.flexStyle.mainOuter = target.flexStyle.main; 100 | target.flexStyle.crossOuter = target.flexStyle.cross; 101 | 102 | if (target.flexStyle.mainOuter === 'auto') { 103 | target.flexStyle.mainOuter = target.flexStyle.mainOffset; 104 | } 105 | 106 | if (target.flexStyle.crossOuter === 'auto') { 107 | target.flexStyle.crossOuter = target.flexStyle.crossOffset; 108 | } 109 | 110 | if (typeof target.flexStyle.mainBefore === 'number') { 111 | target.flexStyle.mainOuter += target.flexStyle.mainBefore; 112 | } 113 | 114 | if (typeof target.flexStyle.mainAfter === 'number') { 115 | target.flexStyle.mainOuter += target.flexStyle.mainAfter; 116 | } 117 | 118 | if (typeof target.flexStyle.crossBefore === 'number') { 119 | target.flexStyle.crossOuter += target.flexStyle.crossBefore; 120 | } 121 | 122 | if (typeof target.flexStyle.crossAfter === 'number') { 123 | target.flexStyle.crossOuter += target.flexStyle.crossAfter; 124 | } 125 | }; 126 | -------------------------------------------------------------------------------- /lib/flexbox/flex-grow/README.md: -------------------------------------------------------------------------------- 1 | # flex-grow 2 | 3 | The `flex-grow` methods calculates any numerical increase to lengths of flex items along the main axis. 4 | 5 | ```js 6 | flexGrow( line ) 7 | ``` 8 | 9 | ### Specification 10 | 11 | > https://drafts.csswg.org/css-flexbox-1/#propdef-flex-grow 12 | 13 | 1. If `line.main-space` is greater than `0`. 14 | 1. Let `grow-factor` be all the `child.flex-grow` in `line.children`. 15 | - If `grow-factor` is greater than `0`. 16 | 1. For each `child` in `line.children`; 17 | 1. Let `child.main-around` be itself and; 18 | `child.flex-grow` divided by `grow-factor` multiplied by `line.main-space`. 19 | - Let `line.main` be all the `child.main-around` in `line.children`. 20 | - Let `line.main-space` be `0`. 21 | 22 | [Implementation](index.js) [Tests](test.js) 23 | -------------------------------------------------------------------------------- /lib/flexbox/flex-grow/index.js: -------------------------------------------------------------------------------- 1 | var reduce = require('../reduce'); 2 | 3 | module.exports = function flexGrow(line) { 4 | if (line.mainSpace > 0) { 5 | var growFactor = reduce(line.children, function (lastGrowFactor, child) { 6 | return lastGrowFactor + parseFloat(child.style.flexGrow); 7 | }, 0); 8 | 9 | if (growFactor > 0) { 10 | line.main = reduce(line.children, function (main, child) { 11 | if (child.flexStyle.main === 'auto') { 12 | child.flexStyle.main = child.flexStyle.mainOffset + parseFloat(child.style.flexGrow) / growFactor * line.mainSpace; 13 | } else { 14 | child.flexStyle.main += parseFloat(child.style.flexGrow) / growFactor * line.mainSpace; 15 | } 16 | 17 | child.flexStyle.mainOuter = child.flexStyle.main + child.flexStyle.mainBefore + child.flexStyle.mainAfter; 18 | 19 | return main + child.flexStyle.mainOuter; 20 | }, 0); 21 | 22 | line.mainSpace = 0; 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /lib/flexbox/flex-shrink/README.md: -------------------------------------------------------------------------------- 1 | # `flex-shrink( line )` 2 | 3 | The `flex-shrink` methods calculates any numerical decrease to lengths of flex items along the main axis. 4 | 5 | ```js 6 | flexGrow( line ) 7 | ``` 8 | 9 | ### Specification 10 | 11 | > https://drafts.csswg.org/css-flexbox-1/#propdef-flex-shrink 12 | 13 | 1. If `line.main-space` is less than `0`. 14 | 1. Let `shrink-factor` be all the `child.flex-shrink` in `line.children`. 15 | - If `shrink-factor` is greater than `0`. 16 | 1. For each `child` in `line.children`; 17 | 1. Let `child.main-around` be itself and; 18 | `child.flex-shrink` divided by `shrink-factor` multiplied by `line.main-space`. 19 | - Let `line.main` be all the `child.main-around` in `line.children`. 20 | - Let `line.main-space` be `0`. 21 | 22 | [Implementation](index.js) [Tests](test.js) 23 | -------------------------------------------------------------------------------- /lib/flexbox/flex-shrink/index.js: -------------------------------------------------------------------------------- 1 | var reduce = require('../reduce'); 2 | 3 | module.exports = function flexShrink(line) { 4 | if (line.mainSpace < 0) { 5 | var shrinkFactor = reduce(line.children, function (lastShrinkFactor, child) { 6 | return lastShrinkFactor + parseFloat(child.style.flexShrink); 7 | }, 0); 8 | 9 | if (shrinkFactor > 0) { 10 | line.main = reduce(line.children, function (main, child) { 11 | child.flexStyle.main += parseFloat(child.style.flexShrink) / shrinkFactor * line.mainSpace; 12 | 13 | child.flexStyle.mainOuter = child.flexStyle.main + child.flexStyle.mainBefore + child.flexStyle.mainAfter; 14 | 15 | return main + child.flexStyle.mainOuter; 16 | }, 0); 17 | 18 | line.mainSpace = 0; 19 | } 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /lib/flexbox/flexbox-lines/README.md: -------------------------------------------------------------------------------- 1 | # flexbox-lines 2 | 3 | The `flexbox-lines` method calculates the lengths of lines in a flex container. 4 | 5 | ```js 6 | flexboxLines( target ) 7 | ``` 8 | 9 | ### Specification 10 | 11 | > https://drafts.csswg.org/css-flexbox-1/ 12 | 13 | 1. Perform `flex-direction( target, target.flex-direction, target.align-items )`. 14 | - Perform `order( target )`. 15 | - Let `target.lines` be an `Array`. 16 | - Let `line` be an `Object` in `target.lines` containing; `line.main` as `0`, `line.cross` as `0`, and `line-children` as an `Array`. 17 | - For each `child` in `target.children`; 18 | 1. If `target.flex-wrap` is `"no-wrap"`, or; 19 | if `line.children` has a length of `0`, or; 20 | if `target.main-around` is greater than or equal to `line.main` and `child.main-around`; 21 | 1. Let `line.main` be itself and `child.main-around`. 22 | - Let `line.cross` be the `Math.max` of itself or `child.cross-around`. 23 | - Otherwise; 24 | 1. Let `line` be an `Object` in `target.lines` containing; `line.main` as `child.main-around`, `line.cross` as `child.cross-around`, and `line-children` as an `Array`. 25 | - Let `child` be a child of `line.children`. 26 | 27 | [Implementation](index.js) [Tests](test.js) 28 | -------------------------------------------------------------------------------- /lib/flexbox/flexbox-lines/index.js: -------------------------------------------------------------------------------- 1 | var reduce = require('../reduce'); 2 | 3 | module.exports = function flexboxLines(details) { 4 | var line; 5 | 6 | details.lines = [line = { 7 | main: 0, 8 | cross: 0, 9 | children: [] 10 | }]; 11 | 12 | var index = -1; 13 | var child; 14 | 15 | while (child = details.children[++index]) { 16 | if ( 17 | details.style.flexWrap === 'nowrap' || 18 | line.children.length === 0 || 19 | details.flexStyle.main === 'auto' || 20 | details.flexStyle.main - details.flexStyle.mainInnerBefore - details.flexStyle.mainInnerAfter - details.flexStyle.mainBorderBefore - details.flexStyle.mainBorderAfter >= line.main + child.flexStyle.mainOuter 21 | ) { 22 | line.main += child.flexStyle.mainOuter; 23 | line.cross = Math.max(line.cross, child.flexStyle.crossOuter); 24 | } else { 25 | details.lines.push(line = { 26 | main: child.flexStyle.mainOuter, 27 | cross: child.flexStyle.crossOuter, 28 | children: [] 29 | }); 30 | } 31 | 32 | line.children.push(child); 33 | } 34 | 35 | details.flexStyle.mainLines = reduce(details.lines, function (mainLines, item) { 36 | return Math.max(mainLines, item.main); 37 | }, 0); 38 | 39 | details.flexStyle.crossLines = reduce(details.lines, function (crossLines, item) { 40 | return crossLines + item.cross; 41 | }, 0); 42 | 43 | if (details.flexStyle.main === 'auto') { 44 | details.flexStyle.main = Math.max(details.flexStyle.mainOffset, details.flexStyle.mainLines + details.flexStyle.mainInnerBefore + details.flexStyle.mainInnerAfter + details.flexStyle.mainBorderBefore + details.flexStyle.mainBorderAfter); 45 | } 46 | 47 | if (details.flexStyle.cross === 'auto') { 48 | details.flexStyle.cross = Math.max(details.flexStyle.crossOffset, details.flexStyle.crossLines + details.flexStyle.crossInnerBefore + details.flexStyle.crossInnerAfter + details.flexStyle.crossBorderBefore + details.flexStyle.crossBorderAfter); 49 | } 50 | 51 | details.flexStyle.crossSpace = details.flexStyle.cross - details.flexStyle.crossInnerBefore - details.flexStyle.crossInnerAfter - details.flexStyle.crossBorderBefore - details.flexStyle.crossBorderAfter - details.flexStyle.crossLines; 52 | 53 | details.flexStyle.mainOuter = details.flexStyle.main + details.flexStyle.mainBefore + details.flexStyle.mainAfter; 54 | details.flexStyle.crossOuter = details.flexStyle.cross + details.flexStyle.crossBefore + details.flexStyle.crossAfter; 55 | }; 56 | -------------------------------------------------------------------------------- /lib/flexbox/index.js: -------------------------------------------------------------------------------- 1 | module.exports = flexbox; 2 | 3 | function flexbox(details) { 4 | var index = -1; 5 | var child; 6 | 7 | // for each flex child 8 | while (child = details.children[++index]) { 9 | // process child styles as metrics 10 | require('./flex-direction')(child, details.style.flexDirection); 11 | } 12 | 13 | // process target styles as metrics 14 | require('./flex-direction')(details, details.style.flexDirection); 15 | 16 | // process ordering of items 17 | require('./order')(details); 18 | 19 | // process flexbox items into lines 20 | require('./flexbox-lines')(details); 21 | 22 | // process align-content item metrics 23 | require('./align-content')(details); 24 | 25 | index = -1; 26 | var line; 27 | 28 | // for each line of items in the target 29 | while (line = details.lines[++index]) { 30 | line.mainSpace = details.flexStyle.main - details.flexStyle.mainInnerBefore - details.flexStyle.mainInnerAfter - details.flexStyle.mainBorderBefore - details.flexStyle.mainBorderAfter - line.main; 31 | 32 | // process flex-grow item metrics 33 | require('./flex-grow')(line); 34 | 35 | // process flex-shrink item metrics 36 | require('./flex-shrink')(line); 37 | 38 | // process margin item metrics 39 | require('./margin-main')(line); 40 | require('./margin-cross')(line); 41 | 42 | // process justify-content item metrics 43 | require('./justify-content')(line, details.style.justifyContent, details); 44 | } 45 | 46 | // process align-items metrics 47 | require('./align-items')(details); 48 | } 49 | -------------------------------------------------------------------------------- /lib/flexbox/justify-content/README.md: -------------------------------------------------------------------------------- 1 | # justify-content 2 | 3 | The `justify-content` method calculates the position of flex items in a line along the main axis. 4 | 5 | ```js 6 | justifyContent( line, target.justifyContent ) 7 | ``` 8 | 9 | ### Specification 10 | 11 | > https://drafts.csswg.org/css-flexbox-1/#propdef-justify-content 12 | 13 | 1. If `justify-content` is `"flex-start"`; 14 | 1. Let `start` be `0`. 15 | - For each `child` in `line.children`; 16 | 1. Let `child.main-start` be `start`. 17 | - Let `start` be itself and `child.main-around`. 18 | - Otherwise, if `justify-content` is `"flex-end"`; 19 | 1. Let `start` be `line.main-space`. 20 | - For each `child` in `line.children`; 21 | 1. Let `child.main-start` be `start`. 22 | - Let `start` be itself and `child.main-around`. 23 | - Otherwise, if `justify-content` is `"center"`; 24 | 1. Let `start` be `line.main-space` divided by `2`. 25 | - For each `child` in `line.children`; 26 | 1. Let `child.main-start` be `start`. 27 | - Let `start` be itself and `child.main-around`. 28 | - Otherwise, if `justify-content` is `"space-between"`; 29 | 1. Let `factor` be `line.main-space` divided by; the length of `line.children` sans `1`. 30 | - Let `start` be `0`. 31 | - For each `child` in `line.children`; 32 | 1. Let `child.main-start` be `start`. 33 | - Let `start` be itself and `child.main-around` and `factor`. 34 | - Otherwise, if `justify-content` is `"space-around"`; 35 | 1. Let `factor` be `line.main-space` multiplied by `2` divided by; the length of `line.children` multiplied by `2`. 36 | - Let `start` be `factor` divided by `2`. 37 | - For each `child` in `line.children`; 38 | 1. Let `child.main-start` be `start`. 39 | - Let `start` be itself and `child.main-around` and `factor`. 40 | 41 | [Implementation](index.js) [Tests](test.js) 42 | -------------------------------------------------------------------------------- /lib/flexbox/justify-content/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function justifyContent(line, targetJustifyContent, details) { 2 | var start; 3 | var factor; 4 | 5 | var inset = details.flexStyle.mainInnerBefore; 6 | 7 | var index = -1; 8 | var child; 9 | 10 | if (targetJustifyContent === 'flex-end') { 11 | start = line.mainSpace; 12 | 13 | start += inset; 14 | 15 | while (child = line.children[++index]) { 16 | child.flexStyle.mainStart = start; 17 | 18 | start += child.flexStyle.mainOuter; 19 | } 20 | } else if (targetJustifyContent === 'center') { 21 | start = line.mainSpace / 2; 22 | 23 | start += inset; 24 | 25 | while (child = line.children[++index]) { 26 | child.flexStyle.mainStart = start; 27 | 28 | start += child.flexStyle.mainOuter; 29 | } 30 | } else if (targetJustifyContent === 'space-between') { 31 | factor = line.mainSpace / (line.children.length - 1); 32 | 33 | start = 0; 34 | 35 | start += inset; 36 | 37 | while (child = line.children[++index]) { 38 | child.flexStyle.mainStart = start; 39 | 40 | start += child.flexStyle.mainOuter + factor; 41 | } 42 | } else if (targetJustifyContent === 'space-around') { 43 | factor = line.mainSpace * 2 / (line.children.length * 2); 44 | start = factor / 2; 45 | 46 | start += inset; 47 | 48 | while (child = line.children[++index]) { 49 | child.flexStyle.mainStart = start; 50 | 51 | start += child.flexStyle.mainOuter + factor; 52 | } 53 | } else { 54 | start = 0; 55 | 56 | start += inset; 57 | 58 | while (child = line.children[++index]) { 59 | child.flexStyle.mainStart = start; 60 | 61 | start += child.flexStyle.mainOuter; 62 | } 63 | } 64 | }; 65 | -------------------------------------------------------------------------------- /lib/flexbox/margin-cross/README.md: -------------------------------------------------------------------------------- 1 | # margin-cross 2 | 3 | The `margin-cross` method calculates the numerical length of flex item margins set to `"auto"` along the cross axis. 4 | 5 | ```js 6 | marginCross( line ) 7 | ``` 8 | 9 | ### Specification 10 | 11 | 1. Let `count` be `0`. 12 | - For each `child` in `line.children`; 13 | 1. If `child.cross-before` is `auto`; 14 | 1. Increment `count` by `1`. 15 | - If `child.cross-after` is `auto`; 16 | 1. Increment `count` by `1`. 17 | 1. If `count` is greater than `0`; 18 | 1. For each `child` in `line.children`; 19 | 1. If `child.cross-before` is `auto`; 20 | 1. Let `child.cross-before` be the `line.cross-space` divided by `count`. 21 | 1. Let `child.cross-around` be itself and `child.cross-before`. 22 | - If `child.cross-after` is `auto`; 23 | 1. Let `child.cross-after` be the `line.cross-space` divided by `count`. 24 | 1. Let `child.cross-around` be itself and `child.cross-after`. 25 | - Let `line.cross-space` be `0`. 26 | 27 | [Implementation](index.js) [Tests](test.js) 28 | -------------------------------------------------------------------------------- /lib/flexbox/margin-cross/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function marginCross(line) { 2 | var index = -1; 3 | var child; 4 | 5 | while (child = line.children[++index]) { 6 | var count = 0; 7 | 8 | if (child.flexStyle.crossBefore === 'auto') { 9 | ++count; 10 | } 11 | 12 | if (child.flexStyle.crossAfter === 'auto') { 13 | ++count; 14 | } 15 | 16 | var childSpace = line.cross - child.flexStyle.crossOuter; 17 | 18 | if (child.flexStyle.crossBefore === 'auto') { 19 | child.flexStyle.crossBefore = childSpace / count; 20 | } 21 | 22 | if (child.flexStyle.crossAfter === 'auto') { 23 | child.flexStyle.crossAfter = childSpace / count; 24 | } 25 | 26 | if (child.flexStyle.cross === 'auto') { 27 | child.flexStyle.crossOuter = child.flexStyle.crossOffset + child.flexStyle.crossBefore + child.flexStyle.crossAfter; 28 | } else { 29 | child.flexStyle.crossOuter = child.flexStyle.cross + child.flexStyle.crossBefore + child.flexStyle.crossAfter; 30 | } 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /lib/flexbox/margin-main/README.md: -------------------------------------------------------------------------------- 1 | # margin-main 2 | 3 | The `margin-main` method calculates the numerical length of flex item margins set to `"auto"` along the main axis. 4 | 5 | ```js 6 | marginCross( line ) 7 | ``` 8 | 9 | ### Specification 10 | 11 | 1. Let `count` be `0`. 12 | - For each `child` in `line.children`; 13 | 1. If `child.main-before` is `auto`; 14 | 1. Increment `count` by `1`. 15 | - If `child.main-after` is `auto`; 16 | 1. Increment `count` by `1`. 17 | 1. If `count` is greater than `0`; 18 | 1. For each `child` in `line.children`; 19 | 1. If `child.main-before` is `auto`; 20 | 1. Let `child.main-before` be the `line.main-space` divided by `count`. 21 | 1. Let `child.main-around` be itself and `child.main-before`. 22 | + If `child.main-after` is `auto`; 23 | 1. Let `child.main-after` be the `line.main-space` divided by `count`. 24 | 1. Let `child.main-around` be itself and `child.main-after`. 25 | + Let `line.main-space` be `0`. 26 | 27 | [Implementation](index.js) [Tests](test.js) 28 | -------------------------------------------------------------------------------- /lib/flexbox/margin-main/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function marginMain(line) { 2 | var count = 0; 3 | 4 | var index = -1; 5 | var child; 6 | 7 | while (child = line.children[++index]) { 8 | if (child.flexStyle.mainBefore === 'auto') { 9 | ++count; 10 | } 11 | 12 | if (child.flexStyle.mainAfter === 'auto') { 13 | ++count; 14 | } 15 | } 16 | 17 | if (count > 0) { 18 | index = -1; 19 | 20 | while (child = line.children[++index]) { 21 | if (child.flexStyle.mainBefore === 'auto') { 22 | child.flexStyle.mainBefore = line.mainSpace / count; 23 | } 24 | 25 | if (child.flexStyle.mainAfter === 'auto') { 26 | child.flexStyle.mainAfter = line.mainSpace / count; 27 | } 28 | 29 | if (child.flexStyle.main === 'auto') { 30 | child.flexStyle.mainOuter = child.flexStyle.mainOffset + child.flexStyle.mainBefore + child.flexStyle.mainAfter; 31 | } else { 32 | child.flexStyle.mainOuter = child.flexStyle.main + child.flexStyle.mainBefore + child.flexStyle.mainAfter; 33 | } 34 | } 35 | 36 | line.mainSpace = 0; 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /lib/flexbox/order/README.md: -------------------------------------------------------------------------------- 1 | # order 2 | 3 | The `order` methods sorts the flex items based on their flex order. 4 | 5 | ```js 6 | order( target ) 7 | ``` 8 | 9 | ### Specification 10 | 11 | > https://drafts.csswg.org/css-flexbox-1/#propdef-justify-content 12 | 13 | 1. Sort each `child` in `target.children`; 14 | 1. Return `child-a.order` sans `child-b.order`, or, if it is `0`; 15 | return `child-a.index` sans `child-b.index`. 16 | -------------------------------------------------------------------------------- /lib/flexbox/order/index.js: -------------------------------------------------------------------------------- 1 | var flexDirectionReverseMatch = /^(column|row)-reverse$/; 2 | 3 | module.exports = function order(target) { 4 | target.children.sort(function (childA, childB) { 5 | return childA.style.order - childB.style.order || childA.index - childB.index; 6 | }); 7 | 8 | if (flexDirectionReverseMatch.test(target.style.flexDirection)) { 9 | target.children.reverse(); 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /lib/flexbox/reduce/index.js: -------------------------------------------------------------------------------- 1 | module.exports = reduce; 2 | 3 | function reduce(arraylike, fn, previousValue) { 4 | var length = arraylike.length; 5 | var index = -1; 6 | var returnValue = previousValue 7 | 8 | while (++index < length) { 9 | if (index in arraylike) { 10 | returnValue = fn(returnValue, arraylike[index], index); 11 | } 12 | } 13 | 14 | return returnValue; 15 | } 16 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | /*! Flexibility 2.0.0 | MIT Licensed | github.com/jonathantneal/flexibility */ 2 | 3 | var read = require('./read'); 4 | var write = require('./write'); 5 | 6 | var readAll = require('./readAll'); 7 | var writeAll = require('./writeAll'); 8 | 9 | module.exports = flexibility; 10 | 11 | module.exports.read = read; 12 | module.exports.write = write; 13 | 14 | module.exports.readAll = readAll; 15 | module.exports.writeAll = writeAll; 16 | 17 | function flexibility(target) { 18 | writeAll(readAll(target)); 19 | } 20 | -------------------------------------------------------------------------------- /lib/read/README.md: -------------------------------------------------------------------------------- 1 | # flexibility.read 2 | 3 | The **read()** method returns the Flexbox related details of an element. 4 | 5 | ### Syntax 6 | 7 | ```js 8 | var detailsObject = flexibility.read( element ); 9 | ``` 10 | 11 | ### Example Response 12 | 13 | ```js 14 | { 15 | "element": Element, 16 | "style": { 17 | "alignContent": "stretch" 18 | "alignItems": "stretch" 19 | "alignSelf": "auto" 20 | "display": "inline" 21 | "flexBasis": "auto" 22 | "flexDirection": "row" 23 | "flexGrow": "0" 24 | "flexShrink": "1" 25 | "flexWrap": "nowrap" 26 | "justifyContent": "flex-start", 27 | "height": "auto" 28 | "marginTop": "0" 29 | "marginRight": "0" 30 | "marginLeft": "0" 31 | "marginBottom": "0" 32 | "maxHeight": "none" 33 | "maxWidth": "none" 34 | "minHeight": "0" 35 | "minWidth": "0" 36 | "order": "0" 37 | "position": "static" 38 | "width": "auto" 39 | } 40 | } 41 | ``` 42 | 43 | [Implementation](index.js) 44 | -------------------------------------------------------------------------------- /lib/read/getComputedLength.js: -------------------------------------------------------------------------------- 1 | module.exports = getComputedLength; 2 | 3 | var lengthMatch = /^([-+]?\d*\.?\d+)(%|[a-z]+)$/; 4 | 5 | var testElement = document.createElement('div'); 6 | 7 | var borderWidths = { 8 | medium: 4, 9 | none: 0, 10 | thick: 6, 11 | thin: 2 12 | }; 13 | 14 | var borderWidthPropMatch = /^border(Bottom|Left|Right|Top)Width$/; 15 | 16 | function getComputedLength(style, prop, element) { 17 | var value = style[prop]; 18 | var match = String(value).match(lengthMatch); 19 | 20 | if (!match) { 21 | var borderWidthProp = prop.match(borderWidthPropMatch); 22 | 23 | if (borderWidthProp) { 24 | var borderStyleProp = style['border' + borderWidthProp[1] + 'Style']; 25 | 26 | if (borderStyleProp === 'none') { 27 | return 0; 28 | } else { 29 | return borderWidths[value] || 0; 30 | } 31 | } 32 | 33 | return value; 34 | } 35 | 36 | var size = match[1]; 37 | var unit = match[2]; 38 | 39 | // for percent, calculate property based on parent's computed size 40 | if(unit === '%') { 41 | var parentComputedStyle = window.getComputedStyle && getComputedStyle(element) || {}; 42 | var d = parentComputedStyle[prop]; 43 | 44 | if(d !== undefined) { 45 | d = parseInt(d, 10); 46 | var pct = size / 100; 47 | return Math.round(d * pct); 48 | } 49 | } 50 | 51 | return unit === 'px' ? Number(size) : 52 | unit === 'cm' ? size * 0.3937 * 96 : 53 | unit === 'in' ? size * 96 : 54 | unit === 'mm' ? size * 0.3937 * 96 / 10 : 55 | unit === 'pc' ? size * 12 * 96 / 72 : 56 | unit === 'pt' ? size * 96 / 72 : 57 | unit === 'rem' ? size * 16 : 58 | getComputedValue(value, element); 59 | } 60 | 61 | function getComputedValue(value, element) { 62 | testElement.style.cssText = 'border:none!important;clip:rect(0 0 0 0)!important;display:block!important;font-size:1em!important;height:0!important;margin:0!important;padding:0!important;position:relative!important;width:' + value + '!important'; 63 | 64 | element.parentNode.insertBefore(testElement, element.nextSibling); 65 | 66 | var fontSize = testElement.offsetWidth; 67 | 68 | element.parentNode.removeChild(testElement); 69 | 70 | return fontSize; 71 | } 72 | -------------------------------------------------------------------------------- /lib/read/index.js: -------------------------------------------------------------------------------- 1 | module.exports = read; 2 | 3 | var declMatch = /([^\s:;]+)\s*:\s*([^;]+?)\s*(;|$)/g; 4 | var ignoredPropsMatch = /^(alignSelf|height|width)$/; 5 | // var pxValueMatch = /^(0|\d*\.?\d+px)$/; 6 | 7 | var getComputedLength = require('./getComputedLength'); 8 | 9 | // Return flexbox related details of an element 10 | function read(element) { 11 | // normalized style 12 | var style = { 13 | alignContent: 'stretch', 14 | alignItems: 'stretch', 15 | alignSelf: 'auto', 16 | borderBottomStyle: 'none', 17 | borderBottomWidth: 0, 18 | borderLeftStyle: 'none', 19 | borderLeftWidth: 0, 20 | borderRightStyle: 'none', 21 | borderRightWidth: 0, 22 | borderTopStyle: 'none', 23 | borderTopWidth: 0, 24 | boxSizing: 'content-box', 25 | display: 'inline', 26 | flexBasis: 'auto', 27 | flexDirection: 'row', 28 | flexGrow: 0, 29 | flexShrink: 1, 30 | flexWrap: 'nowrap', 31 | justifyContent: 'flex-start', 32 | height: 'auto', 33 | marginTop: 0, 34 | marginRight: 0, 35 | marginLeft: 0, 36 | marginBottom: 0, 37 | paddingTop: 0, 38 | paddingRight: 0, 39 | paddingLeft: 0, 40 | paddingBottom: 0, 41 | maxHeight: 'none', 42 | maxWidth: 'none', 43 | minHeight: 0, 44 | minWidth: 0, 45 | order: 0, 46 | position: 'static', 47 | width: 'auto' 48 | }; 49 | 50 | // whether element is an element 51 | var isElement = element instanceof Element; 52 | 53 | if (isElement) { 54 | // whether element has data-style attribute 55 | var hasDataStyleAttr = element.hasAttribute('data-style'); 56 | 57 | // inline style from data-style or style 58 | var inlineStyle = hasDataStyleAttr ? element.getAttribute('data-style') : element.getAttribute('style') || ''; 59 | 60 | if (!hasDataStyleAttr) { 61 | // copy style to data-style 62 | element.setAttribute('data-style', inlineStyle); 63 | } 64 | 65 | // append computed style to style 66 | var computedStyle = window.getComputedStyle && getComputedStyle(element) || {}; 67 | 68 | appendComputedStyle(style, computedStyle); 69 | 70 | // append current style to style 71 | var currentStyle = element.currentStyle || {}; 72 | 73 | appendCurrentStyle(style, currentStyle); 74 | 75 | // append inline style to style 76 | appendInlineStyle(style, inlineStyle); 77 | 78 | // for each camel-case property 79 | for (var prop in style) { 80 | style[prop] = getComputedLength(style, prop, element); 81 | } 82 | 83 | // offset measurements 84 | var boundingClientRect = element.getBoundingClientRect(); 85 | 86 | style.offsetHeight = boundingClientRect.height || element.offsetHeight; 87 | style.offsetWidth = boundingClientRect.width || element.offsetWidth; 88 | } 89 | 90 | var details = { 91 | element: element, 92 | style: style 93 | }; 94 | 95 | return details; 96 | } 97 | 98 | function appendCurrentStyle(style, currentStyle) { 99 | // for each camel-case property 100 | for (var prop in style) { 101 | // whether property is in current style 102 | var hasProp = prop in currentStyle; 103 | 104 | if (hasProp) { 105 | style[prop] = currentStyle[prop]; 106 | } else { 107 | // kebab property 108 | var kebabName = prop.replace(/[A-Z]/g, '-$&').toLowerCase(); 109 | 110 | // whether kebab property is in current style 111 | var hasKebabName = kebabName in currentStyle; 112 | 113 | if (hasKebabName) { 114 | style[prop] = currentStyle[kebabName]; 115 | } 116 | } 117 | } 118 | 119 | // whether -js-display property exists 120 | var hasJsDisplay = '-js-display' in currentStyle; 121 | 122 | if (hasJsDisplay) { 123 | style.display = currentStyle['-js-display']; 124 | } 125 | } 126 | 127 | function appendInlineStyle(style, inlineStyle) { 128 | var decl; 129 | 130 | // for each declaration 131 | while (decl = declMatch.exec(inlineStyle)) { 132 | // camel-case property 133 | var prop = decl[1].toLowerCase().replace(/-[a-z]/g, function (match) { 134 | return match.slice(1).toUpperCase(); 135 | }); 136 | 137 | style[prop] = decl[2]; 138 | } 139 | } 140 | 141 | function appendComputedStyle(style, computedStyle) { 142 | // for each camel-case property 143 | for (var prop in style) { 144 | // whether kebab property is in current style 145 | var hasProp = prop in computedStyle; 146 | 147 | if (hasProp && !ignoredPropsMatch.test(prop)) { 148 | style[prop] = computedStyle[prop]; 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /lib/readAll/README.md: -------------------------------------------------------------------------------- 1 | # flexibility.readAll 2 | 3 | The **readAll()** method returns an unordered list of flexbox related details as discovered on an element or any of its descendants. 4 | 5 | ### Syntax 6 | 7 | ```js 8 | var detailsList = flexibility.readAll( element ); 9 | ``` 10 | 11 | ### Default Response 12 | 13 | ```js 14 | [ 15 | { 16 | "element": element, 17 | "style": { 18 | "alignContent": "stretch" 19 | "alignItems": "stretch" 20 | "alignSelf": "auto" 21 | "display": "inline" 22 | "flexBasis": "auto" 23 | "flexDirection": "row" 24 | "flexGrow": 0 25 | "flexShrink": 1 26 | "flexWrap": "nowrap" 27 | "justifyContent": "flex-start", 28 | "height": "auto" 29 | "marginTop": 0 30 | "marginRight": 0 31 | "marginLeft": 0 32 | "marginBottom": 0 33 | "maxHeight": "none" 34 | "maxWidth": "none" 35 | "minHeight": 0 36 | "minWidth": 0 37 | "order": 0 38 | "position": "static" 39 | "width": "auto" 40 | }, 41 | "children": [ 42 | ... 43 | ] 44 | }, 45 | ... 46 | ] 47 | ``` 48 | 49 | [Implementation](index.js) 50 | -------------------------------------------------------------------------------- /lib/readAll/index.js: -------------------------------------------------------------------------------- 1 | module.exports = readAll; 2 | 3 | var read = require('../read'); 4 | var displayFlexMatch = /(^|;)\s*display\s*:\s*(inline-)?flex\s*(;|$)/i; 5 | var flexMatch = /^(inline-)?flex$/i; 6 | 7 | // Return a list of flexbox details from a matching element or its descendants 8 | function readAll(element) { 9 | // create details list 10 | var detailsList = []; 11 | 12 | // process display flex details 13 | readElementAndTree(element, detailsList); 14 | 15 | return detailsList; 16 | } 17 | 18 | function readElementAndTree(element, detailsList) { 19 | // whether the element has a display flex style 20 | var isDisplayFlex = isElementDisplayFlexCheck(element); 21 | 22 | // children of the element 23 | var children = []; 24 | 25 | var index = -1; 26 | var childNode; 27 | 28 | // for each child node of the element 29 | while (childNode = element.childNodes[++index]) { 30 | // whether the child is non-empty text 31 | var isNonEmptyText = childNode.nodeType === 3 && !/^\s*$/.test(childNode.nodeValue); 32 | 33 | if (isDisplayFlex && isNonEmptyText) { 34 | // replace the text with an element containing the text 35 | var oldNode = childNode; 36 | 37 | childNode = element.insertBefore(document.createElement('flex-item'), oldNode); 38 | 39 | childNode.appendChild(oldNode); 40 | } 41 | 42 | // whether the child is an element 43 | var isElement = childNode instanceof Element; 44 | 45 | if (isElement) { 46 | // get the flex details of the child 47 | var childDetails = readElementAndTree(childNode, detailsList); 48 | 49 | if (isDisplayFlex) { 50 | var runtimeStyle = childNode.style; 51 | 52 | // remove from layout 53 | runtimeStyle.display = 'inline-block'; 54 | runtimeStyle.position = 'absolute'; 55 | 56 | // get the current flex related styles 57 | childDetails.style = read(childNode).style; 58 | 59 | // push the child details to children 60 | children.push(childDetails); 61 | } 62 | } 63 | } 64 | 65 | // combined flex details of the element 66 | var details = { 67 | element: element, 68 | children: children 69 | }; 70 | 71 | if (isDisplayFlex) { 72 | // get the current flex related styles 73 | details.style = read(element).style; 74 | 75 | // push the flex details of the element to detailsList 76 | detailsList.push(details); 77 | } 78 | 79 | return details; 80 | } 81 | 82 | function isElementDisplayFlexCheck(element) { 83 | // whether the element is an element 84 | var isElement = element instanceof Element; 85 | 86 | // whether the element has a data flex attribute 87 | var dataFlexStyle = isElement && element.getAttribute('data-style'); 88 | 89 | // whether the element has a current style and -js-display declaration 90 | var currentStyleJsDisplay = isElement && element.currentStyle && element.currentStyle['-js-display']; 91 | 92 | // whether flex is detected by the data flex attribute or the current style 93 | var isElementDisplayFlex = displayFlexMatch.test(dataFlexStyle) || flexMatch.test(currentStyleJsDisplay); 94 | 95 | return isElementDisplayFlex; 96 | } 97 | -------------------------------------------------------------------------------- /lib/write/README.md: -------------------------------------------------------------------------------- 1 | # flexibility.write 2 | 3 | The **write()** method writes flexbox details back to their respective element and children. 4 | 5 | ### Syntax 6 | 7 | ```js 8 | flexibility.write( details ); 9 | ``` 10 | 11 | [Implementation](index.js) 12 | -------------------------------------------------------------------------------- /lib/write/index.js: -------------------------------------------------------------------------------- 1 | module.exports = write; 2 | 3 | var translate = require('../flexbox'); 4 | 5 | // write( details ): Writes flexbox details back to their respective elements. 6 | function write(details) { 7 | translate(details); 8 | 9 | var runtimeStyle = details.element.style; 10 | 11 | var angle = details.mainAxis === 'inline' ? ['main', 'cross'] : ['cross', 'main']; 12 | 13 | runtimeStyle.boxSizing = 'content-box'; 14 | runtimeStyle.display = 'block'; 15 | runtimeStyle.position = 'relative'; 16 | 17 | runtimeStyle.width = normalize(details.flexStyle[angle[0]] - details.flexStyle[angle[0] + 'InnerBefore'] - details.flexStyle[angle[0] + 'InnerAfter'] - details.flexStyle[angle[0] + 'BorderBefore'] - details.flexStyle[angle[0] + 'BorderAfter']); 18 | runtimeStyle.height = normalize(details.flexStyle[angle[1]] - details.flexStyle[angle[1] + 'InnerBefore'] - details.flexStyle[angle[1] + 'InnerAfter'] - details.flexStyle[angle[1] + 'BorderBefore'] - details.flexStyle[angle[1] + 'BorderAfter']); 19 | 20 | var index = -1; 21 | var child; 22 | 23 | while (child = details.children[++index]) { 24 | var childRuntimeStyle = child.element.style; 25 | 26 | var childAngle = child.mainAxis === 'inline' ? ['main', 'cross'] : ['cross', 'main']; 27 | 28 | childRuntimeStyle.boxSizing = 'content-box'; 29 | childRuntimeStyle.display = 'block'; 30 | childRuntimeStyle.position = 'absolute'; 31 | 32 | if (child.flexStyle[childAngle[0]] !== 'auto') { 33 | childRuntimeStyle.width = normalize(child.flexStyle[childAngle[0]] - child.flexStyle[childAngle[0] + 'InnerBefore'] - child.flexStyle[childAngle[0] + 'InnerAfter'] - child.flexStyle[childAngle[0] + 'BorderBefore'] - child.flexStyle[childAngle[0] + 'BorderAfter']); 34 | } 35 | 36 | if (child.flexStyle[childAngle[1]] !== 'auto') { 37 | childRuntimeStyle.height = normalize(child.flexStyle[childAngle[1]] - child.flexStyle[childAngle[1] + 'InnerBefore'] - child.flexStyle[childAngle[1] + 'InnerAfter'] - child.flexStyle[childAngle[1] + 'BorderBefore'] - child.flexStyle[childAngle[1] + 'BorderAfter']); 38 | } 39 | 40 | childRuntimeStyle.top = normalize(child.flexStyle[childAngle[1] + 'Start']); 41 | childRuntimeStyle.left = normalize(child.flexStyle[childAngle[0] + 'Start']); 42 | 43 | childRuntimeStyle.marginTop = normalize(child.flexStyle[childAngle[1] + 'Before']); 44 | childRuntimeStyle.marginRight = normalize(child.flexStyle[childAngle[0] + 'After']); 45 | childRuntimeStyle.marginBottom = normalize(child.flexStyle[childAngle[1] + 'After']); 46 | childRuntimeStyle.marginLeft = normalize(child.flexStyle[childAngle[0] + 'Before']); 47 | } 48 | } 49 | 50 | function normalize(value) { 51 | return isNaN(value) 52 | ? '0px' 53 | : typeof value === 'string' 54 | ? value 55 | : Math.max(value, 0) + 'px'; 56 | } 57 | -------------------------------------------------------------------------------- /lib/writeAll/README.md: -------------------------------------------------------------------------------- 1 | # flexibility.writeAll 2 | 3 | The **writeAll()** method writes a list of flexbox details back to their respective elements and children. 4 | 5 | ### Syntax 6 | 7 | ```js 8 | flexibility.writeAll( detailsList ); 9 | ``` 10 | 11 | [Implementation](index.js) 12 | -------------------------------------------------------------------------------- /lib/writeAll/index.js: -------------------------------------------------------------------------------- 1 | module.exports = writeAll; 2 | 3 | var write = require('../write'); 4 | 5 | // writeAll( detailsList ): Writes a list of flexbox details back to their respective elements. 6 | function writeAll(detailsList) { 7 | var index = -1; 8 | var details; 9 | 10 | while (details = detailsList[++index]) { 11 | write(details); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flexibility", 3 | "version": "2.0.1", 4 | "description": "A JavaScript polyfill for Flexbox", 5 | "main": "lib/index.js", 6 | "repository": "jonathantneal/flexibility", 7 | "keywords": [ 8 | "flex", 9 | "display", 10 | "direction", 11 | "wrap", 12 | "flow", 13 | "justify", 14 | "content", 15 | "align", 16 | "items", 17 | "content", 18 | "order", 19 | "grow", 20 | "shrink", 21 | "basis", 22 | "self", 23 | "auto", 24 | "start", 25 | "end", 26 | "center", 27 | "baseline", 28 | "stretch", 29 | "space", 30 | "between", 31 | "around", 32 | "polyfill", 33 | "ie", 34 | "internet", 35 | "explorer", 36 | "layout" 37 | ], 38 | "files": [ 39 | "LICENSE.md", 40 | "flexibility.js", 41 | "lib" 42 | ], 43 | "author": "Jonathan Neal (http://jonathantneal.com)", 44 | "license": "MIT", 45 | "bugs": "https://github.com/jonathantneal/flexibility/issues", 46 | "homepage": "https://github.com/jonathantneal/flexibility#readme", 47 | "watch": { 48 | "compile-w-map": { 49 | "patterns": [ 50 | "lib", 51 | "test" 52 | ], 53 | "extensions": "js", 54 | "quiet": "true" 55 | } 56 | }, 57 | "scripts": { 58 | "compile": "browserify lib/index.js --standalone flexibility --outfile flexibility.js", 59 | "compile-w-map": "browserify lib/index.js --debug --standalone flexibility --outfile flexibility.js", 60 | "compress": "uglifyjs flexibility.js --compress --mangle --output flexibility.js", 61 | "compress-w-map": "uglifyjs flexibility.js --compress --mangle --source-map flexibility.js.map --output flexibility.js", 62 | "build": "npm run compile && npm run compress", 63 | "eslint": "eslint ./lib/", 64 | "prepublish": "npm run build", 65 | "test": "npm run eslint", 66 | "watch": "npm-watch" 67 | }, 68 | "dependencies": {}, 69 | "devDependencies": { 70 | "ava": "^0.25.0", 71 | "browserify": "^16.2.2", 72 | "eslint": "^5.2.0", 73 | "eslint-config-dev": "^2.0.0", 74 | "npm-watch": "^0.3.0", 75 | "uglify-js": "^3.4.6" 76 | }, 77 | "engines": { 78 | "node": ">=0.12.0" 79 | }, 80 | "eslintConfig": { 81 | "extends": "dev" 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /test/flex-direction-column.control.html: -------------------------------------------------------------------------------- 1 | 2 | control - flex-direction: column 3 | 4 | 5 | 6 | 7 |

control - flex-direction: column

8 | 9 | -------------------------------------------------------------------------------- /test/flex-direction-column.html: -------------------------------------------------------------------------------- 1 | 2 | test - flex-direction: column 3 | 4 | 5 | 6 | 7 |

test - flex-direction: column

8 | 9 | -------------------------------------------------------------------------------- /test/flex-direction-row.control.html: -------------------------------------------------------------------------------- 1 | 2 | control - flex-direction: row 3 | 4 | 5 | 6 | 7 |

control - flex-direction: row

8 | 9 | -------------------------------------------------------------------------------- /test/flex-direction-row.html: -------------------------------------------------------------------------------- 1 | 2 | test - flex-direction: row 3 | 4 | 5 | 6 | 7 |

test - flex-direction: row

8 | 9 | -------------------------------------------------------------------------------- /test/flex-within-flex.html: -------------------------------------------------------------------------------- 1 | 2 | test - flexbox within flexbox 3 | 4 | 5 | 6 | 7 |

test - flexbox within flexbox

8 | 9 | -------------------------------------------------------------------------------- /test/negative-margin.control.html: -------------------------------------------------------------------------------- 1 | 2 | control - negative margin 3 | 4 | 5 | 6 | 7 |

control - negative margin

8 | 9 | -------------------------------------------------------------------------------- /test/negative-margin.html: -------------------------------------------------------------------------------- 1 | 2 | test - negative margin 3 | 4 | 5 | 6 | 7 |

test - negative margin

8 | 9 | -------------------------------------------------------------------------------- /test/shared/flex-direction-column.html: -------------------------------------------------------------------------------- 1 |
2 |

justify-content: space-around

3 |
4 | a1 5 | a2 6 | a3 7 |
8 |
9 | a1; height: 30px 10 | a2; height: 30px 11 | a3; height: 30px 12 |
13 |
14 | a1; flex-basis: 30px 15 | a2; flex-basis: 30px 16 | a3; flex-basis: 30px 17 |
18 |
19 | 20 |
21 |

flex-grow: 1

22 |
23 | a1 24 | a2; flex-grow: 1 25 |
26 |
27 | a1; flex-grow: 1 28 | a2; flex-grow: 1 29 |
30 |
31 | a1; flex-grow: 1 32 | a2; flex-grow: 3 33 | a3; flex-grow: 1 34 |
35 |
36 | 37 |
38 |

margin: auto

39 |
40 | a1; margin: 0 auto 41 | a2; margin: 0 auto 42 |
43 |
44 | a1; margin: 0 auto 45 | a2; margin: 0 46 |
47 |
48 | a1; margin: 0 49 | a2; margin: 0 auto 50 |
51 |
52 | a1; margin: 0 auto 53 | a2; margin: 0 auto 54 | a3; margin: 0 auto 55 |
56 |
57 | 58 |
59 |

align-items: flex-end; justify-content: flex-end

60 |
61 | a1 62 | a2 63 |
64 |
65 | 66 |
67 |

order: 1

68 |
69 | a1; order: 1 70 | a2; order: 0 71 |
72 |
73 | -------------------------------------------------------------------------------- /test/shared/flex-direction-row.html: -------------------------------------------------------------------------------- 1 |
2 |

justify-content: space-around

3 |
4 | a1 5 | a3 6 | a3 7 |
8 |
9 | a1; width: 250px 10 | a2; width: 250px 11 | a3; width: 250px 12 |
13 |
14 | a1; flex-basis: 250px 15 | a2; flex-basis: 250px 16 | a3; flex-basis: 250px 17 |
18 |
19 | a1; width: 250px 20 | a2; width: 250px 21 | a3; width: 250px 22 |
23 |
24 | a1; width: 250px 25 | a2; width: 250px 26 | a3; width: 250px 27 |
28 |
29 | width: 250px 30 | width: 250px 31 | width: 250px 32 |
33 |
34 | width: 250px; height: 30px 35 | width: 250px 36 | width: 250px 37 |
38 |
39 | 40 |
41 |

flex-grow: 1

42 |
43 | item 44 | flex-grow: 1 45 |
46 |
47 | flex-grow: 1 48 | flex-grow: 1 49 |
50 |
51 | flex-grow: 1 52 | flex-grow: 3 53 | flex-grow: 1 54 |
55 |
56 | 57 |
58 |

margin: auto

59 |
60 | margin: 0 auto 61 | margin: 0 auto 62 |
63 |
64 | margin: 0 auto 65 | margin: 0 66 |
67 |
68 | margin: 0 69 | margin: 0 auto 70 |
71 |
72 | margin: auto 73 | margin: auto 74 | margin: auto 75 | margin: auto 76 | margin: auto 77 |
78 |
79 | 80 |
81 |

align-items: flex-end; justify-content: flex-end

82 |
83 | item 84 | item 85 |
86 |
87 | 88 |
89 |

order: 1

90 |
91 | order: 1 92 | order: 0 93 |
94 |
95 | -------------------------------------------------------------------------------- /test/shared/flex-within-flex.html: -------------------------------------------------------------------------------- 1 |
2 |

display: flex;

3 |
4 |
5 | a1 6 |
7 |
8 | b1 9 | b2 10 |
11 |
12 | c1 13 | c2 14 | c3 15 |
16 |
17 |
18 | -------------------------------------------------------------------------------- /test/shared/negative-margin.html: -------------------------------------------------------------------------------- 1 |
2 |

justify-content: space-around

3 |
4 |
5 |
6 |
a1
7 |
8 |
9 |
a2
10 |
11 |
12 |
a3
13 |
14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /test/shared/script.js: -------------------------------------------------------------------------------- 1 | document.createElement('section'); 2 | 3 | function test(name) { 4 | var xhr = new XMLHttpRequest(); 5 | 6 | xhr.open('GET', 'shared/' + name + '.html?' + new Date().getTime()); 7 | 8 | xhr.onreadystatechange = function () { 9 | if (xhr.readyState === 4) { 10 | var frag = document.createDocumentFragment(); 11 | var html = frag.appendChild(document.createElement('x')); 12 | 13 | if (frag.createElement) { 14 | frag.createElement('section'); 15 | } 16 | 17 | html.innerHTML = xhr.responseText; 18 | 19 | while (html.childNodes.length) { 20 | frag.appendChild(html.firstChild); 21 | } 22 | 23 | frag.removeChild(html); 24 | 25 | document.body.appendChild(frag); 26 | 27 | flexibility(document.body); 28 | } 29 | } 30 | 31 | xhr.send(); 32 | } 33 | 34 | function control(name) { 35 | var xhr = new XMLHttpRequest(); 36 | 37 | xhr.open('GET', 'shared/' + name + '.html?' + new Date().getTime()); 38 | 39 | xhr.onreadystatechange = function () { 40 | if (xhr.readyState === 4) { 41 | var frag = document.createDocumentFragment(); 42 | var html = frag.appendChild(document.createElement('x')); 43 | 44 | if (frag.createElement) { 45 | frag.createElement('section'); 46 | } 47 | 48 | html.innerHTML = xhr.responseText.replace(/data-style/g, 'data-style style'); 49 | 50 | while (html.childNodes.length) { 51 | frag.appendChild(html.firstChild); 52 | } 53 | 54 | frag.removeChild(html); 55 | 56 | document.body.appendChild(frag); 57 | } 58 | } 59 | 60 | xhr.send(); 61 | } 62 | 63 | function editableTest(name) { 64 | var xhr = new XMLHttpRequest(); 65 | 66 | xhr.open('GET', 'shared/' + name + '.html?' + new Date().getTime()); 67 | 68 | xhr.onreadystatechange = function () { 69 | if (xhr.readyState === 4) { 70 | var frag = document.createDocumentFragment(); 71 | var html = frag.appendChild(document.createElement('x')); 72 | 73 | if (frag.createElement) { 74 | frag.createElement('section'); 75 | } 76 | 77 | html.innerHTML = xhr.responseText; 78 | 79 | while (html.childNodes.length) { 80 | frag.appendChild(html.firstChild); 81 | } 82 | 83 | frag.removeChild(html); 84 | 85 | document.body.appendChild(frag); 86 | 87 | var container = document.getElementById('container'); 88 | 89 | var textarea = document.createElement('textarea'); 90 | 91 | textarea.setAttribute('style', 'font-family:monospace,monospace;font-size:100%'); 92 | textarea.setAttribute('cols', 40); 93 | textarea.setAttribute('rows', 8); 94 | textarea.value = container.getAttribute('data-style').replace(/;\s*/g, ';\n'); 95 | 96 | document.body.appendChild(textarea); 97 | 98 | var onresizeTimeout; 99 | 100 | function onresize() { 101 | window.onresize = null; 102 | textarea.onkeyup = null; 103 | 104 | if (!onresizeTimeout) { 105 | onresizeTimeout = setTimeout(function () { 106 | onresizeTimeout = null; 107 | 108 | var index = -1; 109 | var elements = container.querySelectorAll('[style]'); 110 | var element; 111 | 112 | while (element = elements[++index]) { 113 | element.removeAttribute('style'); 114 | } 115 | 116 | var style = textarea.value.replace(/\s+/, ' '); 117 | 118 | container.setAttribute('style', style); 119 | container.setAttribute('data-style', style); 120 | 121 | try { 122 | flexibility(container); 123 | } catch (error) {} 124 | 125 | window.onresize = onresize; 126 | textarea.onkeyup = onresize; 127 | }, 67); 128 | } 129 | } 130 | 131 | onresize(); 132 | } 133 | } 134 | 135 | xhr.send(); 136 | } 137 | -------------------------------------------------------------------------------- /test/shared/style.css: -------------------------------------------------------------------------------- 1 | * { margin: 0; } 2 | 3 | html { font: 100%/1 sans-serif; } 4 | body { margin: 20px; } 5 | section { display: block; margin-top: 20px; } 6 | h1, h3 { margin: 40px 0 20px; } 7 | h3 { font-size: 100%; } 8 | 9 | .wrap { background-color: #73a75c; border: 1px solid #3a542f; margin-top: 20px; padding: 10px; } 10 | .item { background-color: #8fb97c; border: 1px solid #c7ddbd; padding: 10px; } 11 | 12 | /* section > div[data-style] { background-color: #f9f9f9; border: 1px solid #eeeeee; margin-top: 10px; padding: 10px; } 13 | div[data-style] span { background-color: #f4f3f0; border: 1px solid #cccccc; padding: 10px; } 14 | div[data-style] span { background-color: #8fb97c; border: 1px solid #c7ddbd; color: #000000; display: inline-block; font-size: 14px; line-height: 15px; padding: 10px; text-align: center; } */ 15 | 16 | -------------------------------------------------------------------------------- /test/shared/svg.html: -------------------------------------------------------------------------------- 1 |
2 |

3 SVGs

3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 |
24 | -------------------------------------------------------------------------------- /test/svg.control.html: -------------------------------------------------------------------------------- 1 | 2 | control - SVG 3 | 4 | 5 | 6 | 7 |

control - SVG

8 | 9 | -------------------------------------------------------------------------------- /test/svg.html: -------------------------------------------------------------------------------- 1 | 2 | test - SVG 3 | 4 | 5 | 6 | 7 |

test - SVG

8 | 9 | --------------------------------------------------------------------------------