diff --git a/README.md b/README.md index 74c477d9..3df78385 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ div:nth-child(3n + 1) { ##### Basic Columns -To create a basic horizontal grid, just insert some elements into any containing element like so and pass a fraction to the `lost-column` property. +To create a basic horizontal grid, just insert some elements into any containing element like so and pass a fraction to the `lost-column` property. To unset (or remove) a column rule, possibly at a larger breakpoint, use `lost-column: none;` ```html
@@ -145,6 +145,61 @@ div { } ``` +#### Unsetting Columns + +```css +div { + lost-column: 1/2; +} +@media screen and (min-width: 480px) { + div { + lost-column: none; + } +} +``` + + +Processed CSS: + +```css +section { + *zoom: 1; +} + +section:before { + content: ''; + display: table; +} + +section:after { + content: ''; + display: table; + clear: both; +} + +div { + width: calc(99.99% * 1/2 - (30px - 30px * 1/2)); +} + +div:nth-child(n) { + float: left; + margin-right: 30px; + clear: none; +} + +div:last-child { + margin-right: 0; +} + +div:nth-child(2n) { + margin-right: 0; +} + +div:nth-child(2n + 1) { + clear: left; +} +``` + `lost-utility: clearfix;` is just a [clearfix](http://nicolasgallagher.com/micro-clearfix-hack/) function since Lost Grid elements are floated. It's a good idea to give this to the element wrapping your grid elements every time you have nested floated elements. **[⬆ back to top](#table-of-contents)** @@ -164,6 +219,50 @@ div { lost-column: 1/2; } ``` +Processed CSS: + +```css +section { + *zoom: 1; + max-width: 980px; + margin-left: auto; + margin-right: auto; +} + +section:before { + content: ''; + display: table; +} + +section:after { + content: ''; + display: table; + clear: both; +} + +div { + width: calc(99.99% * 1/2 - (30px - 30px * 1/2)); +} + +div:nth-child(n) { + float: left; + margin-right: 30px; + clear: none; +} + +div:last-child { + margin-right: 0; +} + +div:nth-child(2n) { + margin-right: 0; +} + +div:nth-child(2n + 1) { + clear: left; +} +``` + **[⬆ back to top](#table-of-contents)** @@ -181,6 +280,28 @@ div { } ``` +Processed CSS: + +```css +div { + width: calc(99.99% * 2/4 - (30px - 30px * 2/4)); +} +div:nth-child(n) { + float: left; + margin-right: 30px; + clear: none; +} +div:last-child { + margin-right: 0; +} +div:nth-child(2n) { + margin-right: 0; +} +div:nth-child(2n + 1) { + clear: left; +} +``` + This will tell Lost to create `div:nth-child(2n) { margin-right: 0; }` *instead* of `div:nth-child(4n) { margin-right: 0; }` (like it would by default and break). Using this knowledge we can create really flexible layouts with varying widths like so (this will work for a single row nicely). @@ -207,6 +328,68 @@ Using this knowledge we can create really flexible layouts with varying widths l } ``` +Processed CSS: +```css +.row { + *zoom: 1; +} + +.row:before { + content: ''; + display: table; +} + +.row:after { + content: ''; + display: table; + clear: both; +} + +.quarter { + width: calc(99.99% * 1/4 - (30px - 30px * 1/4)); +} + +.quarter:nth-child(n) { + float: left; + margin-right: 30px; + clear: none; +} + +.quarter:last-child { + margin-right: 0; +} + +.quarter:nth-child(0n) { + margin-right: 0; +} + +.quarter:nth-child(0n + 1) { + clear: left; +} + +.half { + width: calc(99.99% * 1/2 - (30px - 30px * 1/2)); +} + +.half:nth-child(n) { + float: left; + margin-right: 30px; + clear: none; +} + +.half:last-child { + margin-right: 0; +} + +.half:nth-child(0n) { + margin-right: 0; +} + +.half:nth-child(0n + 1) { + clear: left; +} +``` + There is a global setting to disable/enable `cycle` by default. Just put `@lost cycle auto;` or `@lost cycle none;` at the top of your stylesheet. It's suggested that you learn the Lost shorthand syntax, but you can specify cycle (and other params) the verbose way with `lost-column-cycle`. @@ -218,6 +401,27 @@ div { } ``` +Processed CSS: +```css +div { + width: calc(99.99% * 2/6 - (30px - 30px * 2/6)); +} +div:nth-child(n) { + float: left; + margin-right: 30px; + clear: none; +} +div:last-child { + margin-right: 0; +} +div:nth-child(3n) { + margin-right: 0; +} +div:nth-child(3n + 1) { + clear: left; +} +``` + The concept of `cycle` is **extremely important** to Lost and what sets good Lost developers apart from great Lost developers. Really try to grok this! **[⬆ back to top](#table-of-contents)** @@ -247,6 +451,28 @@ div { } ``` +Processed CSS: + +```css +div { + width: calc(99.99% * 1/2 - (30px - 30px * 1/2)); +} +div:nth-child(n) { + float: left; + margin-right: 30px; + clear: none; +} +div:last-child { + margin-right: 0; +} +div:nth-child(2n) { + margin-right: 0; +} +div:nth-child(2n + 1) { + clear: left; +} +``` + **[⬆ back to top](#table-of-contents)**   @@ -272,6 +498,35 @@ div:first-child { } ``` +Processed CSS: +```css +div { + width: calc(99.99% * 1/3 - (30px - 30px * 1/3)); +} + +div:nth-child(n) { + float: left; + margin-right: 30px; + clear: none; +} + +div:last-child { + margin-right: 0; +} + +div:nth-child(3n) { + margin-right: 0; +} + +div:nth-child(3n + 1) { + clear: left; +} + +div:first-child { + margin-right: calc(99.99% * 1/3 - (30px - 30px * 1/3) + (30px * 2)) !important; +} +``` + **[⬆ back to top](#table-of-contents)**   @@ -299,13 +554,36 @@ div { } ``` +Processed CSS: +```css +section { + position: relative; + width: 600px; + height: 400px; +} + +section > * { + position: absolute; + top: 50%; + right: auto; + bottom: auto; + left: 50%; + transform: translate(-50%, -50%); +} + +div { + width: 100px; + height: 100px; +} +``` + **[⬆ back to top](#table-of-contents)**   ##### Edit Mode -Use `lost-utility: edit;` on `body` to visualize the entire structure of your site, or just specify the areas you're working on. +Use `lost-utility: edit;` on `body` to visualize the entire structure of your site, or just specify the areas you're working on. Currently the color is `rgba(0, 0, 255, 0.1)`. ```html
@@ -331,6 +609,19 @@ section:nth-of-type(2) { } ``` +Processed CSS: +```css +section:nth-of-type(1) *:not(input):not(textarea):not(select) { + + background-color: rgba(0, 0, 255, 0.1) +} + +section:nth-of-type(2) *:not(input):not(textarea):not(select) { + + background-color: rgba(0, 0, 255, 0.1) +} +``` + **[⬆ back to top](#table-of-contents)**   @@ -359,6 +650,23 @@ div { } ``` +Processed CSS: +```css +section { + height: 100%; +} + +div { + width: 100%; + height: calc(99.99% * 1/3 - (30px - 30px * 1/3)); + margin-bottom: 30px; +} + +div:last-child { + margin-bottom: 0; +} +``` + **[⬆ back to top](#table-of-contents)**   @@ -391,6 +699,42 @@ div { } ``` +Processed CSS: +```css +section { + height: 100%; +} + +div { + width: calc(99.99% * 1/3 - (30px - 30px * 1/3)); + height: calc(99.99% * 1/3 - (30px - 30px * 1/3)); +} + +div:nth-child(n) { + float: left; + margin-right: 30px; + margin-bottom: 30px; + clear: none; +} + +div:last-child { + margin-right: 0; + margin-bottom: 0; +} + +div:nth-child(3n) { + margin-right: 0; +} + +div:nth-child(3n + 1) { + clear: left; +} + +div:nth-last-child(-n + 3) { + margin-bottom: 0; +} +``` + **[⬆ back to top](#table-of-contents)**   @@ -419,6 +763,34 @@ div { } ``` +Processed CSS: +```css +section { + display: flex; + flex-flow: row wrap; + max-width: 980px; + margin-left: auto; + margin-right: auto; +} + +div { + flex: 0 0 auto; + width: calc(99.99% * 1/3 - (30px - 30px * 1/3)); +} + +div:nth-child(n) { + margin-right: 30px; +} + +div:last-child { + margin-right: 0; +} + +div:nth-child(3n) { + margin-right: 0; +} +``` + Flexbox offers slightly cleaner output and avoids the use of `clearfix` and other issues with float-based layouts. It also allows you to have elements of even height rather easily, and [much more](https://github.com/philipwalton/flexbugs/issues/32#issuecomment-90789645). The downside is, Flexbox doesn't work in IE9 or below, so keep that in mind if you have a client that needs that kind of support. Also note that waffle grids work well for the most part, but are somewhat finicky in fringe situations where Flexbox tries to act smarter than it is. All properties provide a way to disable or enable Flexbox per element with the `flex` parameter so if you'd like to disable it for a specific case you could do this: @@ -445,6 +817,56 @@ div { } ``` +Processed CSS: +```css +ection { + *zoom: 1; + max-width: 980px; + margin-left: auto; + margin-right: auto; +} + +section:before { + content: ''; + display: table; +} + +section:after { + content: ''; + display: table; + clear: both; +} + +div { + width: calc(99.99% * 1/3 - (30px - 30px * 1/3)); + height: calc(99.99% * 1/3 - (30px - 30px * 1/3)); +} + +div:nth-child(n) { + float: left; + margin-right: 30px; + margin-bottom: 30px; + clear: none; +} + +div:last-child { + margin-right: 0; + margin-bottom: 0; +} + +div:nth-child(3n) { + margin-right: 0; +} + +div:nth-child(3n + 1) { + clear: left; +} + +div:nth-last-child(-n + 3) { + margin-bottom: 0; +} +``` + **[⬆ back to top](#table-of-contents)**   @@ -471,6 +893,33 @@ div { } ``` +Processed CSS: +```css +section { + *zoom: 1; + margin-left: -15px; + margin-right: -15px; +} + +section:before { + content: ''; + display: table; +} + +section:after { + content: ''; + display: table; + clear: both; +} + +div { + flex: 0 0 auto; + width: calc(99.99% * 1/3 - 30px); + margin-left: 15px; + margin-right: 15px; +} +``` + **[⬆ back to top](#table-of-contents)**   @@ -489,6 +938,19 @@ Lost uses PostCSS which means to override global variables we need to use someth } ``` +Processed CSS: +```css +.foo { + flex: 0 0 auto; +} +.foo:nth-child(n) { + margin-right: 60px; +} +.foo:last-child { + margin-right: 0; +} +``` + - `gutter` accepts any unit value. `30px` by default. - `flexbox` accepts `flex` or `no-flex` (default). - `cycle` accepts `none` or any digit (although this is really weird). `auto` by default. @@ -510,6 +972,13 @@ section { } ``` +Processed CSS: +```css +section *:not(input):not(textarea):not(select) { + background-color: rgba(0, 0, 255, 0.1) +} +``` + **[⬆ back to top](#table-of-contents)**   @@ -529,6 +998,31 @@ div { } ``` +Processed CSS: +```css +section { + display: flex; + flex-flow: row wrap; +} + +div { + flex: 0 0 auto; + width: calc(99.99% * 1/2 - (60px - 60px * 1/2)); +} + +div:nth-child(n) { + margin-right: 60px; +} + +div:last-child { + margin-right: 0; +} + +div:nth-child(2n) { + margin-right: 0; +} +``` + **[⬆ back to top](#table-of-contents)**   @@ -550,6 +1044,28 @@ section { } ``` +Processed CSS: +```css +section { + display: flex; + flex-flow: row wrap; + max-width: 980px; + margin-left: auto; + margin-right: auto; +} + +section { + display: flex; + flex-flow: row wrap; + max-width: 1140px; + margin-left: auto; + margin-right: auto; + padding-left: 30px; + padding-right: 30px; +} + +``` + **[⬆ back to top](#table-of-contents)**   @@ -573,6 +1089,29 @@ Align nested elements. Apply this to a parent container. } ``` +Processed CSS: +```css +.parent { + position: relative; + width: 600px; + height: 400px; +} + +.parent > * { + position: absolute; + top: 50%; + right: 0; + bottom: auto; + left: auto; + transform: translate(0, -50%); +} + +.child { + width: 300px; + height: 150px; +} +``` + **[⬆ back to top](#table-of-contents)**   @@ -585,6 +1124,7 @@ Creates a column that is a fraction of the size of its containing element's widt - `gutter` - The margin on the right side of the element used to create a gutter. Typically this is left alone and settings.gutter will be used, but you can override it here if you want certain elements to have a particularly large or small gutter (pass 0 for no gutter at all). - `flex|no-flex` - Determines whether this element should use Flexbox or not. +- Setting `lost-column` to `none` will unset the column by inheriting the rules from the parent container. ```css div { @@ -596,6 +1136,39 @@ div { } ``` +Processed CSS: +```css +div { + flex: 0 0 auto; + width: calc(99.99% * 1/3 - (60px - 60px * 1/3)); +} + +div:nth-child(n) { + margin-right: 60px; +} + +div:last-child { + margin-right: 0; +} + +div { + flex: 0 0 auto; + width: calc(99.99% * 2/6 - (60px - 60px * 2/6)); +} + +div:nth-child(n) { + margin-right: 60px; +} + +div:last-child { + margin-right: 0; +} + +div:nth-child(3n) { + margin-right: 0; +} +``` + **[⬆ back to top](#table-of-contents)**   @@ -617,6 +1190,24 @@ div { } ``` +Processed CSS: +```css +section { + height: 100%; +} + +div { + width: 100%; + flex: 0 0 auto; + height: calc(99.99% * 1/3 - (60px - 60px * 1/3)); + margin-bottom: 60px; +} + +div:last-child { + margin-bottom: 0; +} +``` + **[⬆ back to top](#table-of-contents)**   @@ -639,6 +1230,29 @@ div { } ``` +Processed CSS: +```css +section { + height: 100%; +} + +div { + flex: 0 0 auto; + width: calc(99.99% * 1/3 - (60px - 60px * 1/3)); + height: calc(99.99% * 1/3 - (60px - 60px * 1/3)); +} + +div:nth-child(n) { + margin-right: 60px; + margin-bottom: 60px; +} + +div:last-child { + margin-right: 0; + margin-bottom: 0; +} +``` + **[⬆ back to top](#table-of-contents)**   @@ -660,6 +1274,26 @@ Margin to the left, right, bottom, or top, of an element depending on if the fra } ``` +Processed CSS: +```css +.two-elements { + flex: 0 0 auto; + width: calc(99.99% * 1/3 - (60px - 60px * 1/3)); +} + +.two-elements:nth-child(n) { + margin-right: 60px; +} + +.two-elements:last-child { + margin-right: 0; +} + +.two-elements:first-child { + margin-right: calc(99.99% * 1/3 - (60px - 60px * 1/3) + (60px * 2)) !important; +} +``` + **[⬆ back to top](#table-of-contents)**   @@ -685,6 +1319,32 @@ div:last-child { } ``` +Processed CSS: +```css +div { + flex: 0 0 auto; + width: calc(99.99% * 1/2 - (60px - 60px * 1/2)); +} + +div:nth-child(n) { + margin-right: 60px; +} + +div:last-child { + margin-right: 0; +} + +div:first-child { + position: relative; + left: calc(99.99% * 1/2 - (60px - 60px * 1/2) + 60px); +} + +div:last-child { + position: relative; + left: calc(99.99% * -1/2 - (60px - 60px * -1/2) + 60px); +} +``` + **[⬆ back to top](#table-of-contents)**   @@ -705,6 +1365,33 @@ div { } ``` +Processed CSS: +```css +section { + *zoom: 1; + margin-left: -30px; + margin-right: -30px; +} + +section:before { + content: ''; + display: table; +} + +section:after { + content: ''; + display: table; + clear: both; +} + +div { + flex: 0 0 auto; + width: calc(99.99% * 1/3 - 60px); + margin-left: 30px; + margin-right: 30px; +} +``` + **[⬆ back to top](#table-of-contents)**   @@ -725,6 +1412,23 @@ div { } ``` +Processed CSS: +```css +section { + display: flex; + flex-flow: row wrap; + margin-left: -30px; + margin-right: -30px; +} + +div { + flex: 0 0 auto; + width: calc(99.99% * 1/3 - 60px); + margin-left: 30px; + margin-right: 30px; +} +``` + **[⬆ back to top](#table-of-contents)**   @@ -762,6 +1466,7 @@ If you like this project then I encourage you to check out a few of my other pro - [Alex Bass](http://abass.co) for letting me bounce ideas off of him. - [Maria Keller](https://dribbble.com/mariakeller) for the amazing logo. Be sure to hire her for all your design and motion graphic needs. +- [Peter Ramsing](http://peter.coffee/) for helping update the README, and adding enhancements. - Everyone who files an [Issue](https://github.com/corysimmons/lost/issues) when something isn't working as expected. - Everyone who is *actually* interested in my work on grids. diff --git a/lib/lost-column.js b/lib/lost-column.js index 1d3c91ec..b8f5fa89 100644 --- a/lib/lost-column.js +++ b/lib/lost-column.js @@ -40,132 +40,165 @@ module.exports = function lostColumnDecl(css, settings) { lostColumnGutter = settings.gutter, lostColumnFlexbox = settings.flexbox; - if (settings.cycle === 'auto') { - lostColumnCycle = decl.value.split('/')[1]; - } else { - lostColumnCycle = settings.cycle; - } - - declArr = decl.value.split(' '); - lostColumn = declArr[0]; - - if (declArr[1] !== undefined && declArr[1].search(/^\d/) !== -1) { - lostColumnCycle = declArr[1]; - } + if (decl.value !== 'none') { + if (settings.cycle === 'auto') { + lostColumnCycle = decl.value.split('/')[1]; + } else { + lostColumnCycle = settings.cycle; + } - if (declArr[1] == 'flex' || declArr[1] == 'no-flex' || declArr[1] == 'auto') { - lostColumnCycle = declArr[0].split('/')[1]; - } + declArr = decl.value.split(' '); + lostColumn = declArr[0]; - if (declArr[2] !== undefined && declArr[2].search(/^\d/) !== -1) { - lostColumnGutter = declArr[2]; - } + if (declArr[1] !== undefined && declArr[1].search(/^\d/) !== -1) { + lostColumnCycle = declArr[1]; + } - if (declArr.indexOf('flex') !== -1) { - lostColumnFlexbox = 'flex'; - } + if (declArr[1] == 'flex' || declArr[1] == 'no-flex' || declArr[1] == 'auto') { + lostColumnCycle = declArr[0].split('/')[1]; + } - if (declArr.indexOf('no-flex') !== -1) { - lostColumnFlexbox = 'no-flex'; - } + if (declArr[2] !== undefined && declArr[2].search(/^\d/) !== -1) { + lostColumnGutter = declArr[2]; + } - decl.parent.nodes.forEach(function (decl) { - if (decl.prop == 'lost-column-cycle') { - lostColumnCycle = decl.value; + if (declArr.indexOf('flex') !== -1) { + lostColumnFlexbox = 'flex'; + } - decl.remove(); + if (declArr.indexOf('no-flex') !== -1) { + lostColumnFlexbox = 'no-flex'; } - }); - decl.parent.nodes.forEach(function (decl) { - if (decl.prop == 'lost-column-gutter') { - lostColumnGutter = decl.value; + decl.parent.nodes.forEach(function (decl) { + if (decl.prop == 'lost-column-cycle') { + lostColumnCycle = decl.value; - decl.remove(); - } - }); + decl.remove(); + } + }); - decl.parent.nodes.forEach(function (decl) { - if (decl.prop == 'lost-column-flexbox') { - if (decl.prop == 'flex') { - lostColumnFlexbox = 'flex'; + decl.parent.nodes.forEach(function (decl) { + if (decl.prop == 'lost-column-gutter') { + lostColumnGutter = decl.value; + + decl.remove(); } + }); - decl.remove(); - } - }); + decl.parent.nodes.forEach(function (decl) { + if (decl.prop == 'lost-column-flexbox') { + if (decl.prop == 'flex') { + lostColumnFlexbox = 'flex'; + } - if (lostColumnFlexbox === 'flex') { - decl.cloneBefore({ - prop: 'flex', - value: '0 0 auto' + decl.remove(); + } }); - if (lostColumnCycle !== 0) { + if (lostColumnFlexbox === 'flex') { + decl.cloneBefore({ + prop: 'flex', + value: '0 0 auto' + }); + + if (lostColumnCycle !== 0) { + newBlock( + decl, + ':nth-child('+ lostColumnCycle +'n)', + ['margin-right'], + [0] + ); + } + newBlock( decl, - ':nth-child('+ lostColumnCycle +'n)', + ':last-child', ['margin-right'], [0] ); - } - newBlock( - decl, - ':last-child', - ['margin-right'], - [0] - ); - - newBlock( - decl, - ':nth-child(n)', - ['margin-right'], - [lostColumnGutter] - ); - } else { - - if (lostColumnCycle !== 0) { newBlock( decl, - ':nth-child('+ lostColumnCycle +'n + 1)', - ['clear'], - ['left'] + ':nth-child(n)', + ['margin-right'], + [lostColumnGutter] ); + } else { + + if (lostColumnCycle !== 0) { + newBlock( + decl, + ':nth-child('+ lostColumnCycle +'n + 1)', + ['clear'], + ['left'] + ); + + newBlock( + decl, + ':nth-child('+ lostColumnCycle +'n)', + ['margin-right'], + [0] + ); + } newBlock( decl, - ':nth-child('+ lostColumnCycle +'n)', + ':last-child', ['margin-right'], [0] ); + + newBlock( + decl, + ':nth-child(n)', + ['float', 'margin-right', 'clear'], + ['left', lostColumnGutter, 'none'] + ); + } + + if (lostColumnGutter !== '0') { + decl.cloneBefore({ + prop: 'width', + value: 'calc(99.99% * '+ lostColumn +' - ('+ lostColumnGutter +' - '+ lostColumnGutter +' * '+ lostColumn +'))' + }); + } else { + decl.cloneBefore({ + prop: 'width', + value: 'calc(99.999999% * '+ lostColumn +')' + }); } + } else { + decl.cloneBefore({ + prop: 'width', + value: 'inherit' + }); newBlock( decl, - ':last-child', - ['margin-right'], - [0] + ':nth-child(1n)', + ['float', 'clear', 'margin-right', 'width'], + ['inherit', 'inherit', 'inherit', 'inherit'] + ); + newBlock( + decl, + ':nth-child(1n + 1)', + ['float', 'clear', 'margin-right', 'width'], + ['inherit', 'inherit', 'inherit', 'inherit'] ); - newBlock( decl, ':nth-child(n)', - ['float', 'margin-right', 'clear'], - ['left', lostColumnGutter, 'none'] + ['float', 'clear', 'margin-right', 'width'], + ['inherit', 'inherit', 'inherit', 'inherit'] + ); + newBlock( + decl, + ':last-child', + ['float', 'clear', 'margin-right', 'width'], + ['inherit', 'inherit', 'inherit', 'inherit'] ); - } - if (lostColumnGutter !== '0') { - decl.cloneBefore({ - prop: 'width', - value: 'calc(99.99% * '+ lostColumn +' - ('+ lostColumnGutter +' - '+ lostColumnGutter +' * '+ lostColumn +'))' - }); - } else { - decl.cloneBefore({ - prop: 'width', - value: 'calc(99.999999% * '+ lostColumn +')' - }); } decl.remove(); diff --git a/test/lost-column.js b/test/lost-column.js index 00479faf..c79a85dd 100644 --- a/test/lost-column.js +++ b/test/lost-column.js @@ -57,4 +57,15 @@ describe('lost-column', function() { 'a:nth-child(3n) { margin-right: 0; }' ); }); + + it('provides none rule', function() { + check( + 'a { lost-column: none; }', + 'a { width: inherit; }\n' + + 'a:last-child { float: inherit; clear: inherit; margin-right: inherit; width: inherit; }\n' + + 'a:nth-child(n) { float: inherit; clear: inherit; margin-right: inherit; width: inherit; }\n' + + 'a:nth-child(1n + 1) { float: inherit; clear: inherit; margin-right: inherit; width: inherit; }\n' + + 'a:nth-child(1n) { float: inherit; clear: inherit; margin-right: inherit; width: inherit; }' + ); + }); });