├── .gitignore ├── .npmignore ├── LICENSE.md ├── README.md ├── examples ├── bootstrap │ ├── README.md │ ├── css-gridish.json │ ├── css-gridish │ │ ├── README.md │ │ ├── bootstrap-grid.sketch │ │ ├── css │ │ │ ├── bootstrap-grid-legacy.css │ │ │ ├── bootstrap-grid-legacy.min.css │ │ │ ├── bootstrap-grid.css │ │ │ └── bootstrap-grid.min.css │ │ └── scss │ │ │ ├── _core.scss │ │ │ ├── _functions.scss │ │ │ ├── _mixins.scss │ │ │ ├── _sass-list-maps.scss │ │ │ ├── _utilities.scss │ │ │ ├── _values.scss │ │ │ ├── _variables.scss │ │ │ ├── bootstrap-grid-legacy.scss │ │ │ └── bootstrap-grid.scss │ ├── index.html │ ├── intro.md │ ├── package.json │ └── yarn.lock ├── carbon │ ├── README.md │ ├── css-gridish.json │ ├── css-gridish │ │ ├── README.md │ │ ├── bx-grid.sketch │ │ ├── css │ │ │ ├── bx-grid-legacy.css │ │ │ ├── bx-grid-legacy.min.css │ │ │ ├── bx-grid.css │ │ │ └── bx-grid.min.css │ │ └── scss │ │ │ ├── _core.scss │ │ │ ├── _functions.scss │ │ │ ├── _mixins.scss │ │ │ ├── _sass-list-maps.scss │ │ │ ├── _utilities.scss │ │ │ ├── _values.scss │ │ │ ├── _variables.scss │ │ │ ├── bx-grid-legacy.scss │ │ │ └── bx-grid.scss │ ├── index.html │ ├── intro.md │ ├── package.json │ └── yarn.lock └── material │ ├── README.md │ ├── css-gridish.json │ ├── css-gridish │ ├── README.md │ ├── css │ │ ├── material-grid-legacy.css │ │ ├── material-grid-legacy.min.css │ │ ├── material-grid.css │ │ └── material-grid.min.css │ ├── material-grid.sketch │ └── scss │ │ ├── _core.scss │ │ ├── _functions.scss │ │ ├── _mixins.scss │ │ ├── _sass-list-maps.scss │ │ ├── _utilities.scss │ │ ├── _values.scss │ │ ├── _variables.scss │ │ ├── material-grid-legacy.scss │ │ └── material-grid.scss │ ├── example.html │ ├── index.html │ ├── intro.md │ ├── package.json │ └── yarn.lock ├── extension ├── LICENSE.md ├── icons │ ├── icon128.png │ ├── icon16.png │ ├── icon19.png │ ├── icon32.png │ ├── icon48.png │ └── icon64.png ├── manifest.json └── src │ ├── browserAction │ ├── browserAction.html │ └── browserAction.js │ └── inject │ ├── inject.css │ └── inject.js ├── graphics ├── configDiagram.png ├── graphics.sketch ├── gridish.png └── gridish_3times.gif ├── gulpfile.js ├── index.html ├── package.json ├── src ├── docs │ └── README.md.hbs ├── index.js ├── scss │ ├── _core.scss │ ├── _functions.scss │ ├── _mixins.scss │ ├── _sass-list-maps.scss │ ├── _utilities.scss │ ├── _variables.scss │ ├── gridish-grid-legacy.scss │ └── gridish-grid.scss └── sketch │ ├── artboard.json │ └── files │ ├── document.json │ ├── meta.json │ ├── pages │ └── BC333699-815E-4E1B-9816-9836EDA5B291.json │ ├── previews │ └── preview.png │ └── user.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | etc 3 | node_modules 4 | output 5 | *.log -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | examples 2 | extension 3 | graphics 4 | output 5 | src -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2017 IBM 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSS Gridish 2 | 3 | ![CSS Gridish Logo](/graphics/gridish_3times.gif?raw=true) 4 | 5 | CSS Gridish takes design specs of your product’s grid and builds out several resources for your team to use: 6 | 7 | * Sketch file with artboards and grid/layout settings for designers 8 | * CSS/SCSS code using CSS Grid with a CSS Flexbox fallback for developers 9 | * [Google Chrome extension](https://chrome.google.com/webstore/detail/css-gridish/ebhcneoilkamaddhlphlehojpcooobgc) for anyone to check a webpage’s alignment 10 | 11 | **This tool is not a grid system with a grid already designed for you.** Instead, CSS Gridish builds all of the resources for the grid your team designed. 12 | 13 | We hope it helps teams adapt CSS Grid sooner and enables more complex layouts. To show how versatile the tool is, we have examples of grids from [Bootstrap,](https://ibm.github.io/css-gridish/examples/bootstrap/index.html) [Carbon Design System,](https://ibm.github.io/css-gridish/examples/carbon/index.html) and [Material Design.](https://ibm.github.io/css-gridish/examples/material/index.html) 14 | 15 | The truth is that many enterprise projects can’t afford to drop support for browsers that do not [support CSS Grid Layout](https://developer.mozilla.org/en-US/docs/Web/CSS/grid#Browser_compatibility) yet. This tool takes your grid’s design specs and builds a slim CSS Grid Layout implementation and a fallback to [CSS Flexbox support.](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout#Browser_compatibility) 16 | 17 | ## Build your grid code 18 | 19 | Requires [Node v8.2.0](https://nodejs.org/en/) or higher, which includes npm and npx. 20 | 21 | 1. Create a file called `css-gridish.json` in your project root. See the [config documentation](#config-file) or an [example config](./examples/material/css-gridish.json) for help. 22 | 2. Determine how you want your grid built: 23 | * If you want to build once, run command `npx css-gridish`. 24 | * If you want to add the grid building to your project’s build process: 25 | 1. Run command `npm install css-gridish`. 26 | 2. Add `scripts: {build: "css-gridish"}` in your `package.json`. 27 | 3. Run command `npm run build`. 28 | 29 | Your CSS and `README.md` with class documentation will be built into `./css-gridish/`. 30 | 31 | ### Config file 32 | 33 | ![CSS Gridish takes design redlines and makes developer-friendly code](/graphics/configDiagram.png?raw=true) 34 | 35 | The config file is where all of your design system specs live. See this [example](./examples/carbon/css-gridish.json) for help. Edit your `css-gridish.json` to have all generated grid content match your design system: 36 | 37 | ``` 38 | { 39 | "prefix": "gridish", // Custom prefix for all classes and filenames 40 | "breakpoints": { 41 | // Class name for a breakpoint 42 | "sm": { 43 | "breakpoint": 20, // Min-width for media query (number in rem) 44 | "columns": 4, // Quantity of columns (number) 45 | "gutter": "2rem", // Space between columns (rem string, px string, vw string or 0) 46 | "margin": "3vw" // Horizontal margin of grid container (rem string, px string, vw string or 0) 47 | }, 48 | ... 49 | "max": { 50 | "breakpoint": 100, 51 | "columns": 12, 52 | "gutter": "4rem", 53 | "margin": "5vw" 54 | } 55 | }, 56 | "extraArtboards": { 57 | "xlg": 100 // Additional breakpoint for the Sketch file (number in rem) 58 | }, 59 | "rem": 16, // Base rem unit for all measurements (number in px) 60 | "rowHeight": 0.5, // Height of a fixed row (number in rem) 61 | "rows": 30, // Quantity of row variables (number) 62 | "paths": { 63 | "route": "css-gridish", // Route that files save in from project root (optional, use `""` for project root, `"css-gridish"` is default) 64 | "intro": "intro.md" // Path to any markdown you want inserted at the top of your README.md documentation (optional) 65 | } 66 | } 67 | ``` 68 | 69 | **Tip:** For the best results in Sketch, we recommend you make your grid breakpoints, margin, and gutter divisible by the row height. 70 | 71 | **Required:** Even if your design specs do not change between breakpoints, you need to list the max-width breakpoint in the `breakpoints` object. 72 | 73 | The first breakpoint min-width media query is not used to save kilobytes, but we recommend stating it anyways for future artboard-making tools. 74 | 75 | ## Legacy support 76 | 77 | If you are supporting browsers that lack [CSS Grid Layout support](https://developer.mozilla.org/en-US/docs/Web/CSS/grid#Browser_compatibility), you can use `css-gridish/yourPrefix-legacy.min.css` and the legacy classes detailed in the `README.md`. With the legacy file and classes, the browsers that do not support the final CSS Grid Legacy spec will fallback to a CSS Flexbox alternative. The CSS Flexbox alternative supports embedded subgrids that still reflect the overall grid system’s column structure. 78 | 79 | ### User-defined breakpoints 80 | 81 | One of the best parts about CSS Grid Layout is that your users can rearrange the layout at any width in their own media query. Your grid will also support rearranging layout at custom breakpoints for the legacy implementation when the user compiles their own Sass. Just have them define the following map of rem widths before they import in your Sass file: 82 | 83 | ```scss 84 | $extraBreakpoints: ( 85 | xsm: 10, 86 | whatever: 78, 87 | superxlarge: 1000, 88 | ... 89 | ); 90 | @import './css-gridish/scss/yourPrefix-legacy.scss; 91 | ``` 92 | 93 | ### Transitioning from Legacy 94 | 95 | Once your experience can drop support for browsers like IE 11 and Edge <15, you can simply remove all legacy classes and switch over to the non-legacy files. This is a great progressive-enhancement for your performance when it happens. 96 | 97 | ## Future Updates 98 | 99 | * [ ] Once Edge and Safari gain `display: subgrid` support, we can remove our dependence on `vw` units. 100 | * [ ] Once a solution in the CSS Grid spec is given for [one item to ignore](https://github.com/w3c/csswg-drafts/issues/2117) `grid-gap`, we can utilize `grid-gap` by default instead of opting in to padding classes. 101 | 102 | ## FAQs 103 | 104 | ### Why does none of the CSS Grid code use `grid-gap` for gutters? 105 | 106 | A lot of times, you will want an item to break out of the gutters for background color, to extend media, or for another reason. Until the CSS Grid spec has a way to ignore that gutter, we use the padding classes (`.yourGrid-padding`) to opt-in to respecting the gutter. The padding classes are always half the size of a gutter for alignment. 107 | 108 | ### Why are columns using vw units and sometimes the calc function? 109 | 110 | Until Edge and Safari support 111 | [`display: subgrid`](https://developer.mozilla.org/en-US/docs/Web/CSS/display#Browser_compatibility), 112 | it will be difficult for you to write semantic HTML with CSS Grid Layout. We are 113 | able to take advantage of vw units and the calc function so you can embed your 114 | `.yourPrefix-grid` class inside of itself as much that is needed for you. 115 | 116 | ### Why are there no row classes for the legacy implementation? 117 | 118 | Thanks to flexbox’s wrapping functionality, nodes that specify rows are not necessary. Only create a node for a row if it has semantic or accessibility significance. You can keep embedding `.yourPrefix-grid` as necessary to accomplish this. 119 | 120 | ### What happens in the legacy implementation if I specify the column width for one breakpoint, but not the next larger breakpoint? 121 | 122 | To maintain a mobile-first opinion, column widths will scale to the next breakpoint if not specified. This means that a `.yourPrefix__col--sm--3` (with 6 total columns) would automatically grow into a `.yourPrefix__col--md--6` (with 12 total columns) if no `md` class was declared to maintain half of the screen size. 123 | -------------------------------------------------------------------------------- /examples/bootstrap/README.md: -------------------------------------------------------------------------------- 1 | # Bootstrap Design Grid 2 | 3 | [View a random layout with this grid.](https://ibm.github.io/css-gridish/examples/bootstrap/index.html) 4 | 5 | An example of [CSS Gridish](../../README.md) generating CSS Grid code, fallback flexbox code, dev documentation, and Sketch files based on [Bootstrap’s grid.](https://getbootstrap.com/docs/4.0/layout/grid/) 6 | 7 | Check out everything CSS Gridish made based off of the [config file](./css-gridish.json) in the [css-gridish folder.](./css-gridish/) 8 | -------------------------------------------------------------------------------- /examples/bootstrap/css-gridish.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "bootstrap", 3 | "breakpoints": { 4 | "sm": { 5 | "breakpoint": 36, 6 | "columns": 12, 7 | "gutter": "30px", 8 | "margin": 0 9 | }, 10 | "xl": { 11 | "breakpoint": 100, 12 | "columns": 12, 13 | "gutter": "30px", 14 | "margin": 0 15 | } 16 | }, 17 | "extraArtboards": { 18 | "md": 51, 19 | "lg": 66 20 | }, 21 | "rem": 15, 22 | "rowHeight": 1, 23 | "rows": 30, 24 | "paths": { 25 | "intro": "intro.md" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/bootstrap/css-gridish/bootstrap-grid.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/css-gridish/c5f16a541df485fa833f8f50299bd6a3f290a142/examples/bootstrap/css-gridish/bootstrap-grid.sketch -------------------------------------------------------------------------------- /examples/bootstrap/css-gridish/css/bootstrap-grid-legacy.min.css: -------------------------------------------------------------------------------- 1 | html{font-size:15px}body{margin:0}.bootstrap-container{box-sizing:border-box;margin-left:auto;margin-right:auto;max-width:100rem;overflow-x:hidden;width:100vw}.bootstrap-container--left{margin-left:0}.bootstrap-container--right{margin-right:0}.bootstrap-grid{align-items:flex-start;box-sizing:border-box;display:flex;display:grid;flex-wrap:wrap;position:relative;grid-auto-rows:minmax(1rem,min-content);grid-template-columns:repeat(auto-fill,8.33vw)}.bootstrap-grid>*{box-sizing:border-box;width:100%;grid-column:span 12}.bootstrap-grid>* :last-child,.bootstrap-grid>* :last-child>:last-child,.bootstrap-grid>* :last-child>:last-child>:last-child{margin-bottom:0}[class*=bootstrap-padding]{box-sizing:border-box}@supports (display:grid){.bootstrap-grid{align-items:unset}.bootstrap-grid>*{width:initial;height:100%}:root{--bootstrap-height-1:1rem;--bootstrap-height-2:2rem;--bootstrap-height-3:3rem;--bootstrap-height-4:4rem;--bootstrap-height-5:5rem;--bootstrap-height-6:6rem;--bootstrap-height-7:7rem;--bootstrap-height-8:8rem;--bootstrap-height-9:9rem;--bootstrap-height-10:10rem;--bootstrap-height-11:11rem;--bootstrap-height-12:12rem;--bootstrap-height-13:13rem;--bootstrap-height-14:14rem;--bootstrap-height-15:15rem;--bootstrap-height-16:16rem;--bootstrap-height-17:17rem;--bootstrap-height-18:18rem;--bootstrap-height-19:19rem;--bootstrap-height-20:20rem;--bootstrap-height-21:21rem;--bootstrap-height-22:22rem;--bootstrap-height-23:23rem;--bootstrap-height-24:24rem;--bootstrap-height-25:25rem;--bootstrap-height-26:26rem;--bootstrap-height-27:27rem;--bootstrap-height-28:28rem;--bootstrap-height-29:29rem}}.bootstrap-grid__height--sm--0{height:0;min-height:0}.bootstrap-grid__height--sm--1{grid-row:span 1;height:1rem;min-height:1rem}.bootstrap-grid__height--sm--2{grid-row:span 2;height:2rem;min-height:2rem}.bootstrap-grid__height--sm--3{grid-row:span 3;height:3rem;min-height:3rem}.bootstrap-grid__height--sm--4{grid-row:span 4;height:4rem;min-height:4rem}.bootstrap-grid__height--sm--5{grid-row:span 5;height:5rem;min-height:5rem}.bootstrap-grid__height--sm--6{grid-row:span 6;height:6rem;min-height:6rem}.bootstrap-grid__height--sm--7{grid-row:span 7;height:7rem;min-height:7rem}.bootstrap-grid__height--sm--8{grid-row:span 8;height:8rem;min-height:8rem}.bootstrap-grid__height--sm--9{grid-row:span 9;height:9rem;min-height:9rem}.bootstrap-grid__height--sm--10{grid-row:span 10;height:10rem;min-height:10rem}.bootstrap-grid__height--sm--11{grid-row:span 11;height:11rem;min-height:11rem}.bootstrap-grid__height--sm--12{grid-row:span 12;height:12rem;min-height:12rem}.bootstrap-grid__height--sm--13{grid-row:span 13;height:13rem;min-height:13rem}.bootstrap-grid__height--sm--14{grid-row:span 14;height:14rem;min-height:14rem}.bootstrap-grid__height--sm--15{grid-row:span 15;height:15rem;min-height:15rem}.bootstrap-grid__height--sm--16{grid-row:span 16;height:16rem;min-height:16rem}.bootstrap-grid__height--sm--17{grid-row:span 17;height:17rem;min-height:17rem}.bootstrap-grid__height--sm--18{grid-row:span 18;height:18rem;min-height:18rem}.bootstrap-grid__height--sm--19{grid-row:span 19;height:19rem;min-height:19rem}.bootstrap-grid__height--sm--20{grid-row:span 20;height:20rem;min-height:20rem}.bootstrap-grid__height--sm--21{grid-row:span 21;height:21rem;min-height:21rem}.bootstrap-grid__height--sm--22{grid-row:span 22;height:22rem;min-height:22rem}.bootstrap-grid__height--sm--23{grid-row:span 23;height:23rem;min-height:23rem}.bootstrap-grid__height--sm--24{grid-row:span 24;height:24rem;min-height:24rem}.bootstrap-grid__height--sm--25{grid-row:span 25;height:25rem;min-height:25rem}.bootstrap-grid__height--sm--26{grid-row:span 26;height:26rem;min-height:26rem}.bootstrap-grid__height--sm--27{grid-row:span 27;height:27rem;min-height:27rem}.bootstrap-grid__height--sm--28{grid-row:span 28;height:28rem;min-height:28rem}.bootstrap-grid__height--sm--29{grid-row:span 29;height:29rem;min-height:29rem}[class*=bootstrap-grid__col--sm--]{display:block}.bootstrap-grid__col--sm--0,.bootstrap-grid__col--sm--0--only{display:none}.bootstrap-padding{padding:15px}.bootstrap-padding--bottom{padding-bottom:15px}.bootstrap-padding--left{padding-left:15px}.bootstrap-padding--right{padding-right:15px}.bootstrap-padding--top{padding-top:15px}.bootstrap-padding--horizontal{padding-left:15px;padding-right:15px}.bootstrap-padding--vertical{padding-bottom:15px;padding-top:15px}.bootstrap-grid.bootstrap-grid--fixed-columns{grid-template-columns:repeat(auto-fill,3rem)}.bootstrap-grid.bootstrap-grid--fluid-rows{grid-auto-rows:8.33vw}.bootstrap-grid__col--sm--1{max-width:8.33rem;width:8.33vw;grid-column:span 1}.bootstrap-grid__col--sm--1.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 1}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--1{grid-row:span 1;height:8.33vw;min-height:8.33vw;max-height:8.33rem}.bootstrap-grid__col--sm--2{max-width:16.66rem;width:16.66vw;grid-column:span 2}.bootstrap-grid__col--sm--2.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 2}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--2{grid-row:span 2;height:16.66vw;min-height:16.66vw;max-height:16.66rem}.bootstrap-grid__col--sm--3{max-width:25rem;width:25vw;grid-column:span 3}.bootstrap-grid__col--sm--3.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 3}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--3{grid-row:span 3;height:25vw;min-height:25vw;max-height:25rem}.bootstrap-grid__col--sm--4{max-width:33.33rem;width:33.33vw;grid-column:span 4}.bootstrap-grid__col--sm--4.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 4}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--4{grid-row:span 4;height:33.33vw;min-height:33.33vw;max-height:33.33rem}.bootstrap-grid__col--sm--5{max-width:41.66rem;width:41.66vw;grid-column:span 5}.bootstrap-grid__col--sm--5.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 5}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--5{grid-row:span 5;height:41.66vw;min-height:41.66vw;max-height:41.66rem}.bootstrap-grid__col--sm--6{max-width:50rem;width:50vw;grid-column:span 6}.bootstrap-grid__col--sm--6.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 6}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--6{grid-row:span 6;height:50vw;min-height:50vw;max-height:50rem}.bootstrap-grid__col--sm--7{max-width:58.33rem;width:58.33vw;grid-column:span 7}.bootstrap-grid__col--sm--7.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 7}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--7{grid-row:span 7;height:58.33vw;min-height:58.33vw;max-height:58.33rem}.bootstrap-grid__col--sm--8{max-width:66.66rem;width:66.66vw;grid-column:span 8}.bootstrap-grid__col--sm--8.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 8}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--8{grid-row:span 8;height:66.66vw;min-height:66.66vw;max-height:66.66rem}.bootstrap-grid__col--sm--9{max-width:75rem;width:75vw;grid-column:span 9}.bootstrap-grid__col--sm--9.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 9}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--9{grid-row:span 9;height:75vw;min-height:75vw;max-height:75rem}.bootstrap-grid__col--sm--10{max-width:83.33rem;width:83.33vw;grid-column:span 10}.bootstrap-grid__col--sm--10.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 10}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--10{grid-row:span 10;height:83.33vw;min-height:83.33vw;max-height:83.33rem}.bootstrap-grid__col--sm--11{max-width:91.66rem;width:91.66vw;grid-column:span 11}.bootstrap-grid__col--sm--11.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 11}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--11{grid-row:span 11;height:91.66vw;min-height:91.66vw;max-height:91.66rem}.bootstrap-grid__col--sm--12{max-width:100rem;width:100vw;grid-column:span 12}.bootstrap-grid__col--sm--12.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 12}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--12{grid-row:span 12;height:100vw;min-height:100vw;max-height:100rem}@media screen and (min-width:100rem){.bootstrap-grid__col--sm--0--only,[class*=bootstrap-grid__col--xl--]{display:block}.bootstrap-grid__col--xl--0,.bootstrap-grid__col--xl--0--only{display:none}.bootstrap-padding{padding:15px}.bootstrap-padding--bottom{padding-bottom:15px}.bootstrap-padding--left{padding-left:15px}.bootstrap-padding--right{padding-right:15px}.bootstrap-padding--top{padding-top:15px}.bootstrap-padding--horizontal{padding-left:15px;padding-right:15px}.bootstrap-padding--vertical{padding-bottom:15px;padding-top:15px}.bootstrap-grid{grid-template-columns:repeat(auto-fill,8.33rem)}.bootstrap-grid.bootstrap-grid--fixed-columns{grid-template-columns:repeat(auto-fill,8.33333rem)}.bootstrap-grid.bootstrap-grid--fluid-rows{grid-auto-rows:8.33rem}[class*=bootstrap-grid__col--]{min-width:0}}@supports (display:grid){.bootstrap-grid>*,.bootstrap-grid>[class*=bootstrap-grid__col--]{min-width:initial;max-width:initial;width:initial}.bootstrap-grid>.bootstrap-grid,.bootstrap-grid>[class*=bootstrap-grid__col--].bootstrap-grid{display:grid}.bootstrap-grid>[class*=bootstrap-grid__height--]{height:unset;max-height:unset;min-height:initial}}.bootstrap-grid>script{display:none} -------------------------------------------------------------------------------- /examples/bootstrap/css-gridish/css/bootstrap-grid.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-size: 15px; } 3 | 4 | body { 5 | margin: 0; } 6 | 7 | .bootstrap-container { 8 | box-sizing: border-box; 9 | margin-left: auto; 10 | margin-right: auto; 11 | max-width: 100rem; 12 | overflow-x: hidden; 13 | width: 100vw; } 14 | 15 | .bootstrap-container--left { 16 | margin-left: 0; } 17 | 18 | .bootstrap-container--right { 19 | margin-right: 0; } 20 | 21 | .bootstrap-grid { 22 | align-items: flex-start; 23 | box-sizing: border-box; 24 | display: grid; 25 | flex-wrap: wrap; 26 | position: relative; } 27 | .bootstrap-grid > * { 28 | box-sizing: border-box; } 29 | .bootstrap-grid > * :last-child, 30 | .bootstrap-grid > * :last-child > :last-child, 31 | .bootstrap-grid > * :last-child > :last-child > :last-child { 32 | margin-bottom: 0; } 33 | 34 | [class*="bootstrap-padding"] { 35 | box-sizing: border-box; } 36 | 37 | @supports (display: grid) { 38 | .bootstrap-grid > * { 39 | height: 100%; } } 40 | 41 | :root { 42 | --bootstrap-height-1: 1rem; 43 | --bootstrap-height-2: 2rem; 44 | --bootstrap-height-3: 3rem; 45 | --bootstrap-height-4: 4rem; 46 | --bootstrap-height-5: 5rem; 47 | --bootstrap-height-6: 6rem; 48 | --bootstrap-height-7: 7rem; 49 | --bootstrap-height-8: 8rem; 50 | --bootstrap-height-9: 9rem; 51 | --bootstrap-height-10: 10rem; 52 | --bootstrap-height-11: 11rem; 53 | --bootstrap-height-12: 12rem; 54 | --bootstrap-height-13: 13rem; 55 | --bootstrap-height-14: 14rem; 56 | --bootstrap-height-15: 15rem; 57 | --bootstrap-height-16: 16rem; 58 | --bootstrap-height-17: 17rem; 59 | --bootstrap-height-18: 18rem; 60 | --bootstrap-height-19: 19rem; 61 | --bootstrap-height-20: 20rem; 62 | --bootstrap-height-21: 21rem; 63 | --bootstrap-height-22: 22rem; 64 | --bootstrap-height-23: 23rem; 65 | --bootstrap-height-24: 24rem; 66 | --bootstrap-height-25: 25rem; 67 | --bootstrap-height-26: 26rem; 68 | --bootstrap-height-27: 27rem; 69 | --bootstrap-height-28: 28rem; 70 | --bootstrap-height-29: 29rem; } 71 | 72 | .bootstrap-grid__height--sm--0 { 73 | height: 0; 74 | min-height: 0; } 75 | 76 | .bootstrap-grid__height--sm--1 { 77 | grid-row: span 1; } 78 | 79 | .bootstrap-grid__height--sm--2 { 80 | grid-row: span 2; } 81 | 82 | .bootstrap-grid__height--sm--3 { 83 | grid-row: span 3; } 84 | 85 | .bootstrap-grid__height--sm--4 { 86 | grid-row: span 4; } 87 | 88 | .bootstrap-grid__height--sm--5 { 89 | grid-row: span 5; } 90 | 91 | .bootstrap-grid__height--sm--6 { 92 | grid-row: span 6; } 93 | 94 | .bootstrap-grid__height--sm--7 { 95 | grid-row: span 7; } 96 | 97 | .bootstrap-grid__height--sm--8 { 98 | grid-row: span 8; } 99 | 100 | .bootstrap-grid__height--sm--9 { 101 | grid-row: span 9; } 102 | 103 | .bootstrap-grid__height--sm--10 { 104 | grid-row: span 10; } 105 | 106 | .bootstrap-grid__height--sm--11 { 107 | grid-row: span 11; } 108 | 109 | .bootstrap-grid__height--sm--12 { 110 | grid-row: span 12; } 111 | 112 | .bootstrap-grid__height--sm--13 { 113 | grid-row: span 13; } 114 | 115 | .bootstrap-grid__height--sm--14 { 116 | grid-row: span 14; } 117 | 118 | .bootstrap-grid__height--sm--15 { 119 | grid-row: span 15; } 120 | 121 | .bootstrap-grid__height--sm--16 { 122 | grid-row: span 16; } 123 | 124 | .bootstrap-grid__height--sm--17 { 125 | grid-row: span 17; } 126 | 127 | .bootstrap-grid__height--sm--18 { 128 | grid-row: span 18; } 129 | 130 | .bootstrap-grid__height--sm--19 { 131 | grid-row: span 19; } 132 | 133 | .bootstrap-grid__height--sm--20 { 134 | grid-row: span 20; } 135 | 136 | .bootstrap-grid__height--sm--21 { 137 | grid-row: span 21; } 138 | 139 | .bootstrap-grid__height--sm--22 { 140 | grid-row: span 22; } 141 | 142 | .bootstrap-grid__height--sm--23 { 143 | grid-row: span 23; } 144 | 145 | .bootstrap-grid__height--sm--24 { 146 | grid-row: span 24; } 147 | 148 | .bootstrap-grid__height--sm--25 { 149 | grid-row: span 25; } 150 | 151 | .bootstrap-grid__height--sm--26 { 152 | grid-row: span 26; } 153 | 154 | .bootstrap-grid__height--sm--27 { 155 | grid-row: span 27; } 156 | 157 | .bootstrap-grid__height--sm--28 { 158 | grid-row: span 28; } 159 | 160 | .bootstrap-grid__height--sm--29 { 161 | grid-row: span 29; } 162 | 163 | [class*="bootstrap-grid__col--sm--"] { 164 | display: block; } 165 | 166 | .bootstrap-grid__col--sm--0, 167 | .bootstrap-grid__col--sm--0--only { 168 | display: none; } 169 | 170 | .bootstrap-padding { 171 | padding: 15px; } 172 | 173 | .bootstrap-padding--bottom { 174 | padding-bottom: 15px; } 175 | 176 | .bootstrap-padding--left { 177 | padding-left: 15px; } 178 | 179 | .bootstrap-padding--right { 180 | padding-right: 15px; } 181 | 182 | .bootstrap-padding--top { 183 | padding-top: 15px; } 184 | 185 | .bootstrap-padding--horizontal { 186 | padding-left: 15px; 187 | padding-right: 15px; } 188 | 189 | .bootstrap-padding--vertical { 190 | padding-bottom: 15px; 191 | padding-top: 15px; } 192 | 193 | .bootstrap-grid { 194 | grid-auto-rows: minmax(1rem, min-content); 195 | grid-template-columns: repeat(auto-fill, 8.33vw); } 196 | .bootstrap-grid.bootstrap-grid--fixed-columns { 197 | grid-template-columns: repeat(auto-fill, 3rem); } 198 | .bootstrap-grid.bootstrap-grid--fluid-rows { 199 | grid-auto-rows: 8.33vw; } 200 | .bootstrap-grid > * { 201 | grid-column: span 12; } 202 | 203 | .bootstrap-grid__col--sm--1 { 204 | grid-column: span 1; } 205 | .bootstrap-grid__col--sm--1.bootstrap-grid > *:not([class*="bootstrap-grid__col"]) { 206 | grid-column: span 1; } 207 | 208 | .bootstrap-grid--fluid-rows 209 | > .bootstrap-grid__height--sm--1 { 210 | grid-row: span 1; } 211 | 212 | .bootstrap-grid__col--sm--2 { 213 | grid-column: span 2; } 214 | .bootstrap-grid__col--sm--2.bootstrap-grid > *:not([class*="bootstrap-grid__col"]) { 215 | grid-column: span 2; } 216 | 217 | .bootstrap-grid--fluid-rows 218 | > .bootstrap-grid__height--sm--2 { 219 | grid-row: span 2; } 220 | 221 | .bootstrap-grid__col--sm--3 { 222 | grid-column: span 3; } 223 | .bootstrap-grid__col--sm--3.bootstrap-grid > *:not([class*="bootstrap-grid__col"]) { 224 | grid-column: span 3; } 225 | 226 | .bootstrap-grid--fluid-rows 227 | > .bootstrap-grid__height--sm--3 { 228 | grid-row: span 3; } 229 | 230 | .bootstrap-grid__col--sm--4 { 231 | grid-column: span 4; } 232 | .bootstrap-grid__col--sm--4.bootstrap-grid > *:not([class*="bootstrap-grid__col"]) { 233 | grid-column: span 4; } 234 | 235 | .bootstrap-grid--fluid-rows 236 | > .bootstrap-grid__height--sm--4 { 237 | grid-row: span 4; } 238 | 239 | .bootstrap-grid__col--sm--5 { 240 | grid-column: span 5; } 241 | .bootstrap-grid__col--sm--5.bootstrap-grid > *:not([class*="bootstrap-grid__col"]) { 242 | grid-column: span 5; } 243 | 244 | .bootstrap-grid--fluid-rows 245 | > .bootstrap-grid__height--sm--5 { 246 | grid-row: span 5; } 247 | 248 | .bootstrap-grid__col--sm--6 { 249 | grid-column: span 6; } 250 | .bootstrap-grid__col--sm--6.bootstrap-grid > *:not([class*="bootstrap-grid__col"]) { 251 | grid-column: span 6; } 252 | 253 | .bootstrap-grid--fluid-rows 254 | > .bootstrap-grid__height--sm--6 { 255 | grid-row: span 6; } 256 | 257 | .bootstrap-grid__col--sm--7 { 258 | grid-column: span 7; } 259 | .bootstrap-grid__col--sm--7.bootstrap-grid > *:not([class*="bootstrap-grid__col"]) { 260 | grid-column: span 7; } 261 | 262 | .bootstrap-grid--fluid-rows 263 | > .bootstrap-grid__height--sm--7 { 264 | grid-row: span 7; } 265 | 266 | .bootstrap-grid__col--sm--8 { 267 | grid-column: span 8; } 268 | .bootstrap-grid__col--sm--8.bootstrap-grid > *:not([class*="bootstrap-grid__col"]) { 269 | grid-column: span 8; } 270 | 271 | .bootstrap-grid--fluid-rows 272 | > .bootstrap-grid__height--sm--8 { 273 | grid-row: span 8; } 274 | 275 | .bootstrap-grid__col--sm--9 { 276 | grid-column: span 9; } 277 | .bootstrap-grid__col--sm--9.bootstrap-grid > *:not([class*="bootstrap-grid__col"]) { 278 | grid-column: span 9; } 279 | 280 | .bootstrap-grid--fluid-rows 281 | > .bootstrap-grid__height--sm--9 { 282 | grid-row: span 9; } 283 | 284 | .bootstrap-grid__col--sm--10 { 285 | grid-column: span 10; } 286 | .bootstrap-grid__col--sm--10.bootstrap-grid > *:not([class*="bootstrap-grid__col"]) { 287 | grid-column: span 10; } 288 | 289 | .bootstrap-grid--fluid-rows 290 | > .bootstrap-grid__height--sm--10 { 291 | grid-row: span 10; } 292 | 293 | .bootstrap-grid__col--sm--11 { 294 | grid-column: span 11; } 295 | .bootstrap-grid__col--sm--11.bootstrap-grid > *:not([class*="bootstrap-grid__col"]) { 296 | grid-column: span 11; } 297 | 298 | .bootstrap-grid--fluid-rows 299 | > .bootstrap-grid__height--sm--11 { 300 | grid-row: span 11; } 301 | 302 | .bootstrap-grid__col--sm--12 { 303 | grid-column: span 12; } 304 | .bootstrap-grid__col--sm--12.bootstrap-grid > *:not([class*="bootstrap-grid__col"]) { 305 | grid-column: span 12; } 306 | 307 | .bootstrap-grid--fluid-rows 308 | > .bootstrap-grid__height--sm--12 { 309 | grid-row: span 12; } 310 | 311 | @media screen and (min-width: 100rem) { 312 | .bootstrap-grid__col--sm--0--only { 313 | display: block; } 314 | [class*="bootstrap-grid__col--xl--"] { 315 | display: block; } 316 | .bootstrap-grid__col--xl--0, 317 | .bootstrap-grid__col--xl--0--only { 318 | display: none; } 319 | .bootstrap-padding { 320 | padding: 15px; } 321 | .bootstrap-padding--bottom { 322 | padding-bottom: 15px; } 323 | .bootstrap-padding--left { 324 | padding-left: 15px; } 325 | .bootstrap-padding--right { 326 | padding-right: 15px; } 327 | .bootstrap-padding--top { 328 | padding-top: 15px; } 329 | .bootstrap-padding--horizontal { 330 | padding-left: 15px; 331 | padding-right: 15px; } 332 | .bootstrap-padding--vertical { 333 | padding-bottom: 15px; 334 | padding-top: 15px; } 335 | .bootstrap-grid { 336 | grid-template-columns: repeat(auto-fill, 8.33rem); } 337 | .bootstrap-grid.bootstrap-grid--fixed-columns { 338 | grid-template-columns: repeat(auto-fill, 8.33333rem); } 339 | .bootstrap-grid.bootstrap-grid--fluid-rows { 340 | grid-auto-rows: 8.33rem; } } 341 | -------------------------------------------------------------------------------- /examples/bootstrap/css-gridish/css/bootstrap-grid.min.css: -------------------------------------------------------------------------------- 1 | html{font-size:15px}body{margin:0}.bootstrap-container{box-sizing:border-box;margin-left:auto;margin-right:auto;max-width:100rem;overflow-x:hidden;width:100vw}.bootstrap-container--left{margin-left:0}.bootstrap-container--right{margin-right:0}.bootstrap-grid{align-items:flex-start;box-sizing:border-box;display:grid;flex-wrap:wrap;position:relative;grid-auto-rows:minmax(1rem,min-content);grid-template-columns:repeat(auto-fill,8.33vw)}.bootstrap-grid>*{box-sizing:border-box;grid-column:span 12}.bootstrap-grid>* :last-child,.bootstrap-grid>* :last-child>:last-child,.bootstrap-grid>* :last-child>:last-child>:last-child{margin-bottom:0}[class*=bootstrap-padding]{box-sizing:border-box}@supports (display:grid){.bootstrap-grid>*{height:100%}}:root{--bootstrap-height-1:1rem;--bootstrap-height-2:2rem;--bootstrap-height-3:3rem;--bootstrap-height-4:4rem;--bootstrap-height-5:5rem;--bootstrap-height-6:6rem;--bootstrap-height-7:7rem;--bootstrap-height-8:8rem;--bootstrap-height-9:9rem;--bootstrap-height-10:10rem;--bootstrap-height-11:11rem;--bootstrap-height-12:12rem;--bootstrap-height-13:13rem;--bootstrap-height-14:14rem;--bootstrap-height-15:15rem;--bootstrap-height-16:16rem;--bootstrap-height-17:17rem;--bootstrap-height-18:18rem;--bootstrap-height-19:19rem;--bootstrap-height-20:20rem;--bootstrap-height-21:21rem;--bootstrap-height-22:22rem;--bootstrap-height-23:23rem;--bootstrap-height-24:24rem;--bootstrap-height-25:25rem;--bootstrap-height-26:26rem;--bootstrap-height-27:27rem;--bootstrap-height-28:28rem;--bootstrap-height-29:29rem}.bootstrap-grid__height--sm--0{height:0;min-height:0}.bootstrap-grid__height--sm--1{grid-row:span 1}.bootstrap-grid__height--sm--2{grid-row:span 2}.bootstrap-grid__height--sm--3{grid-row:span 3}.bootstrap-grid__height--sm--4{grid-row:span 4}.bootstrap-grid__height--sm--5{grid-row:span 5}.bootstrap-grid__height--sm--6{grid-row:span 6}.bootstrap-grid__height--sm--7{grid-row:span 7}.bootstrap-grid__height--sm--8{grid-row:span 8}.bootstrap-grid__height--sm--9{grid-row:span 9}.bootstrap-grid__height--sm--10{grid-row:span 10}.bootstrap-grid__height--sm--11{grid-row:span 11}.bootstrap-grid__height--sm--12{grid-row:span 12}.bootstrap-grid__height--sm--13{grid-row:span 13}.bootstrap-grid__height--sm--14{grid-row:span 14}.bootstrap-grid__height--sm--15{grid-row:span 15}.bootstrap-grid__height--sm--16{grid-row:span 16}.bootstrap-grid__height--sm--17{grid-row:span 17}.bootstrap-grid__height--sm--18{grid-row:span 18}.bootstrap-grid__height--sm--19{grid-row:span 19}.bootstrap-grid__height--sm--20{grid-row:span 20}.bootstrap-grid__height--sm--21{grid-row:span 21}.bootstrap-grid__height--sm--22{grid-row:span 22}.bootstrap-grid__height--sm--23{grid-row:span 23}.bootstrap-grid__height--sm--24{grid-row:span 24}.bootstrap-grid__height--sm--25{grid-row:span 25}.bootstrap-grid__height--sm--26{grid-row:span 26}.bootstrap-grid__height--sm--27{grid-row:span 27}.bootstrap-grid__height--sm--28{grid-row:span 28}.bootstrap-grid__height--sm--29{grid-row:span 29}[class*=bootstrap-grid__col--sm--]{display:block}.bootstrap-grid__col--sm--0,.bootstrap-grid__col--sm--0--only{display:none}.bootstrap-padding{padding:15px}.bootstrap-padding--bottom{padding-bottom:15px}.bootstrap-padding--left{padding-left:15px}.bootstrap-padding--right{padding-right:15px}.bootstrap-padding--top{padding-top:15px}.bootstrap-padding--horizontal{padding-left:15px;padding-right:15px}.bootstrap-padding--vertical{padding-bottom:15px;padding-top:15px}.bootstrap-grid.bootstrap-grid--fixed-columns{grid-template-columns:repeat(auto-fill,3rem)}.bootstrap-grid.bootstrap-grid--fluid-rows{grid-auto-rows:8.33vw}.bootstrap-grid__col--sm--1,.bootstrap-grid__col--sm--1.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 1}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--1{grid-row:span 1}.bootstrap-grid__col--sm--2,.bootstrap-grid__col--sm--2.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 2}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--2{grid-row:span 2}.bootstrap-grid__col--sm--3,.bootstrap-grid__col--sm--3.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 3}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--3{grid-row:span 3}.bootstrap-grid__col--sm--4,.bootstrap-grid__col--sm--4.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 4}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--4{grid-row:span 4}.bootstrap-grid__col--sm--5,.bootstrap-grid__col--sm--5.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 5}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--5{grid-row:span 5}.bootstrap-grid__col--sm--6,.bootstrap-grid__col--sm--6.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 6}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--6{grid-row:span 6}.bootstrap-grid__col--sm--7,.bootstrap-grid__col--sm--7.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 7}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--7{grid-row:span 7}.bootstrap-grid__col--sm--8,.bootstrap-grid__col--sm--8.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 8}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--8{grid-row:span 8}.bootstrap-grid__col--sm--9,.bootstrap-grid__col--sm--9.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 9}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--9{grid-row:span 9}.bootstrap-grid__col--sm--10,.bootstrap-grid__col--sm--10.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 10}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--10{grid-row:span 10}.bootstrap-grid__col--sm--11,.bootstrap-grid__col--sm--11.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 11}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--11{grid-row:span 11}.bootstrap-grid__col--sm--12,.bootstrap-grid__col--sm--12.bootstrap-grid>:not([class*=bootstrap-grid__col]){grid-column:span 12}.bootstrap-grid--fluid-rows>.bootstrap-grid__height--sm--12{grid-row:span 12}@media screen and (min-width:100rem){.bootstrap-grid__col--sm--0--only,[class*=bootstrap-grid__col--xl--]{display:block}.bootstrap-grid__col--xl--0,.bootstrap-grid__col--xl--0--only{display:none}.bootstrap-padding{padding:15px}.bootstrap-padding--bottom{padding-bottom:15px}.bootstrap-padding--left{padding-left:15px}.bootstrap-padding--right{padding-right:15px}.bootstrap-padding--top{padding-top:15px}.bootstrap-padding--horizontal{padding-left:15px;padding-right:15px}.bootstrap-padding--vertical{padding-bottom:15px;padding-top:15px}.bootstrap-grid{grid-template-columns:repeat(auto-fill,8.33rem)}.bootstrap-grid.bootstrap-grid--fixed-columns{grid-template-columns:repeat(auto-fill,8.33333rem)}.bootstrap-grid.bootstrap-grid--fluid-rows{grid-auto-rows:8.33rem}} -------------------------------------------------------------------------------- /examples/bootstrap/css-gridish/scss/_core.scss: -------------------------------------------------------------------------------- 1 | @import "functions.scss"; 2 | @import "mixins.scss"; 3 | @import "variables.scss"; 4 | @import "utilities.scss"; 5 | 6 | html { 7 | font-size: map-get($grid-values, "rem") * 1px; 8 | } 9 | 10 | body { 11 | margin: 0; 12 | } 13 | 14 | .#{$prefix}-container { 15 | box-sizing: border-box; 16 | margin-left: auto; 17 | margin-right: auto; 18 | max-width: #{map-get($last, breakpoint)}rem; 19 | overflow-x: hidden; 20 | width: 100vw; 21 | } 22 | 23 | .#{$prefix}-container--left { 24 | margin-left: 0; 25 | } 26 | 27 | .#{$prefix}-container--right { 28 | margin-right: 0; 29 | } 30 | 31 | .#{$prefix}-grid { 32 | align-items: flex-start; 33 | box-sizing: border-box; 34 | @if $includeFlexFallback { 35 | display: flex; 36 | } 37 | display: grid; 38 | flex-wrap: wrap; 39 | position: relative; 40 | 41 | > * { 42 | box-sizing: border-box; 43 | 44 | :last-child, 45 | :last-child > :last-child, 46 | :last-child > :last-child > :last-child { 47 | margin-bottom: 0; 48 | } 49 | } 50 | } 51 | 52 | [class*="#{$prefix}-padding"] { 53 | box-sizing: border-box; 54 | } 55 | 56 | // Rules needed in legacy, but needed to change in CSS Grid 57 | @if $includeFlexFallback { 58 | .#{$prefix}-grid > * { 59 | width: 100%; 60 | } 61 | 62 | @supports (display: grid) { 63 | .#{$prefix}-grid { 64 | align-items: unset; 65 | } 66 | 67 | .#{$prefix}-grid > * { 68 | width: initial; 69 | } 70 | } 71 | } 72 | 73 | // Rules not needed in legacy, but needed in CSS Grid 74 | @supports (display: grid) { 75 | .#{$prefix}-grid > * { 76 | height: 100%; 77 | } 78 | } 79 | 80 | @include grid-legacy-wrapper($includeFlexFallback) { 81 | :root { 82 | @include grid-heights-fixed($rows); 83 | } 84 | } 85 | 86 | @each $name, $breakpoint in $allBreakpoints { 87 | @include media-query($name) { 88 | @if is-same-breakpoint($breakpoint, $last) == false { 89 | @include grid-legacy-heights($name); 90 | } 91 | @include grid-legacy-zeros($breakpoint, $name); 92 | @include grid-padding($breakpoint); 93 | @include grid($breakpoint, $name); 94 | @include grid-legacy-columns($breakpoint, $name); 95 | 96 | // Wrap all bleed/break classes and css variables in a CSS Grid support query 97 | @include grid-legacy-wrapper($includeFlexFallback) { 98 | @include grid-margin($breakpoint, $name); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /examples/bootstrap/css-gridish/scss/_functions.scss: -------------------------------------------------------------------------------- 1 | @import "sass-list-maps"; 2 | 3 | // Transform the gutter property into a padding property for web 4 | @function add-padding($breakpoints) { 5 | $cleanBreakpoints: (); 6 | @each $name, $breakpoint in $breakpoints { 7 | $cleanBreakpoints: map-merge( 8 | $cleanBreakpoints, 9 | ( 10 | $name: 11 | map-merge($breakpoint, (padding: map-get($breakpoint, gutter) / 2)) 12 | ) 13 | ); 14 | } 15 | 16 | @return $cleanBreakpoints; 17 | } 18 | 19 | // Merge standard and custom breakpoints into list 20 | @function all-breakpoints($breakpoints, $extraBreakpoints, $first, $last) { 21 | $allBreakpoints: $breakpoints; 22 | @each $currentBreakpoint in $extraBreakpoints { 23 | $extraBreakpointName: nth($currentBreakpoint, 1); 24 | $extraBreakpointWidth: nth($currentBreakpoint, 2); 25 | $found: false; 26 | $match: null; 27 | @each $majorBreakpoint in $breakpoints { 28 | @if $found == false { 29 | @if map-get(nth($majorBreakpoint, 2), breakpoint) > 30 | $extraBreakpointWidth 31 | { 32 | $found: true; 33 | } @else { 34 | $match: $majorBreakpoint; 35 | } 36 | } 37 | } 38 | @if $extraBreakpointWidth > map-get($last, breakpoint) { 39 | $match: ( 40 | last, 41 | $last 42 | ); 43 | } 44 | @if $extraBreakpointWidth < map-get($first, breakpoint) { 45 | $match: ( 46 | first, 47 | $first 48 | ); 49 | } 50 | 51 | $newBreakpoint: map-merge( 52 | nth($match, 2), 53 | (breakpoint: $extraBreakpointWidth) 54 | ); 55 | $currentBreakpoint: ( 56 | $extraBreakpointName: 57 | map-merge(nth($match, 2), (breakpoint: $extraBreakpointWidth)) 58 | ); 59 | $allBreakpoints: map-merge($allBreakpoints, $currentBreakpoint); 60 | } 61 | 62 | @return maps-sort($allBreakpoints, breakpoint); 63 | } 64 | 65 | @function is-same-breakpoint($a, $b) { 66 | @return map-get($a, breakpoint) == map-get($b, breakpoint); 67 | } 68 | 69 | /// Traverse maps and retrieve deeply nested values: https://css-tricks.com/snippets/sass/deep-getset-maps/ 70 | /// @author Hugo Giraudel 71 | /// @param {Map} $map A sass map and any number of keys. 72 | /// @param {*} $keys Nested values. 73 | /// @return Nested values or nested map. 74 | @function map-deep-get($map, $keys...) { 75 | @each $key in $keys { 76 | $map: map-get($map, $key); 77 | } 78 | @return $map; 79 | } 80 | 81 | // _decimal.scss | MIT License | gist.github.com/terkel/4373420 82 | @function round-decimal($number, $digits: 0, $mode: round) { 83 | $n: 1; 84 | // $number must be a number 85 | @if type-of($number) != number { 86 | @warn "#{ $number } is not a number."; 87 | @return $number; 88 | } 89 | // $digits must be a unitless number 90 | @if type-of($digits) != number { 91 | @warn "#{ $digits } is not a number."; 92 | @return $number; 93 | } @else if not unitless($digits) { 94 | @warn "#{ $digits } has a unit."; 95 | @return $number; 96 | } 97 | @for $i from 1 through $digits { 98 | $n: $n * 10; 99 | } 100 | @if $mode == round { 101 | @return round($number * $n) / $n; 102 | } @else if $mode == ceil { 103 | @return ceil($number * $n) / $n; 104 | } @else if $mode == floor { 105 | @return floor($number * $n) / $n; 106 | } @else { 107 | @warn "#{ $mode } is undefined keyword."; 108 | @return $number; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /examples/bootstrap/css-gridish/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Set the width of a grid’s column 2 | @mixin grid($breakpoint, $breakpointName) { 3 | @if (map-get($breakpoint, columns) != null) { 4 | $columnSize: get-fluid-size($breakpointName, 1); 5 | 6 | .#{$prefix}-grid { 7 | @if is-same-breakpoint($breakpoint, $first) { 8 | grid-auto-rows: minmax($rowHeight * 1rem, min-content); 9 | } 10 | grid-template-columns: repeat(auto-fill, $columnSize); 11 | 12 | &.#{$prefix}-grid--fixed-columns { 13 | grid-template-columns: repeat( 14 | auto-fill, 15 | map-get($breakpoint, breakpoint) * 16 | 1rem / 17 | map-get($breakpoint, columns) 18 | ); 19 | } 20 | 21 | &.#{$prefix}-grid--fluid-rows { 22 | grid-auto-rows: $columnSize; 23 | } 24 | 25 | @if is-same-breakpoint($breakpoint, $last) == false { 26 | > * { 27 | grid-column: span #{map-get($breakpoint, columns)}; 28 | } 29 | } 30 | } 31 | } 32 | } 33 | 34 | // Generate variables for commonly used rows 35 | @mixin grid-heights-fixed($rows) { 36 | @for $i from 1 to $rows { 37 | --#{$prefix}-height-#{$i}: get-fixed-size($i); 38 | } 39 | } 40 | 41 | // Set the width of a grid’s column for legacy grid 42 | @mixin grid-legacy-columns($breakpoint, $name) { 43 | // Do not make class if last media query 44 | @if is-same-breakpoint($breakpoint, $last) == false { 45 | // Loop each breakpoint to insert previous breakpoint classes inside this breakpoint’s media query 46 | // Ex: Make sure .yourPrefix-grid__col--sm--2 has correct sizes in the lg media query 47 | @each $currentName, $currentBreakpoint in $allBreakpoints { 48 | // Check if current breakpoint is not bigger than current media query 49 | @if map-get($breakpoint, breakpoint) >= 50 | map-get($currentBreakpoint, breakpoint) 51 | { 52 | // Loop each column in current breakpoint for new class 53 | // Ex: .yourPrefix-grid__col--sm--1, .yourPrefix-grid__col--sm--2, etc. 54 | @for $i from 1 through map-get($currentBreakpoint, columns) { 55 | $columnMultiplier: $i * 56 | map-get($breakpoint, columns) / 57 | map-get($currentBreakpoint, columns); 58 | $columnSize: get-fluid-size($name, $columnMultiplier); 59 | 60 | $isSecondToLast: is-same-breakpoint( 61 | $breakpoint, 62 | nth(nth($allBreakpoints, length($allBreakpoints) - 1), 2) 63 | ); 64 | 65 | $maxColumnSize: get-fluid-size( 66 | nth(nth($allBreakpoints, length($allBreakpoints)), 1), 67 | $columnMultiplier 68 | ); 69 | 70 | .#{$prefix}-grid__col--#{$currentName}--#{$i} { 71 | @if $includeFlexFallback { 72 | // If second-to-last media query, apply max-width instead of remaking classes in last media query 73 | @if $isSecondToLast { 74 | max-width: $maxColumnSize; 75 | } 76 | width: $columnSize; 77 | } 78 | grid-column: span #{$columnMultiplier}; 79 | 80 | @if is-same-breakpoint($breakpoint, $last) == false { 81 | &.#{$prefix}-grid > *:not([class*="#{$prefix}-grid__col"]) { 82 | grid-column: span #{$i}; 83 | } 84 | } 85 | } 86 | 87 | .#{$prefix}-grid--fluid-rows 88 | > .#{$prefix}-grid__height--#{$currentName}--#{$i} { 89 | grid-row: span $i; 90 | @if $includeFlexFallback { 91 | height: $columnSize; 92 | min-height: $columnSize; 93 | // If second-to-last media query, apply max-height instead of remaking classes in last media query 94 | @if $isSecondToLast { 95 | max-height: $maxColumnSize; 96 | } 97 | } 98 | } 99 | } 100 | } 101 | } 102 | } 103 | 104 | @if $includeFlexFallback { 105 | @if is-same-breakpoint($breakpoint, $last) { 106 | [class*="#{$prefix}-grid__col--"] { 107 | min-width: 0; 108 | } 109 | } 110 | } 111 | } 112 | 113 | // Set the height of an item for legacy grid 114 | @mixin grid-legacy-heights($name) { 115 | .#{$prefix}-grid__height--#{$name}--0 { 116 | height: 0; 117 | min-height: 0; 118 | } 119 | @for $i from 1 to $rows { 120 | .#{$prefix}-grid__height--#{$name}--#{$i} { 121 | grid-row: span $i; 122 | @if $includeFlexFallback { 123 | height: get-fixed-size($i); 124 | min-height: get-fixed-size($i); 125 | } 126 | } 127 | } 128 | } 129 | 130 | // If we need legacy grid, wrap this content in support tag 131 | @mixin grid-legacy-wrapper($includeFlexFallback) { 132 | @if $includeFlexFallback { 133 | @supports (display: grid) { 134 | @content; 135 | } 136 | } @else { 137 | @content; 138 | } 139 | } 140 | 141 | // Generate all classes for 0 and 0-only displaying, including custom breakpoints if they exist 142 | @mixin grid-legacy-zeros($breakpoint, $name) { 143 | // Undo previous breakpoint’s 0--only class 144 | @for $i from length($allBreakpoints) * -1 through -1 { 145 | $currentBreakpoint: nth($allBreakpoints, $i); 146 | @if map-get(nth($currentBreakpoint, 2), breakpoint) < 147 | map-get($breakpoint, breakpoint) 148 | { 149 | .#{$prefix}-grid__col--#{nth($currentBreakpoint, 1)}--0--only { 150 | display: block; 151 | } 152 | } 153 | } 154 | 155 | [class*="#{$prefix}-grid__col--#{$name}--"] { 156 | display: block; 157 | } 158 | 159 | .#{$prefix}-grid__col--#{$name}--0, 160 | .#{$prefix}-grid__col--#{$name}--0--only { 161 | display: none; 162 | } 163 | } 164 | 165 | // Set the width of a grid’s margin 166 | // and allow for a child to break out of the grid’s margin 167 | @mixin grid-margin($breakpoint, $name) { 168 | $nameToUse: $name; 169 | $margin: #{map-get($breakpoint, margin)}; 170 | $padding: #{map-get($breakpoint, padding)}; 171 | 172 | // If last breakpoint, we use the previous breakpoint name 173 | // to treat the last breakpoint as the max-width of the previous breakpoint 174 | @if is-same-breakpoint($breakpoint, $last) == true { 175 | $previousBreakpoint: nth( 176 | $allBreakpoints, 177 | index(map-keys($allBreakpoints), $name) - 1 178 | ); 179 | $nameToUse: nth($previousBreakpoint, 1); 180 | } 181 | 182 | // Undo previous breakpoint’s bleeds and breaks 183 | @if is-same-breakpoint($breakpoint, $first) == 184 | false and 185 | is-same-breakpoint($breakpoint, $last) == 186 | false 187 | { 188 | $previousBreakpoint: nth( 189 | $allBreakpoints, 190 | index(map-keys($allBreakpoints), $name) - 1 191 | ); 192 | $previousName: nth($previousBreakpoint, 1); 193 | $previousMargin: map-get(nth($previousBreakpoint, 2), margin); 194 | 195 | @if $previousMargin != 196 | null and 197 | $previousMargin != 198 | 0 and 199 | $previousMargin != 200 | "0" 201 | { 202 | [class^="#{$prefix}-container__bleed--#{$previousName}"], 203 | [class^="#{$prefix}-container__break--#{$previousName}"] { 204 | margin-left: 0; 205 | margin-right: 0; 206 | padding-left: 0; 207 | padding-right: 0; 208 | 209 | &[class^="#{$prefix}-padding"] { 210 | padding-left: $padding; 211 | padding-right: $padding; 212 | } 213 | } 214 | } 215 | } 216 | 217 | @if $margin != null and $margin != 0 and $margin != "0" { 218 | $marginPlusPadding: calc(#{$margin} + #{$padding}); 219 | @if $margin == "0" and $padding == "0" { 220 | $marginPlusPadding: 0; 221 | } @else if $margin == "0" { 222 | $marginPlusPadding: $padding; 223 | } @else if $padding == "0" { 224 | $marginPlusPadding: $margin; 225 | } 226 | 227 | .#{$prefix}-container { 228 | margin-left: auto; 229 | margin-right: auto; 230 | padding-left: $margin; 231 | padding-right: $margin; 232 | } 233 | 234 | .#{$prefix}-container--left { 235 | margin-left: 0; 236 | } 237 | 238 | .#{$prefix}-container--right { 239 | margin-right: 0; 240 | } 241 | 242 | .#{$prefix}-container__bleed--#{$nameToUse}, 243 | .#{$prefix}-container__bleed--#{$nameToUse}--left, 244 | .#{$prefix}-container__break--#{$nameToUse}, 245 | .#{$prefix}-container__break--#{$nameToUse}--left { 246 | margin-left: -#{$margin}; 247 | } 248 | 249 | .#{$prefix}-container__bleed--#{$nameToUse}, 250 | .#{$prefix}-container__bleed--#{$nameToUse}--right, 251 | .#{$prefix}-container__break--#{$nameToUse}, 252 | .#{$prefix}-container__break--#{$nameToUse}--right { 253 | margin-right: -#{$margin}; 254 | } 255 | 256 | .#{$prefix}-container__bleed--#{$nameToUse}, 257 | .#{$prefix}-container__bleed--#{$nameToUse}--left { 258 | padding-left: $margin; 259 | 260 | &.#{$prefix}-padding, 261 | &.#{$prefix}-padding--horizontal, 262 | &.#{$prefix}-padding--left { 263 | padding-left: $marginPlusPadding; 264 | } 265 | } 266 | 267 | .#{$prefix}-container__bleed--#{$nameToUse}, 268 | .#{$prefix}-container__bleed--#{$nameToUse}--right { 269 | padding-right: $margin; 270 | 271 | &.#{$prefix}-padding, 272 | &.#{$prefix}-padding--horizontal, 273 | &.#{$prefix}-padding--right { 274 | padding-right: $marginPlusPadding; 275 | } 276 | } 277 | } 278 | } 279 | 280 | // Classnames for different padding options 281 | @mixin grid-padding($breakpoint) { 282 | @if (map-get($breakpoint, padding) != null) { 283 | $padding: map-get($breakpoint, padding); 284 | 285 | .#{$prefix}-padding { 286 | padding: $padding; 287 | } 288 | 289 | .#{$prefix}-padding--bottom { 290 | padding-bottom: $padding; 291 | } 292 | 293 | .#{$prefix}-padding--left { 294 | padding-left: $padding; 295 | } 296 | 297 | .#{$prefix}-padding--right { 298 | padding-right: $padding; 299 | } 300 | 301 | .#{$prefix}-padding--top { 302 | padding-top: $padding; 303 | } 304 | 305 | .#{$prefix}-padding--horizontal { 306 | padding-left: $padding; 307 | padding-right: $padding; 308 | } 309 | 310 | .#{$prefix}-padding--vertical { 311 | padding-bottom: $padding; 312 | padding-top: $padding; 313 | } 314 | } 315 | } 316 | -------------------------------------------------------------------------------- /examples/bootstrap/css-gridish/scss/_sass-list-maps.scss: -------------------------------------------------------------------------------- 1 | /// _ 2 | /// | | 3 | /// ___ __ _ ___ ___ ______ _ __ ___ __ _ _ __ ___ ______ _ __ | |_ _ ___ 4 | /// / __|/ _` / __/ __|______| '_ ` _ \ / _` | '_ \/ __|______| '_ \| | | | / __| 5 | /// \__ \ (_| \__ \__ \ | | | | | | (_| | |_) \__ \ | |_) | | |_| \__ \ 6 | /// |___/\__,_|___/___/ |_| |_| |_|\__,_| .__/|___/ | .__/|_|\__,_|___/ 7 | /// | | | | 8 | /// |_| |_| 9 | /// Sass Maps Plus 0.9.2 10 | /// Advanced map and list-map manipulation for all versions of Sass 11 | /// MIT License 12 | /// @author Lu Nelson 13 | 14 | /// Global sort direction: either `asc` or `desc` 15 | /// @access public 16 | /// @group map-lists/map-maps 17 | $maps-sort-dir: "asc"; 18 | 19 | /// get value at nested or 'deep' key, per $keys list 20 | /// @access public 21 | /// @group maps 22 | /// @param {Map} $map - map 23 | /// @param {Arglist} $keys - nested keys 24 | /// @return {*} 25 | @function map-get-nested($map, $keys...) { 26 | @if length($map) == 0 { 27 | @return null; 28 | } 29 | @each $key in $keys { 30 | @if type-of($map) != "map" { 31 | @return $map; 32 | } 33 | $map: map-get($map, $key); 34 | } 35 | @return $map; 36 | } 37 | 38 | /// Sort a list-of-maps or map-of-maps, based on value at key(s) in maps 39 | /// @access public 40 | /// @group map-lists/map-maps 41 | /// @param {Map|List} $maps - Map of maps, or List of maps, to sort 42 | /// @param {Arglist} $keys - Chain of keys to the value that will be sorted for 43 | /// @return {Map|List} 44 | /// @require {function} map-get-nested 45 | @function maps-sort($maps, $keys...) { 46 | @if length($keys) == 0 { 47 | @return $maps; 48 | } 49 | 50 | @if length($maps) > 1 { 51 | $less: (); 52 | $equal: (); 53 | $greater: (); 54 | 55 | $map-of-maps: type-of($maps) == "map"; 56 | 57 | @if $map-of-maps { 58 | $seed-map: nth(nth($maps, ceil(length($maps) / 2)), 2); 59 | 60 | $seed-value: map-get-nested($seed-map, $keys...); 61 | 62 | // TODO: add code to handle case of non-number values (warn and return $maps) 63 | 64 | @each $key, $map in $maps { 65 | $curr-value: map-get-nested($map, $keys...); 66 | 67 | @if $curr-value == $seed-value { 68 | $equal: map-merge($equal, ($key: $map)); 69 | } @else if $curr-value < $seed-value { 70 | @if $maps-sort-dir == "asc" { 71 | $less: map-merge($less, ($key: $map)); 72 | } @else { 73 | $greater: map-merge($greater, ($key: $map)); 74 | } 75 | } @else { 76 | @if $maps-sort-dir == "asc" { 77 | $greater: map-merge($greater, ($key: $map)); 78 | } @else { 79 | $less: map-merge($less, ($key: $map)); 80 | } 81 | } 82 | } 83 | 84 | $less: maps-sort($less, $keys...); 85 | $greater: maps-sort($greater, $keys...); 86 | 87 | @return map-merge(map-merge($less, $equal), $greater); 88 | } @else { 89 | $seed-map: nth($maps, ceil(length($maps) / 2)); 90 | 91 | $seed-value: map-get-nested($seed-map, $keys...); 92 | 93 | @each $map in $maps { 94 | $curr-value: map-get-nested($map, $keys...); 95 | 96 | @if $curr-value == $seed-value { 97 | $equal: append($equal, $map); 98 | } @else if $curr-value < $seed-value { 99 | @if $maps-sort-dir == "asc" { 100 | $less: append($less, $map); 101 | } @else { 102 | $greater: append($greater, $map); 103 | } 104 | } @else { 105 | @if $maps-sort-dir == "asc" { 106 | $greater: append($greater, $map); 107 | } @else { 108 | $less: append($less, $map); 109 | } 110 | } 111 | } 112 | 113 | $less: maps-sort($less, $keys...); 114 | $greater: maps-sort($greater, $keys...); 115 | 116 | @return join(join($less, $equal), $greater); 117 | } 118 | } 119 | 120 | @return $maps; 121 | } 122 | -------------------------------------------------------------------------------- /examples/bootstrap/css-gridish/scss/_utilities.scss: -------------------------------------------------------------------------------- 1 | @import "functions"; 2 | @import "values"; 3 | @import "variables"; 4 | 5 | /// Function returns the value for a given breakpoint. 6 | /// @param {String} $breakpointName Breakpoint name. 7 | /// @return {Length} The breakpoint value in rems. 8 | @function get-breakpoint-value($breakpointName) { 9 | $breakpointValue: map-deep-get( 10 | $breakpointsAndArtboards, 11 | $breakpointName, 12 | "breakpoint" 13 | ); 14 | 15 | @return $breakpointValue * 1rem; 16 | } 17 | 18 | /// Returns a calc() expression that represents a fluid width at a given breakpoint. 19 | /// @param {String} $breakpointName A valid breakpoint. 20 | /// @param {Number} $columnSpan The number of columns to span across. 21 | /// @return {Length} A calc() expression representing fluid width. 22 | /// @example scss 23 | /// button { 24 | /// @include media-query('sm') { 25 | /// max-width: get-fluid-size('sm', 1); 26 | /// } 27 | /// } 28 | /// @output css 29 | /// @media screen and (min-width: 20rem) { 30 | /// button { 31 | /// max-width: 25vw; 32 | /// } 33 | /// } 34 | @function get-fluid-size($breakpointName, $columnSpan) { 35 | $breakpoint: map-get($breakpointsAndArtboards, $breakpointName); 36 | 37 | @if ($breakpoint == null or type-of($breakpoint) != "map") { 38 | @error "The provided breakpoint `#{$breakpointName}` is not a valid breakpoint found in breakpoints or extraArtboards in $grid-values. Please double-check your grid configuration."; 39 | } 40 | 41 | $columnTotal: map-get($breakpoint, columns); 42 | $margin: map-get($breakpoint, margin); 43 | 44 | @if ($columnTotal == null or type-of($columnTotal) != "number") { 45 | @error "The provided breakpoint `#{$breakpointName}` needs to have a total number of columns set in $grid-values. Please double-check your grid configuration."; 46 | } 47 | 48 | @if ($columnSpan == null or type-of($columnSpan) != "number") { 49 | @error "The number of columns to span for the breakpoint `#{$breakpointName}` must be a valid number. The provided column span value `#{$columnSpan}` is not a number"; 50 | } 51 | 52 | @if ($columnSpan > $columnTotal or $columnSpan <= 0) { 53 | @error "The number of columns to span for the breakpoint `#{$breakpointName}` must be greater than 0 and less than or equal to the total number of columns for this breakpoint. The provided column value `#{$columnSpan}` does not meet this criteria"; 54 | } 55 | 56 | $container: 100vw; 57 | // Last breakpoint is a max-width and should be a fixed number 58 | @if is-same-breakpoint($breakpoint, $last) { 59 | $container: map-get($breakpoint, breakpoint) * 1rem; 60 | } 61 | 62 | $multiplier: round-decimal($columnSpan / $columnTotal, 4, floor); 63 | 64 | // For IE, we can't have a 0 in the $fluidWidth calc(). 65 | @if ($margin == 0) { 66 | @return $container * $multiplier; 67 | } 68 | 69 | @return calc((#{$container} - #{$margin * 2}) * #{$multiplier}); 70 | } 71 | 72 | /// Function gets a calculated rem value for a fixed size. 73 | /// @param {Number} $unitQuantity Fixed nondimensional units. 74 | /// @return {Length} A calculated rem value. 75 | /// @example scss 76 | /// button { 77 | /// @include media-query('sm') { 78 | /// max-width: get-fixed-size(10); 79 | /// } 80 | /// } 81 | /// @output css 82 | /// @media screen and (min-width: 20rem) { 83 | /// button { 84 | /// max-width: 5rem; 85 | /// } 86 | /// } 87 | @function get-fixed-size($unitQuantity) { 88 | // Derive the base unit from the current row height of the grid 89 | $fixedUnit: map-get($grid-values, "rowHeight"); 90 | 91 | @if ($fixedUnit == null or type-of($fixedUnit) != "number") { 92 | @error "The rowHeight in $grid-values needs be a valid number. Please check your grid configuration."; 93 | } 94 | 95 | @if ($unitQuantity == null or type-of($unitQuantity) != "number") { 96 | @error "The provided fixed value `#{$unitQuantity}` to get-fixed-size() needs to be a valid number greater than 0."; 97 | } 98 | 99 | @return $unitQuantity * $fixedUnit * 1rem; 100 | } 101 | 102 | /// Utility for declaring mobile-first media queries. 103 | /// @param {String} $breakpointName The name of the breakpoint to set its width value to media query. 104 | @mixin media-query($breakpointName) { 105 | $breakpointValue: get-breakpoint-value($breakpointName); 106 | @if $breakpointValue == map-get($first, breakpoint) { 107 | @content; 108 | } @else { 109 | @media screen and (min-width: #{$breakpointValue}) { 110 | @content; 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /examples/bootstrap/css-gridish/scss/_values.scss: -------------------------------------------------------------------------------- 1 | $grid-values: ( 2 | prefix: bootstrap, 3 | breakpoints: ( 4 | sm: ( 5 | breakpoint: 36, 6 | columns: 12, 7 | gutter: 30px, 8 | margin: 0 9 | ), 10 | xl: ( 11 | breakpoint: 100, 12 | columns: 12, 13 | gutter: 30px, 14 | margin: 0 15 | ) 16 | ), 17 | extraArtboards: ( 18 | md: 51, 19 | lg: 66 20 | ), 21 | rem: 15, 22 | rowHeight: 1, 23 | rows: 30, 24 | paths: null 25 | ); -------------------------------------------------------------------------------- /examples/bootstrap/css-gridish/scss/_variables.scss: -------------------------------------------------------------------------------- 1 | @import "values"; 2 | 3 | $prefix: gridish !default; 4 | @if map-get($grid-values, "prefix") and $prefix == "gridish" { 5 | $prefix: map-get($grid-values, "prefix"); 6 | } 7 | $extraBreakpoints: () !default; 8 | $breakpoints: add-padding(map-get($grid-values, "breakpoints")); 9 | $first: nth(nth($breakpoints, 1), 2); 10 | $last: nth(nth($breakpoints, -1), 2); 11 | $includeFlexFallback: false !default; 12 | $rowHeight: map-get($grid-values, "rowHeight"); 13 | $rows: map-get($grid-values, "rows"); 14 | $extraArtboards: map-get($grid-values, "extraArtboards"); 15 | $allBreakpoints: all-breakpoints( 16 | $breakpoints, 17 | $extraBreakpoints, 18 | $first, 19 | $last 20 | ); 21 | $breakpointsAndArtboards: all-breakpoints( 22 | $breakpoints, 23 | $extraArtboards, 24 | $first, 25 | $last 26 | ); 27 | -------------------------------------------------------------------------------- /examples/bootstrap/css-gridish/scss/bootstrap-grid-legacy.scss: -------------------------------------------------------------------------------- 1 | $includeFlexFallback: true; 2 | @import "core.scss"; 3 | 4 | @supports (display: grid) { 5 | .#{$prefix}-grid > *, 6 | .#{$prefix}-grid > [class*="#{$prefix}-grid__col--"] { 7 | min-width: initial; 8 | max-width: initial; 9 | width: initial; 10 | 11 | &.#{$prefix}-grid { 12 | display: grid; 13 | } 14 | } 15 | 16 | .#{$prefix}-grid > [class*="#{$prefix}-grid__height--"] { 17 | height: unset; 18 | max-height: unset; 19 | min-height: initial; 20 | } 21 | } 22 | 23 | .#{$prefix}-grid > script { 24 | display: none; 25 | } 26 | -------------------------------------------------------------------------------- /examples/bootstrap/css-gridish/scss/bootstrap-grid.scss: -------------------------------------------------------------------------------- 1 | @import "core.scss"; 2 | -------------------------------------------------------------------------------- /examples/bootstrap/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 32 | 33 | 34 | 35 |
36 |

CSS Gridish

37 |

Bootstrap Example

38 | 39 | 40 |
41 | 42 | 43 |
44 |
45 |

Learn more about 46 | CSS Gridish. 47 |

48 |

Also check out our examples of CSS Gridish making grid code for 49 | Carbon and 50 | Material. 51 |

52 |
53 | 54 | 79 | 80 | -------------------------------------------------------------------------------- /examples/bootstrap/intro.md: -------------------------------------------------------------------------------- 1 | # Bootstrap Design Grid 2 | 3 | An example of [CSS Gridish](../../../README.md) generating CSS Grid code, fallback flexbox code, dev documentation, and Sketch files based on the [Bootstrap v4 grid.](https://github.com/twbs/bootstrap/blob/v4-dev/scss/_variables.scss#L168-174) 4 | -------------------------------------------------------------------------------- /examples/bootstrap/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-gridish-example-carbon", 3 | "version": "0.0.1", 4 | "engines": { 5 | "node": ">=8.2.0" 6 | }, 7 | "repository": { 8 | "type": "git", 9 | "url": "git@ibm.com:ibm/css-gridish.git" 10 | }, 11 | "author": "James Y. Rauhut ", 12 | "license": "Apache-2.0", 13 | "scripts": { 14 | "build": "node ../../bin/index.js", 15 | "test": "true" 16 | }, 17 | "dependencies": {} 18 | } 19 | -------------------------------------------------------------------------------- /examples/bootstrap/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/carbon/README.md: -------------------------------------------------------------------------------- 1 | # Carbon Design Grid 2 | 3 | [View a random layout with this grid.](https://ibm.github.io/css-gridish/examples/carbon/index.html) 4 | 5 | An example of [CSS Gridish](../../README.md) generating CSS Grid code, fallback flexbox code, dev documentation, and Sketch files based on the [Carbon Design System grid.](http://carbondesignsystem.com/style/grid/design) 6 | 7 | Check out everything CSS Gridish made based off of the [config file](./css-gridish.json) in the [css-gridish folder.](./css-gridish/) 8 | -------------------------------------------------------------------------------- /examples/carbon/css-gridish.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "bx", 3 | "breakpoints": { 4 | "sm": { 5 | "breakpoint": 20, 6 | "columns": 12, 7 | "gutter": "1.250rem", 8 | "margin": "5vw" 9 | }, 10 | "xxl": { 11 | "breakpoint": 100, 12 | "columns": 12, 13 | "gutter": "1.250rem", 14 | "margin": "5vw" 15 | } 16 | }, 17 | "extraArtboards": { 18 | "md": 48, 19 | "lg": 62, 20 | "xl": 75 21 | }, 22 | "rem": 16, 23 | "rowHeight": 0.5, 24 | "rows": 30, 25 | "paths": { 26 | "intro": "intro.md" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/carbon/css-gridish/bx-grid.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/css-gridish/c5f16a541df485fa833f8f50299bd6a3f290a142/examples/carbon/css-gridish/bx-grid.sketch -------------------------------------------------------------------------------- /examples/carbon/css-gridish/css/bx-grid-legacy.min.css: -------------------------------------------------------------------------------- 1 | html{font-size:16px}body{margin:0}.bx-container{box-sizing:border-box;margin-left:auto;margin-right:auto;max-width:100rem;overflow-x:hidden;width:100vw}.bx-container--left{margin-left:0}.bx-container--right{margin-right:0}.bx-grid{align-items:flex-start;box-sizing:border-box;display:flex;display:grid;flex-wrap:wrap;position:relative;grid-auto-rows:minmax(.5rem,min-content);grid-template-columns:repeat(auto-fill,calc((100vw - 10vw) * .0833))}.bx-grid>*{box-sizing:border-box;width:100%;grid-column:span 12}.bx-grid>* :last-child,.bx-grid>* :last-child>:last-child,.bx-grid>* :last-child>:last-child>:last-child{margin-bottom:0}[class*=bx-padding]{box-sizing:border-box}@supports (display:grid){.bx-grid{align-items:unset}.bx-grid>*{width:initial;height:100%}:root{--bx-height-1:0.5rem;--bx-height-2:1rem;--bx-height-3:1.5rem;--bx-height-4:2rem;--bx-height-5:2.5rem;--bx-height-6:3rem;--bx-height-7:3.5rem;--bx-height-8:4rem;--bx-height-9:4.5rem;--bx-height-10:5rem;--bx-height-11:5.5rem;--bx-height-12:6rem;--bx-height-13:6.5rem;--bx-height-14:7rem;--bx-height-15:7.5rem;--bx-height-16:8rem;--bx-height-17:8.5rem;--bx-height-18:9rem;--bx-height-19:9.5rem;--bx-height-20:10rem;--bx-height-21:10.5rem;--bx-height-22:11rem;--bx-height-23:11.5rem;--bx-height-24:12rem;--bx-height-25:12.5rem;--bx-height-26:13rem;--bx-height-27:13.5rem;--bx-height-28:14rem;--bx-height-29:14.5rem}}.bx-grid__height--sm--0{height:0;min-height:0}.bx-grid__height--sm--1{grid-row:span 1;height:.5rem;min-height:.5rem}.bx-grid__height--sm--2{grid-row:span 2;height:1rem;min-height:1rem}.bx-grid__height--sm--3{grid-row:span 3;height:1.5rem;min-height:1.5rem}.bx-grid__height--sm--4{grid-row:span 4;height:2rem;min-height:2rem}.bx-grid__height--sm--5{grid-row:span 5;height:2.5rem;min-height:2.5rem}.bx-grid__height--sm--6{grid-row:span 6;height:3rem;min-height:3rem}.bx-grid__height--sm--7{grid-row:span 7;height:3.5rem;min-height:3.5rem}.bx-grid__height--sm--8{grid-row:span 8;height:4rem;min-height:4rem}.bx-grid__height--sm--9{grid-row:span 9;height:4.5rem;min-height:4.5rem}.bx-grid__height--sm--10{grid-row:span 10;height:5rem;min-height:5rem}.bx-grid__height--sm--11{grid-row:span 11;height:5.5rem;min-height:5.5rem}.bx-grid__height--sm--12{grid-row:span 12;height:6rem;min-height:6rem}.bx-grid__height--sm--13{grid-row:span 13;height:6.5rem;min-height:6.5rem}.bx-grid__height--sm--14{grid-row:span 14;height:7rem;min-height:7rem}.bx-grid__height--sm--15{grid-row:span 15;height:7.5rem;min-height:7.5rem}.bx-grid__height--sm--16{grid-row:span 16;height:8rem;min-height:8rem}.bx-grid__height--sm--17{grid-row:span 17;height:8.5rem;min-height:8.5rem}.bx-grid__height--sm--18{grid-row:span 18;height:9rem;min-height:9rem}.bx-grid__height--sm--19{grid-row:span 19;height:9.5rem;min-height:9.5rem}.bx-grid__height--sm--20{grid-row:span 20;height:10rem;min-height:10rem}.bx-grid__height--sm--21{grid-row:span 21;height:10.5rem;min-height:10.5rem}.bx-grid__height--sm--22{grid-row:span 22;height:11rem;min-height:11rem}.bx-grid__height--sm--23{grid-row:span 23;height:11.5rem;min-height:11.5rem}.bx-grid__height--sm--24{grid-row:span 24;height:12rem;min-height:12rem}.bx-grid__height--sm--25{grid-row:span 25;height:12.5rem;min-height:12.5rem}.bx-grid__height--sm--26{grid-row:span 26;height:13rem;min-height:13rem}.bx-grid__height--sm--27{grid-row:span 27;height:13.5rem;min-height:13.5rem}.bx-grid__height--sm--28{grid-row:span 28;height:14rem;min-height:14rem}.bx-grid__height--sm--29{grid-row:span 29;height:14.5rem;min-height:14.5rem}[class*=bx-grid__col--sm--]{display:block}.bx-grid__col--sm--0,.bx-grid__col--sm--0--only{display:none}.bx-padding{padding:.625rem}.bx-padding--bottom{padding-bottom:.625rem}.bx-padding--left{padding-left:.625rem}.bx-padding--right{padding-right:.625rem}.bx-padding--top{padding-top:.625rem}.bx-padding--horizontal{padding-left:.625rem;padding-right:.625rem}.bx-padding--vertical{padding-bottom:.625rem;padding-top:.625rem}.bx-grid.bx-grid--fixed-columns{grid-template-columns:repeat(auto-fill,1.66667rem)}.bx-grid.bx-grid--fluid-rows{grid-auto-rows:calc((100vw - 10vw) * .0833)}.bx-grid__col--sm--1{max-width:calc((100rem - 10vw) * .0833);width:calc((100vw - 10vw) * .0833);grid-column:span 1}.bx-grid__col--sm--1.bx-grid>:not([class*=bx-grid__col]){grid-column:span 1}.bx-grid--fluid-rows>.bx-grid__height--sm--1{grid-row:span 1;height:calc((100vw - 10vw) * .0833);min-height:calc((100vw - 10vw) * .0833);max-height:calc((100rem - 10vw) * .0833)}.bx-grid__col--sm--2{max-width:calc((100rem - 10vw) * .1666);width:calc((100vw - 10vw) * .1666);grid-column:span 2}.bx-grid__col--sm--2.bx-grid>:not([class*=bx-grid__col]){grid-column:span 2}.bx-grid--fluid-rows>.bx-grid__height--sm--2{grid-row:span 2;height:calc((100vw - 10vw) * .1666);min-height:calc((100vw - 10vw) * .1666);max-height:calc((100rem - 10vw) * .1666)}.bx-grid__col--sm--3{max-width:calc((100rem - 10vw) * .25);width:calc((100vw - 10vw) * .25);grid-column:span 3}.bx-grid__col--sm--3.bx-grid>:not([class*=bx-grid__col]){grid-column:span 3}.bx-grid--fluid-rows>.bx-grid__height--sm--3{grid-row:span 3;height:calc((100vw - 10vw) * .25);min-height:calc((100vw - 10vw) * .25);max-height:calc((100rem - 10vw) * .25)}.bx-grid__col--sm--4{max-width:calc((100rem - 10vw) * .3333);width:calc((100vw - 10vw) * .3333);grid-column:span 4}.bx-grid__col--sm--4.bx-grid>:not([class*=bx-grid__col]){grid-column:span 4}.bx-grid--fluid-rows>.bx-grid__height--sm--4{grid-row:span 4;height:calc((100vw - 10vw) * .3333);min-height:calc((100vw - 10vw) * .3333);max-height:calc((100rem - 10vw) * .3333)}.bx-grid__col--sm--5{max-width:calc((100rem - 10vw) * .4166);width:calc((100vw - 10vw) * .4166);grid-column:span 5}.bx-grid__col--sm--5.bx-grid>:not([class*=bx-grid__col]){grid-column:span 5}.bx-grid--fluid-rows>.bx-grid__height--sm--5{grid-row:span 5;height:calc((100vw - 10vw) * .4166);min-height:calc((100vw - 10vw) * .4166);max-height:calc((100rem - 10vw) * .4166)}.bx-grid__col--sm--6{max-width:calc((100rem - 10vw) * .5);width:calc((100vw - 10vw) * .5);grid-column:span 6}.bx-grid__col--sm--6.bx-grid>:not([class*=bx-grid__col]){grid-column:span 6}.bx-grid--fluid-rows>.bx-grid__height--sm--6{grid-row:span 6;height:calc((100vw - 10vw) * .5);min-height:calc((100vw - 10vw) * .5);max-height:calc((100rem - 10vw) * .5)}.bx-grid__col--sm--7{max-width:calc((100rem - 10vw) * .5833);width:calc((100vw - 10vw) * .5833);grid-column:span 7}.bx-grid__col--sm--7.bx-grid>:not([class*=bx-grid__col]){grid-column:span 7}.bx-grid--fluid-rows>.bx-grid__height--sm--7{grid-row:span 7;height:calc((100vw - 10vw) * .5833);min-height:calc((100vw - 10vw) * .5833);max-height:calc((100rem - 10vw) * .5833)}.bx-grid__col--sm--8{max-width:calc((100rem - 10vw) * .6666);width:calc((100vw - 10vw) * .6666);grid-column:span 8}.bx-grid__col--sm--8.bx-grid>:not([class*=bx-grid__col]){grid-column:span 8}.bx-grid--fluid-rows>.bx-grid__height--sm--8{grid-row:span 8;height:calc((100vw - 10vw) * .6666);min-height:calc((100vw - 10vw) * .6666);max-height:calc((100rem - 10vw) * .6666)}.bx-grid__col--sm--9{max-width:calc((100rem - 10vw) * .75);width:calc((100vw - 10vw) * .75);grid-column:span 9}.bx-grid__col--sm--9.bx-grid>:not([class*=bx-grid__col]){grid-column:span 9}.bx-grid--fluid-rows>.bx-grid__height--sm--9{grid-row:span 9;height:calc((100vw - 10vw) * .75);min-height:calc((100vw - 10vw) * .75);max-height:calc((100rem - 10vw) * .75)}.bx-grid__col--sm--10{max-width:calc((100rem - 10vw) * .8333);width:calc((100vw - 10vw) * .8333);grid-column:span 10}.bx-grid__col--sm--10.bx-grid>:not([class*=bx-grid__col]){grid-column:span 10}.bx-grid--fluid-rows>.bx-grid__height--sm--10{grid-row:span 10;height:calc((100vw - 10vw) * .8333);min-height:calc((100vw - 10vw) * .8333);max-height:calc((100rem - 10vw) * .8333)}.bx-grid__col--sm--11{max-width:calc((100rem - 10vw) * .9166);width:calc((100vw - 10vw) * .9166);grid-column:span 11}.bx-grid__col--sm--11.bx-grid>:not([class*=bx-grid__col]){grid-column:span 11}.bx-grid--fluid-rows>.bx-grid__height--sm--11{grid-row:span 11;height:calc((100vw - 10vw) * .9166);min-height:calc((100vw - 10vw) * .9166);max-height:calc((100rem - 10vw) * .9166)}.bx-grid__col--sm--12{max-width:calc((100rem - 10vw) * 1);width:calc((100vw - 10vw) * 1);grid-column:span 12}.bx-grid__col--sm--12.bx-grid>:not([class*=bx-grid__col]){grid-column:span 12}.bx-grid--fluid-rows>.bx-grid__height--sm--12{grid-row:span 12;height:calc((100vw - 10vw) * 1);min-height:calc((100vw - 10vw) * 1);max-height:calc((100rem - 10vw) * 1)}@supports (display:grid){.bx-container{margin-left:auto;margin-right:auto;padding-left:5vw;padding-right:5vw}.bx-container--left{margin-left:0}.bx-container--right{margin-right:0}.bx-container__bleed--sm,.bx-container__bleed--sm--left,.bx-container__break--sm,.bx-container__break--sm--left{margin-left:-5vw}.bx-container__bleed--sm,.bx-container__bleed--sm--right,.bx-container__break--sm,.bx-container__break--sm--right{margin-right:-5vw}.bx-container__bleed--sm,.bx-container__bleed--sm--left{padding-left:5vw}.bx-container__bleed--sm--left.bx-padding,.bx-container__bleed--sm--left.bx-padding--horizontal,.bx-container__bleed--sm--left.bx-padding--left,.bx-container__bleed--sm.bx-padding,.bx-container__bleed--sm.bx-padding--horizontal,.bx-container__bleed--sm.bx-padding--left{padding-left:calc(5vw + .625rem)}.bx-container__bleed--sm,.bx-container__bleed--sm--right{padding-right:5vw}.bx-container__bleed--sm--right.bx-padding,.bx-container__bleed--sm--right.bx-padding--horizontal,.bx-container__bleed--sm--right.bx-padding--right,.bx-container__bleed--sm.bx-padding,.bx-container__bleed--sm.bx-padding--horizontal,.bx-container__bleed--sm.bx-padding--right{padding-right:calc(5vw + .625rem)}}@media screen and (min-width:100rem){.bx-grid__col--sm--0--only,[class*=bx-grid__col--xxl--]{display:block}.bx-grid__col--xxl--0,.bx-grid__col--xxl--0--only{display:none}.bx-padding{padding:.625rem}.bx-padding--bottom{padding-bottom:.625rem}.bx-padding--left{padding-left:.625rem}.bx-padding--right{padding-right:.625rem}.bx-padding--top{padding-top:.625rem}.bx-padding--horizontal{padding-left:.625rem;padding-right:.625rem}.bx-padding--vertical{padding-bottom:.625rem;padding-top:.625rem}.bx-grid{grid-template-columns:repeat(auto-fill,calc((100rem - 10vw) * .0833))}.bx-grid.bx-grid--fixed-columns{grid-template-columns:repeat(auto-fill,8.33333rem)}.bx-grid.bx-grid--fluid-rows{grid-auto-rows:calc((100rem - 10vw) * .0833)}[class*=bx-grid__col--]{min-width:0}@supports (display:grid){.bx-container{margin-left:auto;margin-right:auto;padding-left:5vw;padding-right:5vw}.bx-container--left{margin-left:0}.bx-container--right{margin-right:0}.bx-container__bleed--sm,.bx-container__bleed--sm--left,.bx-container__break--sm,.bx-container__break--sm--left{margin-left:-5vw}.bx-container__bleed--sm,.bx-container__bleed--sm--right,.bx-container__break--sm,.bx-container__break--sm--right{margin-right:-5vw}.bx-container__bleed--sm,.bx-container__bleed--sm--left{padding-left:5vw}.bx-container__bleed--sm--left.bx-padding,.bx-container__bleed--sm--left.bx-padding--horizontal,.bx-container__bleed--sm--left.bx-padding--left,.bx-container__bleed--sm.bx-padding,.bx-container__bleed--sm.bx-padding--horizontal,.bx-container__bleed--sm.bx-padding--left{padding-left:calc(5vw + .625rem)}.bx-container__bleed--sm,.bx-container__bleed--sm--right{padding-right:5vw}.bx-container__bleed--sm--right.bx-padding,.bx-container__bleed--sm--right.bx-padding--horizontal,.bx-container__bleed--sm--right.bx-padding--right,.bx-container__bleed--sm.bx-padding,.bx-container__bleed--sm.bx-padding--horizontal,.bx-container__bleed--sm.bx-padding--right{padding-right:calc(5vw + .625rem)}}}@supports (display:grid){.bx-grid>*,.bx-grid>[class*=bx-grid__col--]{min-width:initial;max-width:initial;width:initial}.bx-grid>.bx-grid,.bx-grid>[class*=bx-grid__col--].bx-grid{display:grid}.bx-grid>[class*=bx-grid__height--]{height:unset;max-height:unset;min-height:initial}}.bx-grid>script{display:none} -------------------------------------------------------------------------------- /examples/carbon/css-gridish/css/bx-grid.min.css: -------------------------------------------------------------------------------- 1 | html{font-size:16px}body{margin:0}.bx-grid{align-items:flex-start;box-sizing:border-box;display:grid;flex-wrap:wrap;position:relative;grid-auto-rows:minmax(.5rem,min-content);grid-template-columns:repeat(auto-fill,calc((100vw - 10vw) * .0833))}.bx-grid>*{box-sizing:border-box;grid-column:span 12}.bx-grid>* :last-child,.bx-grid>* :last-child>:last-child,.bx-grid>* :last-child>:last-child>:last-child{margin-bottom:0}[class*=bx-padding]{box-sizing:border-box}@supports (display:grid){.bx-grid>*{height:100%}}:root{--bx-height-1:0.5rem;--bx-height-2:1rem;--bx-height-3:1.5rem;--bx-height-4:2rem;--bx-height-5:2.5rem;--bx-height-6:3rem;--bx-height-7:3.5rem;--bx-height-8:4rem;--bx-height-9:4.5rem;--bx-height-10:5rem;--bx-height-11:5.5rem;--bx-height-12:6rem;--bx-height-13:6.5rem;--bx-height-14:7rem;--bx-height-15:7.5rem;--bx-height-16:8rem;--bx-height-17:8.5rem;--bx-height-18:9rem;--bx-height-19:9.5rem;--bx-height-20:10rem;--bx-height-21:10.5rem;--bx-height-22:11rem;--bx-height-23:11.5rem;--bx-height-24:12rem;--bx-height-25:12.5rem;--bx-height-26:13rem;--bx-height-27:13.5rem;--bx-height-28:14rem;--bx-height-29:14.5rem}.bx-grid__height--sm--0{height:0;min-height:0}.bx-grid__height--sm--1{grid-row:span 1}.bx-grid__height--sm--2{grid-row:span 2}.bx-grid__height--sm--3{grid-row:span 3}.bx-grid__height--sm--4{grid-row:span 4}.bx-grid__height--sm--5{grid-row:span 5}.bx-grid__height--sm--6{grid-row:span 6}.bx-grid__height--sm--7{grid-row:span 7}.bx-grid__height--sm--8{grid-row:span 8}.bx-grid__height--sm--9{grid-row:span 9}.bx-grid__height--sm--10{grid-row:span 10}.bx-grid__height--sm--11{grid-row:span 11}.bx-grid__height--sm--12{grid-row:span 12}.bx-grid__height--sm--13{grid-row:span 13}.bx-grid__height--sm--14{grid-row:span 14}.bx-grid__height--sm--15{grid-row:span 15}.bx-grid__height--sm--16{grid-row:span 16}.bx-grid__height--sm--17{grid-row:span 17}.bx-grid__height--sm--18{grid-row:span 18}.bx-grid__height--sm--19{grid-row:span 19}.bx-grid__height--sm--20{grid-row:span 20}.bx-grid__height--sm--21{grid-row:span 21}.bx-grid__height--sm--22{grid-row:span 22}.bx-grid__height--sm--23{grid-row:span 23}.bx-grid__height--sm--24{grid-row:span 24}.bx-grid__height--sm--25{grid-row:span 25}.bx-grid__height--sm--26{grid-row:span 26}.bx-grid__height--sm--27{grid-row:span 27}.bx-grid__height--sm--28{grid-row:span 28}.bx-grid__height--sm--29{grid-row:span 29}[class*=bx-grid__col--sm--]{display:block}.bx-grid__col--sm--0,.bx-grid__col--sm--0--only{display:none}.bx-padding{padding:.625rem}.bx-padding--bottom{padding-bottom:.625rem}.bx-padding--left{padding-left:.625rem}.bx-padding--right{padding-right:.625rem}.bx-padding--top{padding-top:.625rem}.bx-padding--horizontal{padding-left:.625rem;padding-right:.625rem}.bx-padding--vertical{padding-bottom:.625rem;padding-top:.625rem}.bx-grid.bx-grid--fixed-columns{grid-template-columns:repeat(auto-fill,1.66667rem)}.bx-grid.bx-grid--fluid-rows{grid-auto-rows:calc((100vw - 10vw) * .0833)}.bx-grid__col--sm--1,.bx-grid__col--sm--1.bx-grid>:not([class*=bx-grid__col]){grid-column:span 1}.bx-grid--fluid-rows>.bx-grid__height--sm--1{grid-row:span 1}.bx-grid__col--sm--2,.bx-grid__col--sm--2.bx-grid>:not([class*=bx-grid__col]){grid-column:span 2}.bx-grid--fluid-rows>.bx-grid__height--sm--2{grid-row:span 2}.bx-grid__col--sm--3,.bx-grid__col--sm--3.bx-grid>:not([class*=bx-grid__col]){grid-column:span 3}.bx-grid--fluid-rows>.bx-grid__height--sm--3{grid-row:span 3}.bx-grid__col--sm--4,.bx-grid__col--sm--4.bx-grid>:not([class*=bx-grid__col]){grid-column:span 4}.bx-grid--fluid-rows>.bx-grid__height--sm--4{grid-row:span 4}.bx-grid__col--sm--5,.bx-grid__col--sm--5.bx-grid>:not([class*=bx-grid__col]){grid-column:span 5}.bx-grid--fluid-rows>.bx-grid__height--sm--5{grid-row:span 5}.bx-grid__col--sm--6,.bx-grid__col--sm--6.bx-grid>:not([class*=bx-grid__col]){grid-column:span 6}.bx-grid--fluid-rows>.bx-grid__height--sm--6{grid-row:span 6}.bx-grid__col--sm--7,.bx-grid__col--sm--7.bx-grid>:not([class*=bx-grid__col]){grid-column:span 7}.bx-grid--fluid-rows>.bx-grid__height--sm--7{grid-row:span 7}.bx-grid__col--sm--8,.bx-grid__col--sm--8.bx-grid>:not([class*=bx-grid__col]){grid-column:span 8}.bx-grid--fluid-rows>.bx-grid__height--sm--8{grid-row:span 8}.bx-grid__col--sm--9,.bx-grid__col--sm--9.bx-grid>:not([class*=bx-grid__col]){grid-column:span 9}.bx-grid--fluid-rows>.bx-grid__height--sm--9{grid-row:span 9}.bx-grid__col--sm--10,.bx-grid__col--sm--10.bx-grid>:not([class*=bx-grid__col]){grid-column:span 10}.bx-grid--fluid-rows>.bx-grid__height--sm--10{grid-row:span 10}.bx-grid__col--sm--11,.bx-grid__col--sm--11.bx-grid>:not([class*=bx-grid__col]){grid-column:span 11}.bx-grid--fluid-rows>.bx-grid__height--sm--11{grid-row:span 11}.bx-grid__col--sm--12,.bx-grid__col--sm--12.bx-grid>:not([class*=bx-grid__col]){grid-column:span 12}.bx-grid--fluid-rows>.bx-grid__height--sm--12{grid-row:span 12}.bx-container{box-sizing:border-box;max-width:100rem;overflow-x:hidden;width:100vw;margin-left:auto;margin-right:auto;padding-left:5vw;padding-right:5vw}.bx-container--left{margin-left:0}.bx-container--right{margin-right:0}.bx-container__bleed--sm,.bx-container__bleed--sm--left,.bx-container__break--sm,.bx-container__break--sm--left{margin-left:-5vw}.bx-container__bleed--sm,.bx-container__bleed--sm--right,.bx-container__break--sm,.bx-container__break--sm--right{margin-right:-5vw}.bx-container__bleed--sm,.bx-container__bleed--sm--left{padding-left:5vw}.bx-container__bleed--sm--left.bx-padding,.bx-container__bleed--sm--left.bx-padding--horizontal,.bx-container__bleed--sm--left.bx-padding--left,.bx-container__bleed--sm.bx-padding,.bx-container__bleed--sm.bx-padding--horizontal,.bx-container__bleed--sm.bx-padding--left{padding-left:calc(5vw + .625rem)}.bx-container__bleed--sm,.bx-container__bleed--sm--right{padding-right:5vw}.bx-container__bleed--sm--right.bx-padding,.bx-container__bleed--sm--right.bx-padding--horizontal,.bx-container__bleed--sm--right.bx-padding--right,.bx-container__bleed--sm.bx-padding,.bx-container__bleed--sm.bx-padding--horizontal,.bx-container__bleed--sm.bx-padding--right{padding-right:calc(5vw + .625rem)}@media screen and (min-width:100rem){.bx-grid__col--sm--0--only,[class*=bx-grid__col--xxl--]{display:block}.bx-grid__col--xxl--0,.bx-grid__col--xxl--0--only{display:none}.bx-padding{padding:.625rem}.bx-padding--bottom{padding-bottom:.625rem}.bx-padding--left{padding-left:.625rem}.bx-padding--right{padding-right:.625rem}.bx-padding--top{padding-top:.625rem}.bx-padding--horizontal{padding-left:.625rem;padding-right:.625rem}.bx-padding--vertical{padding-bottom:.625rem;padding-top:.625rem}.bx-grid{grid-template-columns:repeat(auto-fill,calc((100rem - 10vw) * .0833))}.bx-grid.bx-grid--fixed-columns{grid-template-columns:repeat(auto-fill,8.33333rem)}.bx-grid.bx-grid--fluid-rows{grid-auto-rows:calc((100rem - 10vw) * .0833)}.bx-container{margin-left:auto;margin-right:auto;padding-left:5vw;padding-right:5vw}.bx-container--left{margin-left:0}.bx-container--right{margin-right:0}.bx-container__bleed--sm,.bx-container__bleed--sm--left,.bx-container__break--sm,.bx-container__break--sm--left{margin-left:-5vw}.bx-container__bleed--sm,.bx-container__bleed--sm--right,.bx-container__break--sm,.bx-container__break--sm--right{margin-right:-5vw}.bx-container__bleed--sm,.bx-container__bleed--sm--left{padding-left:5vw}.bx-container__bleed--sm--left.bx-padding,.bx-container__bleed--sm--left.bx-padding--horizontal,.bx-container__bleed--sm--left.bx-padding--left,.bx-container__bleed--sm.bx-padding,.bx-container__bleed--sm.bx-padding--horizontal,.bx-container__bleed--sm.bx-padding--left{padding-left:calc(5vw + .625rem)}.bx-container__bleed--sm,.bx-container__bleed--sm--right{padding-right:5vw}.bx-container__bleed--sm--right.bx-padding,.bx-container__bleed--sm--right.bx-padding--horizontal,.bx-container__bleed--sm--right.bx-padding--right,.bx-container__bleed--sm.bx-padding,.bx-container__bleed--sm.bx-padding--horizontal,.bx-container__bleed--sm.bx-padding--right{padding-right:calc(5vw + .625rem)}} -------------------------------------------------------------------------------- /examples/carbon/css-gridish/scss/_core.scss: -------------------------------------------------------------------------------- 1 | @import "functions.scss"; 2 | @import "mixins.scss"; 3 | @import "variables.scss"; 4 | @import "utilities.scss"; 5 | 6 | html { 7 | font-size: map-get($grid-values, "rem") * 1px; 8 | } 9 | 10 | body { 11 | margin: 0; 12 | } 13 | 14 | .#{$prefix}-container { 15 | box-sizing: border-box; 16 | margin-left: auto; 17 | margin-right: auto; 18 | max-width: #{map-get($last, breakpoint)}rem; 19 | overflow-x: hidden; 20 | width: 100vw; 21 | } 22 | 23 | .#{$prefix}-container--left { 24 | margin-left: 0; 25 | } 26 | 27 | .#{$prefix}-container--right { 28 | margin-right: 0; 29 | } 30 | 31 | .#{$prefix}-grid { 32 | align-items: flex-start; 33 | box-sizing: border-box; 34 | @if $includeFlexFallback { 35 | display: flex; 36 | } 37 | display: grid; 38 | flex-wrap: wrap; 39 | position: relative; 40 | 41 | > * { 42 | box-sizing: border-box; 43 | 44 | :last-child, 45 | :last-child > :last-child, 46 | :last-child > :last-child > :last-child { 47 | margin-bottom: 0; 48 | } 49 | } 50 | } 51 | 52 | [class*="#{$prefix}-padding"] { 53 | box-sizing: border-box; 54 | } 55 | 56 | // Rules needed in legacy, but needed to change in CSS Grid 57 | @if $includeFlexFallback { 58 | .#{$prefix}-grid > * { 59 | width: 100%; 60 | } 61 | 62 | @supports (display: grid) { 63 | .#{$prefix}-grid { 64 | align-items: unset; 65 | } 66 | 67 | .#{$prefix}-grid > * { 68 | width: initial; 69 | } 70 | } 71 | } 72 | 73 | // Rules not needed in legacy, but needed in CSS Grid 74 | @supports (display: grid) { 75 | .#{$prefix}-grid > * { 76 | height: 100%; 77 | } 78 | } 79 | 80 | @include grid-legacy-wrapper($includeFlexFallback) { 81 | :root { 82 | @include grid-heights-fixed($rows); 83 | } 84 | } 85 | 86 | @each $name, $breakpoint in $allBreakpoints { 87 | @include media-query($name) { 88 | @if is-same-breakpoint($breakpoint, $last) == false { 89 | @include grid-legacy-heights($name); 90 | } 91 | @include grid-legacy-zeros($breakpoint, $name); 92 | @include grid-padding($breakpoint); 93 | @include grid($breakpoint, $name); 94 | @include grid-legacy-columns($breakpoint, $name); 95 | 96 | // Wrap all bleed/break classes and css variables in a CSS Grid support query 97 | @include grid-legacy-wrapper($includeFlexFallback) { 98 | @include grid-margin($breakpoint, $name); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /examples/carbon/css-gridish/scss/_functions.scss: -------------------------------------------------------------------------------- 1 | @import "sass-list-maps"; 2 | 3 | // Transform the gutter property into a padding property for web 4 | @function add-padding($breakpoints) { 5 | $cleanBreakpoints: (); 6 | @each $name, $breakpoint in $breakpoints { 7 | $cleanBreakpoints: map-merge( 8 | $cleanBreakpoints, 9 | ( 10 | $name: 11 | map-merge($breakpoint, (padding: map-get($breakpoint, gutter) / 2)) 12 | ) 13 | ); 14 | } 15 | 16 | @return $cleanBreakpoints; 17 | } 18 | 19 | // Merge standard and custom breakpoints into list 20 | @function all-breakpoints($breakpoints, $extraBreakpoints, $first, $last) { 21 | $allBreakpoints: $breakpoints; 22 | @each $currentBreakpoint in $extraBreakpoints { 23 | $extraBreakpointName: nth($currentBreakpoint, 1); 24 | $extraBreakpointWidth: nth($currentBreakpoint, 2); 25 | $found: false; 26 | $match: null; 27 | @each $majorBreakpoint in $breakpoints { 28 | @if $found == false { 29 | @if map-get(nth($majorBreakpoint, 2), breakpoint) > 30 | $extraBreakpointWidth 31 | { 32 | $found: true; 33 | } @else { 34 | $match: $majorBreakpoint; 35 | } 36 | } 37 | } 38 | @if $extraBreakpointWidth > map-get($last, breakpoint) { 39 | $match: ( 40 | last, 41 | $last 42 | ); 43 | } 44 | @if $extraBreakpointWidth < map-get($first, breakpoint) { 45 | $match: ( 46 | first, 47 | $first 48 | ); 49 | } 50 | 51 | $newBreakpoint: map-merge( 52 | nth($match, 2), 53 | (breakpoint: $extraBreakpointWidth) 54 | ); 55 | $currentBreakpoint: ( 56 | $extraBreakpointName: 57 | map-merge(nth($match, 2), (breakpoint: $extraBreakpointWidth)) 58 | ); 59 | $allBreakpoints: map-merge($allBreakpoints, $currentBreakpoint); 60 | } 61 | 62 | @return maps-sort($allBreakpoints, breakpoint); 63 | } 64 | 65 | @function is-same-breakpoint($a, $b) { 66 | @return map-get($a, breakpoint) == map-get($b, breakpoint); 67 | } 68 | 69 | /// Traverse maps and retrieve deeply nested values: https://css-tricks.com/snippets/sass/deep-getset-maps/ 70 | /// @author Hugo Giraudel 71 | /// @param {Map} $map A sass map and any number of keys. 72 | /// @param {*} $keys Nested values. 73 | /// @return Nested values or nested map. 74 | @function map-deep-get($map, $keys...) { 75 | @each $key in $keys { 76 | $map: map-get($map, $key); 77 | } 78 | @return $map; 79 | } 80 | 81 | // _decimal.scss | MIT License | gist.github.com/terkel/4373420 82 | @function round-decimal($number, $digits: 0, $mode: round) { 83 | $n: 1; 84 | // $number must be a number 85 | @if type-of($number) != number { 86 | @warn "#{ $number } is not a number."; 87 | @return $number; 88 | } 89 | // $digits must be a unitless number 90 | @if type-of($digits) != number { 91 | @warn "#{ $digits } is not a number."; 92 | @return $number; 93 | } @else if not unitless($digits) { 94 | @warn "#{ $digits } has a unit."; 95 | @return $number; 96 | } 97 | @for $i from 1 through $digits { 98 | $n: $n * 10; 99 | } 100 | @if $mode == round { 101 | @return round($number * $n) / $n; 102 | } @else if $mode == ceil { 103 | @return ceil($number * $n) / $n; 104 | } @else if $mode == floor { 105 | @return floor($number * $n) / $n; 106 | } @else { 107 | @warn "#{ $mode } is undefined keyword."; 108 | @return $number; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /examples/carbon/css-gridish/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Set the width of a grid’s column 2 | @mixin grid($breakpoint, $breakpointName) { 3 | @if (map-get($breakpoint, columns) != null) { 4 | $columnSize: get-fluid-size($breakpointName, 1); 5 | 6 | .#{$prefix}-grid { 7 | @if is-same-breakpoint($breakpoint, $first) { 8 | grid-auto-rows: minmax($rowHeight * 1rem, min-content); 9 | } 10 | grid-template-columns: repeat(auto-fill, $columnSize); 11 | 12 | &.#{$prefix}-grid--fixed-columns { 13 | grid-template-columns: repeat( 14 | auto-fill, 15 | map-get($breakpoint, breakpoint) * 16 | 1rem / 17 | map-get($breakpoint, columns) 18 | ); 19 | } 20 | 21 | &.#{$prefix}-grid--fluid-rows { 22 | grid-auto-rows: $columnSize; 23 | } 24 | 25 | @if is-same-breakpoint($breakpoint, $last) == false { 26 | > * { 27 | grid-column: span #{map-get($breakpoint, columns)}; 28 | } 29 | } 30 | } 31 | } 32 | } 33 | 34 | // Generate variables for commonly used rows 35 | @mixin grid-heights-fixed($rows) { 36 | @for $i from 1 to $rows { 37 | --#{$prefix}-height-#{$i}: get-fixed-size($i); 38 | } 39 | } 40 | 41 | // Set the width of a grid’s column for legacy grid 42 | @mixin grid-legacy-columns($breakpoint, $name) { 43 | // Do not make class if last media query 44 | @if is-same-breakpoint($breakpoint, $last) == false { 45 | // Loop each breakpoint to insert previous breakpoint classes inside this breakpoint’s media query 46 | // Ex: Make sure .yourPrefix-grid__col--sm--2 has correct sizes in the lg media query 47 | @each $currentName, $currentBreakpoint in $allBreakpoints { 48 | // Check if current breakpoint is not bigger than current media query 49 | @if map-get($breakpoint, breakpoint) >= 50 | map-get($currentBreakpoint, breakpoint) 51 | { 52 | // Loop each column in current breakpoint for new class 53 | // Ex: .yourPrefix-grid__col--sm--1, .yourPrefix-grid__col--sm--2, etc. 54 | @for $i from 1 through map-get($currentBreakpoint, columns) { 55 | $columnMultiplier: $i * 56 | map-get($breakpoint, columns) / 57 | map-get($currentBreakpoint, columns); 58 | $columnSize: get-fluid-size($name, $columnMultiplier); 59 | 60 | $isSecondToLast: is-same-breakpoint( 61 | $breakpoint, 62 | nth(nth($allBreakpoints, length($allBreakpoints) - 1), 2) 63 | ); 64 | 65 | $maxColumnSize: get-fluid-size( 66 | nth(nth($allBreakpoints, length($allBreakpoints)), 1), 67 | $columnMultiplier 68 | ); 69 | 70 | .#{$prefix}-grid__col--#{$currentName}--#{$i} { 71 | @if $includeFlexFallback { 72 | // If second-to-last media query, apply max-width instead of remaking classes in last media query 73 | @if $isSecondToLast { 74 | max-width: $maxColumnSize; 75 | } 76 | width: $columnSize; 77 | } 78 | grid-column: span #{$columnMultiplier}; 79 | 80 | @if is-same-breakpoint($breakpoint, $last) == false { 81 | &.#{$prefix}-grid > *:not([class*="#{$prefix}-grid__col"]) { 82 | grid-column: span #{$i}; 83 | } 84 | } 85 | } 86 | 87 | .#{$prefix}-grid--fluid-rows 88 | > .#{$prefix}-grid__height--#{$currentName}--#{$i} { 89 | grid-row: span $i; 90 | @if $includeFlexFallback { 91 | height: $columnSize; 92 | min-height: $columnSize; 93 | // If second-to-last media query, apply max-height instead of remaking classes in last media query 94 | @if $isSecondToLast { 95 | max-height: $maxColumnSize; 96 | } 97 | } 98 | } 99 | } 100 | } 101 | } 102 | } 103 | 104 | @if $includeFlexFallback { 105 | @if is-same-breakpoint($breakpoint, $last) { 106 | [class*="#{$prefix}-grid__col--"] { 107 | min-width: 0; 108 | } 109 | } 110 | } 111 | } 112 | 113 | // Set the height of an item for legacy grid 114 | @mixin grid-legacy-heights($name) { 115 | .#{$prefix}-grid__height--#{$name}--0 { 116 | height: 0; 117 | min-height: 0; 118 | } 119 | @for $i from 1 to $rows { 120 | .#{$prefix}-grid__height--#{$name}--#{$i} { 121 | grid-row: span $i; 122 | @if $includeFlexFallback { 123 | height: get-fixed-size($i); 124 | min-height: get-fixed-size($i); 125 | } 126 | } 127 | } 128 | } 129 | 130 | // If we need legacy grid, wrap this content in support tag 131 | @mixin grid-legacy-wrapper($includeFlexFallback) { 132 | @if $includeFlexFallback { 133 | @supports (display: grid) { 134 | @content; 135 | } 136 | } @else { 137 | @content; 138 | } 139 | } 140 | 141 | // Generate all classes for 0 and 0-only displaying, including custom breakpoints if they exist 142 | @mixin grid-legacy-zeros($breakpoint, $name) { 143 | // Undo previous breakpoint’s 0--only class 144 | @for $i from length($allBreakpoints) * -1 through -1 { 145 | $currentBreakpoint: nth($allBreakpoints, $i); 146 | @if map-get(nth($currentBreakpoint, 2), breakpoint) < 147 | map-get($breakpoint, breakpoint) 148 | { 149 | .#{$prefix}-grid__col--#{nth($currentBreakpoint, 1)}--0--only { 150 | display: block; 151 | } 152 | } 153 | } 154 | 155 | [class*="#{$prefix}-grid__col--#{$name}--"] { 156 | display: block; 157 | } 158 | 159 | .#{$prefix}-grid__col--#{$name}--0, 160 | .#{$prefix}-grid__col--#{$name}--0--only { 161 | display: none; 162 | } 163 | } 164 | 165 | // Set the width of a grid’s margin 166 | // and allow for a child to break out of the grid’s margin 167 | @mixin grid-margin($breakpoint, $name) { 168 | $nameToUse: $name; 169 | $margin: #{map-get($breakpoint, margin)}; 170 | $padding: #{map-get($breakpoint, padding)}; 171 | 172 | // If last breakpoint, we use the previous breakpoint name 173 | // to treat the last breakpoint as the max-width of the previous breakpoint 174 | @if is-same-breakpoint($breakpoint, $last) == true { 175 | $previousBreakpoint: nth( 176 | $allBreakpoints, 177 | index(map-keys($allBreakpoints), $name) - 1 178 | ); 179 | $nameToUse: nth($previousBreakpoint, 1); 180 | } 181 | 182 | // Undo previous breakpoint’s bleeds and breaks 183 | @if is-same-breakpoint($breakpoint, $first) == 184 | false and 185 | is-same-breakpoint($breakpoint, $last) == 186 | false 187 | { 188 | $previousBreakpoint: nth( 189 | $allBreakpoints, 190 | index(map-keys($allBreakpoints), $name) - 1 191 | ); 192 | $previousName: nth($previousBreakpoint, 1); 193 | $previousMargin: map-get(nth($previousBreakpoint, 2), margin); 194 | 195 | @if $previousMargin != 196 | null and 197 | $previousMargin != 198 | 0 and 199 | $previousMargin != 200 | "0" 201 | { 202 | [class^="#{$prefix}-container__bleed--#{$previousName}"], 203 | [class^="#{$prefix}-container__break--#{$previousName}"] { 204 | margin-left: 0; 205 | margin-right: 0; 206 | padding-left: 0; 207 | padding-right: 0; 208 | 209 | &[class^="#{$prefix}-padding"] { 210 | padding-left: $padding; 211 | padding-right: $padding; 212 | } 213 | } 214 | } 215 | } 216 | 217 | @if $margin != null and $margin != 0 and $margin != "0" { 218 | $marginPlusPadding: calc(#{$margin} + #{$padding}); 219 | @if $margin == "0" and $padding == "0" { 220 | $marginPlusPadding: 0; 221 | } @else if $margin == "0" { 222 | $marginPlusPadding: $padding; 223 | } @else if $padding == "0" { 224 | $marginPlusPadding: $margin; 225 | } 226 | 227 | .#{$prefix}-container { 228 | margin-left: auto; 229 | margin-right: auto; 230 | padding-left: $margin; 231 | padding-right: $margin; 232 | } 233 | 234 | .#{$prefix}-container--left { 235 | margin-left: 0; 236 | } 237 | 238 | .#{$prefix}-container--right { 239 | margin-right: 0; 240 | } 241 | 242 | .#{$prefix}-container__bleed--#{$nameToUse}, 243 | .#{$prefix}-container__bleed--#{$nameToUse}--left, 244 | .#{$prefix}-container__break--#{$nameToUse}, 245 | .#{$prefix}-container__break--#{$nameToUse}--left { 246 | margin-left: -#{$margin}; 247 | } 248 | 249 | .#{$prefix}-container__bleed--#{$nameToUse}, 250 | .#{$prefix}-container__bleed--#{$nameToUse}--right, 251 | .#{$prefix}-container__break--#{$nameToUse}, 252 | .#{$prefix}-container__break--#{$nameToUse}--right { 253 | margin-right: -#{$margin}; 254 | } 255 | 256 | .#{$prefix}-container__bleed--#{$nameToUse}, 257 | .#{$prefix}-container__bleed--#{$nameToUse}--left { 258 | padding-left: $margin; 259 | 260 | &.#{$prefix}-padding, 261 | &.#{$prefix}-padding--horizontal, 262 | &.#{$prefix}-padding--left { 263 | padding-left: $marginPlusPadding; 264 | } 265 | } 266 | 267 | .#{$prefix}-container__bleed--#{$nameToUse}, 268 | .#{$prefix}-container__bleed--#{$nameToUse}--right { 269 | padding-right: $margin; 270 | 271 | &.#{$prefix}-padding, 272 | &.#{$prefix}-padding--horizontal, 273 | &.#{$prefix}-padding--right { 274 | padding-right: $marginPlusPadding; 275 | } 276 | } 277 | } 278 | } 279 | 280 | // Classnames for different padding options 281 | @mixin grid-padding($breakpoint) { 282 | @if (map-get($breakpoint, padding) != null) { 283 | $padding: map-get($breakpoint, padding); 284 | 285 | .#{$prefix}-padding { 286 | padding: $padding; 287 | } 288 | 289 | .#{$prefix}-padding--bottom { 290 | padding-bottom: $padding; 291 | } 292 | 293 | .#{$prefix}-padding--left { 294 | padding-left: $padding; 295 | } 296 | 297 | .#{$prefix}-padding--right { 298 | padding-right: $padding; 299 | } 300 | 301 | .#{$prefix}-padding--top { 302 | padding-top: $padding; 303 | } 304 | 305 | .#{$prefix}-padding--horizontal { 306 | padding-left: $padding; 307 | padding-right: $padding; 308 | } 309 | 310 | .#{$prefix}-padding--vertical { 311 | padding-bottom: $padding; 312 | padding-top: $padding; 313 | } 314 | } 315 | } 316 | -------------------------------------------------------------------------------- /examples/carbon/css-gridish/scss/_sass-list-maps.scss: -------------------------------------------------------------------------------- 1 | /// _ 2 | /// | | 3 | /// ___ __ _ ___ ___ ______ _ __ ___ __ _ _ __ ___ ______ _ __ | |_ _ ___ 4 | /// / __|/ _` / __/ __|______| '_ ` _ \ / _` | '_ \/ __|______| '_ \| | | | / __| 5 | /// \__ \ (_| \__ \__ \ | | | | | | (_| | |_) \__ \ | |_) | | |_| \__ \ 6 | /// |___/\__,_|___/___/ |_| |_| |_|\__,_| .__/|___/ | .__/|_|\__,_|___/ 7 | /// | | | | 8 | /// |_| |_| 9 | /// Sass Maps Plus 0.9.2 10 | /// Advanced map and list-map manipulation for all versions of Sass 11 | /// MIT License 12 | /// @author Lu Nelson 13 | 14 | /// Global sort direction: either `asc` or `desc` 15 | /// @access public 16 | /// @group map-lists/map-maps 17 | $maps-sort-dir: "asc"; 18 | 19 | /// get value at nested or 'deep' key, per $keys list 20 | /// @access public 21 | /// @group maps 22 | /// @param {Map} $map - map 23 | /// @param {Arglist} $keys - nested keys 24 | /// @return {*} 25 | @function map-get-nested($map, $keys...) { 26 | @if length($map) == 0 { 27 | @return null; 28 | } 29 | @each $key in $keys { 30 | @if type-of($map) != "map" { 31 | @return $map; 32 | } 33 | $map: map-get($map, $key); 34 | } 35 | @return $map; 36 | } 37 | 38 | /// Sort a list-of-maps or map-of-maps, based on value at key(s) in maps 39 | /// @access public 40 | /// @group map-lists/map-maps 41 | /// @param {Map|List} $maps - Map of maps, or List of maps, to sort 42 | /// @param {Arglist} $keys - Chain of keys to the value that will be sorted for 43 | /// @return {Map|List} 44 | /// @require {function} map-get-nested 45 | @function maps-sort($maps, $keys...) { 46 | @if length($keys) == 0 { 47 | @return $maps; 48 | } 49 | 50 | @if length($maps) > 1 { 51 | $less: (); 52 | $equal: (); 53 | $greater: (); 54 | 55 | $map-of-maps: type-of($maps) == "map"; 56 | 57 | @if $map-of-maps { 58 | $seed-map: nth(nth($maps, ceil(length($maps) / 2)), 2); 59 | 60 | $seed-value: map-get-nested($seed-map, $keys...); 61 | 62 | // TODO: add code to handle case of non-number values (warn and return $maps) 63 | 64 | @each $key, $map in $maps { 65 | $curr-value: map-get-nested($map, $keys...); 66 | 67 | @if $curr-value == $seed-value { 68 | $equal: map-merge($equal, ($key: $map)); 69 | } @else if $curr-value < $seed-value { 70 | @if $maps-sort-dir == "asc" { 71 | $less: map-merge($less, ($key: $map)); 72 | } @else { 73 | $greater: map-merge($greater, ($key: $map)); 74 | } 75 | } @else { 76 | @if $maps-sort-dir == "asc" { 77 | $greater: map-merge($greater, ($key: $map)); 78 | } @else { 79 | $less: map-merge($less, ($key: $map)); 80 | } 81 | } 82 | } 83 | 84 | $less: maps-sort($less, $keys...); 85 | $greater: maps-sort($greater, $keys...); 86 | 87 | @return map-merge(map-merge($less, $equal), $greater); 88 | } @else { 89 | $seed-map: nth($maps, ceil(length($maps) / 2)); 90 | 91 | $seed-value: map-get-nested($seed-map, $keys...); 92 | 93 | @each $map in $maps { 94 | $curr-value: map-get-nested($map, $keys...); 95 | 96 | @if $curr-value == $seed-value { 97 | $equal: append($equal, $map); 98 | } @else if $curr-value < $seed-value { 99 | @if $maps-sort-dir == "asc" { 100 | $less: append($less, $map); 101 | } @else { 102 | $greater: append($greater, $map); 103 | } 104 | } @else { 105 | @if $maps-sort-dir == "asc" { 106 | $greater: append($greater, $map); 107 | } @else { 108 | $less: append($less, $map); 109 | } 110 | } 111 | } 112 | 113 | $less: maps-sort($less, $keys...); 114 | $greater: maps-sort($greater, $keys...); 115 | 116 | @return join(join($less, $equal), $greater); 117 | } 118 | } 119 | 120 | @return $maps; 121 | } 122 | -------------------------------------------------------------------------------- /examples/carbon/css-gridish/scss/_utilities.scss: -------------------------------------------------------------------------------- 1 | @import "functions"; 2 | @import "values"; 3 | @import "variables"; 4 | 5 | /// Function returns the value for a given breakpoint. 6 | /// @param {String} $breakpointName Breakpoint name. 7 | /// @return {Length} The breakpoint value in rems. 8 | @function get-breakpoint-value($breakpointName) { 9 | $breakpointValue: map-deep-get( 10 | $breakpointsAndArtboards, 11 | $breakpointName, 12 | "breakpoint" 13 | ); 14 | 15 | @return $breakpointValue * 1rem; 16 | } 17 | 18 | /// Returns a calc() expression that represents a fluid width at a given breakpoint. 19 | /// @param {String} $breakpointName A valid breakpoint. 20 | /// @param {Number} $columnSpan The number of columns to span across. 21 | /// @return {Length} A calc() expression representing fluid width. 22 | /// @example scss 23 | /// button { 24 | /// @include media-query('sm') { 25 | /// max-width: get-fluid-size('sm', 1); 26 | /// } 27 | /// } 28 | /// @output css 29 | /// @media screen and (min-width: 20rem) { 30 | /// button { 31 | /// max-width: 25vw; 32 | /// } 33 | /// } 34 | @function get-fluid-size($breakpointName, $columnSpan) { 35 | $breakpoint: map-get($breakpointsAndArtboards, $breakpointName); 36 | 37 | @if ($breakpoint == null or type-of($breakpoint) != "map") { 38 | @error "The provided breakpoint `#{$breakpointName}` is not a valid breakpoint found in breakpoints or extraArtboards in $grid-values. Please double-check your grid configuration."; 39 | } 40 | 41 | $columnTotal: map-get($breakpoint, columns); 42 | $margin: map-get($breakpoint, margin); 43 | 44 | @if ($columnTotal == null or type-of($columnTotal) != "number") { 45 | @error "The provided breakpoint `#{$breakpointName}` needs to have a total number of columns set in $grid-values. Please double-check your grid configuration."; 46 | } 47 | 48 | @if ($columnSpan == null or type-of($columnSpan) != "number") { 49 | @error "The number of columns to span for the breakpoint `#{$breakpointName}` must be a valid number. The provided column span value `#{$columnSpan}` is not a number"; 50 | } 51 | 52 | @if ($columnSpan > $columnTotal or $columnSpan <= 0) { 53 | @error "The number of columns to span for the breakpoint `#{$breakpointName}` must be greater than 0 and less than or equal to the total number of columns for this breakpoint. The provided column value `#{$columnSpan}` does not meet this criteria"; 54 | } 55 | 56 | $container: 100vw; 57 | // Last breakpoint is a max-width and should be a fixed number 58 | @if is-same-breakpoint($breakpoint, $last) { 59 | $container: map-get($breakpoint, breakpoint) * 1rem; 60 | } 61 | 62 | $multiplier: round-decimal($columnSpan / $columnTotal, 4, floor); 63 | 64 | // For IE, we can't have a 0 in the $fluidWidth calc(). 65 | @if ($margin == 0) { 66 | @return $container * $multiplier; 67 | } 68 | 69 | @return calc((#{$container} - #{$margin * 2}) * #{$multiplier}); 70 | } 71 | 72 | /// Function gets a calculated rem value for a fixed size. 73 | /// @param {Number} $unitQuantity Fixed nondimensional units. 74 | /// @return {Length} A calculated rem value. 75 | /// @example scss 76 | /// button { 77 | /// @include media-query('sm') { 78 | /// max-width: get-fixed-size(10); 79 | /// } 80 | /// } 81 | /// @output css 82 | /// @media screen and (min-width: 20rem) { 83 | /// button { 84 | /// max-width: 5rem; 85 | /// } 86 | /// } 87 | @function get-fixed-size($unitQuantity) { 88 | // Derive the base unit from the current row height of the grid 89 | $fixedUnit: map-get($grid-values, "rowHeight"); 90 | 91 | @if ($fixedUnit == null or type-of($fixedUnit) != "number") { 92 | @error "The rowHeight in $grid-values needs be a valid number. Please check your grid configuration."; 93 | } 94 | 95 | @if ($unitQuantity == null or type-of($unitQuantity) != "number") { 96 | @error "The provided fixed value `#{$unitQuantity}` to get-fixed-size() needs to be a valid number greater than 0."; 97 | } 98 | 99 | @return $unitQuantity * $fixedUnit * 1rem; 100 | } 101 | 102 | /// Utility for declaring mobile-first media queries. 103 | /// @param {String} $breakpointName The name of the breakpoint to set its width value to media query. 104 | @mixin media-query($breakpointName) { 105 | $breakpointValue: get-breakpoint-value($breakpointName); 106 | @if $breakpointValue == map-get($first, breakpoint) { 107 | @content; 108 | } @else { 109 | @media screen and (min-width: #{$breakpointValue}) { 110 | @content; 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /examples/carbon/css-gridish/scss/_values.scss: -------------------------------------------------------------------------------- 1 | $grid-values: ( 2 | prefix: bx, 3 | breakpoints: ( 4 | sm: ( 5 | breakpoint: 20, 6 | columns: 12, 7 | gutter: 1.250rem, 8 | margin: 5vw 9 | ), 10 | xxl: ( 11 | breakpoint: 100, 12 | columns: 12, 13 | gutter: 1.250rem, 14 | margin: 5vw 15 | ) 16 | ), 17 | extraArtboards: ( 18 | md: 48, 19 | lg: 62, 20 | xl: 75 21 | ), 22 | rem: 16, 23 | rowHeight: 0.5, 24 | rows: 30, 25 | paths: null 26 | ); -------------------------------------------------------------------------------- /examples/carbon/css-gridish/scss/_variables.scss: -------------------------------------------------------------------------------- 1 | @import "values"; 2 | 3 | $prefix: gridish !default; 4 | @if map-get($grid-values, "prefix") and $prefix == "gridish" { 5 | $prefix: map-get($grid-values, "prefix"); 6 | } 7 | $extraBreakpoints: () !default; 8 | $breakpoints: add-padding(map-get($grid-values, "breakpoints")); 9 | $first: nth(nth($breakpoints, 1), 2); 10 | $last: nth(nth($breakpoints, -1), 2); 11 | $includeFlexFallback: false !default; 12 | $rowHeight: map-get($grid-values, "rowHeight"); 13 | $rows: map-get($grid-values, "rows"); 14 | $extraArtboards: map-get($grid-values, "extraArtboards"); 15 | $allBreakpoints: all-breakpoints( 16 | $breakpoints, 17 | $extraBreakpoints, 18 | $first, 19 | $last 20 | ); 21 | $breakpointsAndArtboards: all-breakpoints( 22 | $breakpoints, 23 | $extraArtboards, 24 | $first, 25 | $last 26 | ); 27 | -------------------------------------------------------------------------------- /examples/carbon/css-gridish/scss/bx-grid-legacy.scss: -------------------------------------------------------------------------------- 1 | $includeFlexFallback: true; 2 | @import "core.scss"; 3 | 4 | @supports (display: grid) { 5 | .#{$prefix}-grid > *, 6 | .#{$prefix}-grid > [class*="#{$prefix}-grid__col--"] { 7 | min-width: initial; 8 | max-width: initial; 9 | width: initial; 10 | 11 | &.#{$prefix}-grid { 12 | display: grid; 13 | } 14 | } 15 | 16 | .#{$prefix}-grid > [class*="#{$prefix}-grid__height--"] { 17 | height: unset; 18 | max-height: unset; 19 | min-height: initial; 20 | } 21 | } 22 | 23 | .#{$prefix}-grid > script { 24 | display: none; 25 | } 26 | -------------------------------------------------------------------------------- /examples/carbon/css-gridish/scss/bx-grid.scss: -------------------------------------------------------------------------------- 1 | @import "core.scss"; 2 | -------------------------------------------------------------------------------- /examples/carbon/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 42 | 43 | 44 | 45 |
46 |

CSS Gridish

47 |

Carbon Example

48 | 49 | 50 |
51 | 52 | 53 |
54 |
55 |

Learn more about 56 | CSS Gridish. 57 |

58 |

Also check out our examples of CSS Gridish making grid code for 59 | Bootstrap and 60 | Material. 61 |

62 |
63 | 64 | 89 | 90 | -------------------------------------------------------------------------------- /examples/carbon/intro.md: -------------------------------------------------------------------------------- 1 | # Carbon Design Grid 2 | 3 | An example of [CSS Gridish](../../../README.md) generating CSS Grid code, fallback flexbox code, dev documentation, and Sketch files based on the [Carbon Design System grid.](https://github.com/carbon-design-system/carbon-components/blob/master/src/globals/grid/_grid.scss#L29-L31) 4 | -------------------------------------------------------------------------------- /examples/carbon/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-gridish-example-carbon", 3 | "version": "0.0.1", 4 | "engines": { 5 | "node": ">=8.2.0" 6 | }, 7 | "repository": { 8 | "type": "git", 9 | "url": "git@ibm.com:ibm/css-gridish.git" 10 | }, 11 | "author": "James Y. Rauhut ", 12 | "license": "Apache-2.0", 13 | "scripts": { 14 | "build": "node ../../bin/index.js", 15 | "test": "true" 16 | }, 17 | "dependencies": {} 18 | } 19 | -------------------------------------------------------------------------------- /examples/carbon/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/material/README.md: -------------------------------------------------------------------------------- 1 | # CSS Gridish: Material Design Example 2 | 3 | [View a random layout with this grid.](https://ibm.github.io/css-gridish/examples/material/index.html) 4 | 5 | [View a UI layout with this grid, including a CSS Flexbox fallback.](https://ibm.github.io/css-gridish/examples/material/example.html) 6 | 7 | An example of [CSS Gridish](../../README.md) generating CSS Grid code, fallback flexbox code, dev documentation, and Sketch files based on [Material Design’s grid.](https://material.io/guidelines/layout/responsive-ui.html#responsive-ui-grid) 8 | 9 | Check out everything CSS Gridish made based off of the [config file](./css-gridish.json) in the [css-gridish folder.](./css-gridish/) 10 | -------------------------------------------------------------------------------- /examples/material/css-gridish.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "material", 3 | "breakpoints": { 4 | "xsmall": { 5 | "breakpoint": 22.5, 6 | "columns": 4, 7 | "gutter": "1rem", 8 | "margin": 0 9 | }, 10 | "small": { 11 | "breakpoint": 37.5, 12 | "columns": 8, 13 | "gutter": "1rem", 14 | "margin": 0 15 | }, 16 | "medium": { 17 | "breakpoint": 64, 18 | "columns": 12, 19 | "gutter": "2rem", 20 | "margin": 0 21 | }, 22 | "xlarge": { 23 | "breakpoint": 120, 24 | "columns": 12, 25 | "gutter": "2rem", 26 | "margin": 0 27 | } 28 | }, 29 | "extraArtboards": { 30 | "large": 90 31 | }, 32 | "rem": 16, 33 | "rowHeight": 0.5, 34 | "rows": 30, 35 | "paths": { 36 | "intro": "intro.md" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/material/css-gridish/material-grid.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/css-gridish/c5f16a541df485fa833f8f50299bd6a3f290a142/examples/material/css-gridish/material-grid.sketch -------------------------------------------------------------------------------- /examples/material/css-gridish/scss/_core.scss: -------------------------------------------------------------------------------- 1 | @import "functions.scss"; 2 | @import "mixins.scss"; 3 | @import "variables.scss"; 4 | @import "utilities.scss"; 5 | 6 | html { 7 | font-size: map-get($grid-values, "rem") * 1px; 8 | } 9 | 10 | body { 11 | margin: 0; 12 | } 13 | 14 | .#{$prefix}-container { 15 | box-sizing: border-box; 16 | margin-left: auto; 17 | margin-right: auto; 18 | max-width: #{map-get($last, breakpoint)}rem; 19 | overflow-x: hidden; 20 | width: 100vw; 21 | } 22 | 23 | .#{$prefix}-container--left { 24 | margin-left: 0; 25 | } 26 | 27 | .#{$prefix}-container--right { 28 | margin-right: 0; 29 | } 30 | 31 | .#{$prefix}-grid { 32 | align-items: flex-start; 33 | box-sizing: border-box; 34 | @if $includeFlexFallback { 35 | display: flex; 36 | } 37 | display: grid; 38 | flex-wrap: wrap; 39 | position: relative; 40 | 41 | > * { 42 | box-sizing: border-box; 43 | 44 | :last-child, 45 | :last-child > :last-child, 46 | :last-child > :last-child > :last-child { 47 | margin-bottom: 0; 48 | } 49 | } 50 | } 51 | 52 | [class*="#{$prefix}-padding"] { 53 | box-sizing: border-box; 54 | } 55 | 56 | // Rules needed in legacy, but needed to change in CSS Grid 57 | @if $includeFlexFallback { 58 | .#{$prefix}-grid > * { 59 | width: 100%; 60 | } 61 | 62 | @supports (display: grid) { 63 | .#{$prefix}-grid { 64 | align-items: unset; 65 | } 66 | 67 | .#{$prefix}-grid > * { 68 | width: initial; 69 | } 70 | } 71 | } 72 | 73 | // Rules not needed in legacy, but needed in CSS Grid 74 | @supports (display: grid) { 75 | .#{$prefix}-grid > * { 76 | height: 100%; 77 | } 78 | } 79 | 80 | @include grid-legacy-wrapper($includeFlexFallback) { 81 | :root { 82 | @include grid-heights-fixed($rows); 83 | } 84 | } 85 | 86 | @each $name, $breakpoint in $allBreakpoints { 87 | @include media-query($name) { 88 | @if is-same-breakpoint($breakpoint, $last) == false { 89 | @include grid-legacy-heights($name); 90 | } 91 | @include grid-legacy-zeros($breakpoint, $name); 92 | @include grid-padding($breakpoint); 93 | @include grid($breakpoint, $name); 94 | @include grid-legacy-columns($breakpoint, $name); 95 | 96 | // Wrap all bleed/break classes and css variables in a CSS Grid support query 97 | @include grid-legacy-wrapper($includeFlexFallback) { 98 | @include grid-margin($breakpoint, $name); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /examples/material/css-gridish/scss/_functions.scss: -------------------------------------------------------------------------------- 1 | @import "sass-list-maps"; 2 | 3 | // Transform the gutter property into a padding property for web 4 | @function add-padding($breakpoints) { 5 | $cleanBreakpoints: (); 6 | @each $name, $breakpoint in $breakpoints { 7 | $cleanBreakpoints: map-merge( 8 | $cleanBreakpoints, 9 | ( 10 | $name: 11 | map-merge($breakpoint, (padding: map-get($breakpoint, gutter) / 2)) 12 | ) 13 | ); 14 | } 15 | 16 | @return $cleanBreakpoints; 17 | } 18 | 19 | // Merge standard and custom breakpoints into list 20 | @function all-breakpoints($breakpoints, $extraBreakpoints, $first, $last) { 21 | $allBreakpoints: $breakpoints; 22 | @each $currentBreakpoint in $extraBreakpoints { 23 | $extraBreakpointName: nth($currentBreakpoint, 1); 24 | $extraBreakpointWidth: nth($currentBreakpoint, 2); 25 | $found: false; 26 | $match: null; 27 | @each $majorBreakpoint in $breakpoints { 28 | @if $found == false { 29 | @if map-get(nth($majorBreakpoint, 2), breakpoint) > 30 | $extraBreakpointWidth 31 | { 32 | $found: true; 33 | } @else { 34 | $match: $majorBreakpoint; 35 | } 36 | } 37 | } 38 | @if $extraBreakpointWidth > map-get($last, breakpoint) { 39 | $match: ( 40 | last, 41 | $last 42 | ); 43 | } 44 | @if $extraBreakpointWidth < map-get($first, breakpoint) { 45 | $match: ( 46 | first, 47 | $first 48 | ); 49 | } 50 | 51 | $newBreakpoint: map-merge( 52 | nth($match, 2), 53 | (breakpoint: $extraBreakpointWidth) 54 | ); 55 | $currentBreakpoint: ( 56 | $extraBreakpointName: 57 | map-merge(nth($match, 2), (breakpoint: $extraBreakpointWidth)) 58 | ); 59 | $allBreakpoints: map-merge($allBreakpoints, $currentBreakpoint); 60 | } 61 | 62 | @return maps-sort($allBreakpoints, breakpoint); 63 | } 64 | 65 | @function is-same-breakpoint($a, $b) { 66 | @return map-get($a, breakpoint) == map-get($b, breakpoint); 67 | } 68 | 69 | /// Traverse maps and retrieve deeply nested values: https://css-tricks.com/snippets/sass/deep-getset-maps/ 70 | /// @author Hugo Giraudel 71 | /// @param {Map} $map A sass map and any number of keys. 72 | /// @param {*} $keys Nested values. 73 | /// @return Nested values or nested map. 74 | @function map-deep-get($map, $keys...) { 75 | @each $key in $keys { 76 | $map: map-get($map, $key); 77 | } 78 | @return $map; 79 | } 80 | 81 | // _decimal.scss | MIT License | gist.github.com/terkel/4373420 82 | @function round-decimal($number, $digits: 0, $mode: round) { 83 | $n: 1; 84 | // $number must be a number 85 | @if type-of($number) != number { 86 | @warn "#{ $number } is not a number."; 87 | @return $number; 88 | } 89 | // $digits must be a unitless number 90 | @if type-of($digits) != number { 91 | @warn "#{ $digits } is not a number."; 92 | @return $number; 93 | } @else if not unitless($digits) { 94 | @warn "#{ $digits } has a unit."; 95 | @return $number; 96 | } 97 | @for $i from 1 through $digits { 98 | $n: $n * 10; 99 | } 100 | @if $mode == round { 101 | @return round($number * $n) / $n; 102 | } @else if $mode == ceil { 103 | @return ceil($number * $n) / $n; 104 | } @else if $mode == floor { 105 | @return floor($number * $n) / $n; 106 | } @else { 107 | @warn "#{ $mode } is undefined keyword."; 108 | @return $number; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /examples/material/css-gridish/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Set the width of a grid’s column 2 | @mixin grid($breakpoint, $breakpointName) { 3 | @if (map-get($breakpoint, columns) != null) { 4 | $columnSize: get-fluid-size($breakpointName, 1); 5 | 6 | .#{$prefix}-grid { 7 | @if is-same-breakpoint($breakpoint, $first) { 8 | grid-auto-rows: minmax($rowHeight * 1rem, min-content); 9 | } 10 | grid-template-columns: repeat(auto-fill, $columnSize); 11 | 12 | &.#{$prefix}-grid--fixed-columns { 13 | grid-template-columns: repeat( 14 | auto-fill, 15 | map-get($breakpoint, breakpoint) * 16 | 1rem / 17 | map-get($breakpoint, columns) 18 | ); 19 | } 20 | 21 | &.#{$prefix}-grid--fluid-rows { 22 | grid-auto-rows: $columnSize; 23 | } 24 | 25 | @if is-same-breakpoint($breakpoint, $last) == false { 26 | > * { 27 | grid-column: span #{map-get($breakpoint, columns)}; 28 | } 29 | } 30 | } 31 | } 32 | } 33 | 34 | // Generate variables for commonly used rows 35 | @mixin grid-heights-fixed($rows) { 36 | @for $i from 1 to $rows { 37 | --#{$prefix}-height-#{$i}: get-fixed-size($i); 38 | } 39 | } 40 | 41 | // Set the width of a grid’s column for legacy grid 42 | @mixin grid-legacy-columns($breakpoint, $name) { 43 | // Do not make class if last media query 44 | @if is-same-breakpoint($breakpoint, $last) == false { 45 | // Loop each breakpoint to insert previous breakpoint classes inside this breakpoint’s media query 46 | // Ex: Make sure .yourPrefix-grid__col--sm--2 has correct sizes in the lg media query 47 | @each $currentName, $currentBreakpoint in $allBreakpoints { 48 | // Check if current breakpoint is not bigger than current media query 49 | @if map-get($breakpoint, breakpoint) >= 50 | map-get($currentBreakpoint, breakpoint) 51 | { 52 | // Loop each column in current breakpoint for new class 53 | // Ex: .yourPrefix-grid__col--sm--1, .yourPrefix-grid__col--sm--2, etc. 54 | @for $i from 1 through map-get($currentBreakpoint, columns) { 55 | $columnMultiplier: $i * 56 | map-get($breakpoint, columns) / 57 | map-get($currentBreakpoint, columns); 58 | $columnSize: get-fluid-size($name, $columnMultiplier); 59 | 60 | $isSecondToLast: is-same-breakpoint( 61 | $breakpoint, 62 | nth(nth($allBreakpoints, length($allBreakpoints) - 1), 2) 63 | ); 64 | 65 | $maxColumnSize: get-fluid-size( 66 | nth(nth($allBreakpoints, length($allBreakpoints)), 1), 67 | $columnMultiplier 68 | ); 69 | 70 | .#{$prefix}-grid__col--#{$currentName}--#{$i} { 71 | @if $includeFlexFallback { 72 | // If second-to-last media query, apply max-width instead of remaking classes in last media query 73 | @if $isSecondToLast { 74 | max-width: $maxColumnSize; 75 | } 76 | width: $columnSize; 77 | } 78 | grid-column: span #{$columnMultiplier}; 79 | 80 | @if is-same-breakpoint($breakpoint, $last) == false { 81 | &.#{$prefix}-grid > *:not([class*="#{$prefix}-grid__col"]) { 82 | grid-column: span #{$i}; 83 | } 84 | } 85 | } 86 | 87 | .#{$prefix}-grid--fluid-rows 88 | > .#{$prefix}-grid__height--#{$currentName}--#{$i} { 89 | grid-row: span $i; 90 | @if $includeFlexFallback { 91 | height: $columnSize; 92 | min-height: $columnSize; 93 | // If second-to-last media query, apply max-height instead of remaking classes in last media query 94 | @if $isSecondToLast { 95 | max-height: $maxColumnSize; 96 | } 97 | } 98 | } 99 | } 100 | } 101 | } 102 | } 103 | 104 | @if $includeFlexFallback { 105 | @if is-same-breakpoint($breakpoint, $last) { 106 | [class*="#{$prefix}-grid__col--"] { 107 | min-width: 0; 108 | } 109 | } 110 | } 111 | } 112 | 113 | // Set the height of an item for legacy grid 114 | @mixin grid-legacy-heights($name) { 115 | .#{$prefix}-grid__height--#{$name}--0 { 116 | height: 0; 117 | min-height: 0; 118 | } 119 | @for $i from 1 to $rows { 120 | .#{$prefix}-grid__height--#{$name}--#{$i} { 121 | grid-row: span $i; 122 | @if $includeFlexFallback { 123 | height: get-fixed-size($i); 124 | min-height: get-fixed-size($i); 125 | } 126 | } 127 | } 128 | } 129 | 130 | // If we need legacy grid, wrap this content in support tag 131 | @mixin grid-legacy-wrapper($includeFlexFallback) { 132 | @if $includeFlexFallback { 133 | @supports (display: grid) { 134 | @content; 135 | } 136 | } @else { 137 | @content; 138 | } 139 | } 140 | 141 | // Generate all classes for 0 and 0-only displaying, including custom breakpoints if they exist 142 | @mixin grid-legacy-zeros($breakpoint, $name) { 143 | // Undo previous breakpoint’s 0--only class 144 | @for $i from length($allBreakpoints) * -1 through -1 { 145 | $currentBreakpoint: nth($allBreakpoints, $i); 146 | @if map-get(nth($currentBreakpoint, 2), breakpoint) < 147 | map-get($breakpoint, breakpoint) 148 | { 149 | .#{$prefix}-grid__col--#{nth($currentBreakpoint, 1)}--0--only { 150 | display: block; 151 | } 152 | } 153 | } 154 | 155 | [class*="#{$prefix}-grid__col--#{$name}--"] { 156 | display: block; 157 | } 158 | 159 | .#{$prefix}-grid__col--#{$name}--0, 160 | .#{$prefix}-grid__col--#{$name}--0--only { 161 | display: none; 162 | } 163 | } 164 | 165 | // Set the width of a grid’s margin 166 | // and allow for a child to break out of the grid’s margin 167 | @mixin grid-margin($breakpoint, $name) { 168 | $nameToUse: $name; 169 | $margin: #{map-get($breakpoint, margin)}; 170 | $padding: #{map-get($breakpoint, padding)}; 171 | 172 | // If last breakpoint, we use the previous breakpoint name 173 | // to treat the last breakpoint as the max-width of the previous breakpoint 174 | @if is-same-breakpoint($breakpoint, $last) == true { 175 | $previousBreakpoint: nth( 176 | $allBreakpoints, 177 | index(map-keys($allBreakpoints), $name) - 1 178 | ); 179 | $nameToUse: nth($previousBreakpoint, 1); 180 | } 181 | 182 | // Undo previous breakpoint’s bleeds and breaks 183 | @if is-same-breakpoint($breakpoint, $first) == 184 | false and 185 | is-same-breakpoint($breakpoint, $last) == 186 | false 187 | { 188 | $previousBreakpoint: nth( 189 | $allBreakpoints, 190 | index(map-keys($allBreakpoints), $name) - 1 191 | ); 192 | $previousName: nth($previousBreakpoint, 1); 193 | $previousMargin: map-get(nth($previousBreakpoint, 2), margin); 194 | 195 | @if $previousMargin != 196 | null and 197 | $previousMargin != 198 | 0 and 199 | $previousMargin != 200 | "0" 201 | { 202 | [class^="#{$prefix}-container__bleed--#{$previousName}"], 203 | [class^="#{$prefix}-container__break--#{$previousName}"] { 204 | margin-left: 0; 205 | margin-right: 0; 206 | padding-left: 0; 207 | padding-right: 0; 208 | 209 | &[class^="#{$prefix}-padding"] { 210 | padding-left: $padding; 211 | padding-right: $padding; 212 | } 213 | } 214 | } 215 | } 216 | 217 | @if $margin != null and $margin != 0 and $margin != "0" { 218 | $marginPlusPadding: calc(#{$margin} + #{$padding}); 219 | @if $margin == "0" and $padding == "0" { 220 | $marginPlusPadding: 0; 221 | } @else if $margin == "0" { 222 | $marginPlusPadding: $padding; 223 | } @else if $padding == "0" { 224 | $marginPlusPadding: $margin; 225 | } 226 | 227 | .#{$prefix}-container { 228 | margin-left: auto; 229 | margin-right: auto; 230 | padding-left: $margin; 231 | padding-right: $margin; 232 | } 233 | 234 | .#{$prefix}-container--left { 235 | margin-left: 0; 236 | } 237 | 238 | .#{$prefix}-container--right { 239 | margin-right: 0; 240 | } 241 | 242 | .#{$prefix}-container__bleed--#{$nameToUse}, 243 | .#{$prefix}-container__bleed--#{$nameToUse}--left, 244 | .#{$prefix}-container__break--#{$nameToUse}, 245 | .#{$prefix}-container__break--#{$nameToUse}--left { 246 | margin-left: -#{$margin}; 247 | } 248 | 249 | .#{$prefix}-container__bleed--#{$nameToUse}, 250 | .#{$prefix}-container__bleed--#{$nameToUse}--right, 251 | .#{$prefix}-container__break--#{$nameToUse}, 252 | .#{$prefix}-container__break--#{$nameToUse}--right { 253 | margin-right: -#{$margin}; 254 | } 255 | 256 | .#{$prefix}-container__bleed--#{$nameToUse}, 257 | .#{$prefix}-container__bleed--#{$nameToUse}--left { 258 | padding-left: $margin; 259 | 260 | &.#{$prefix}-padding, 261 | &.#{$prefix}-padding--horizontal, 262 | &.#{$prefix}-padding--left { 263 | padding-left: $marginPlusPadding; 264 | } 265 | } 266 | 267 | .#{$prefix}-container__bleed--#{$nameToUse}, 268 | .#{$prefix}-container__bleed--#{$nameToUse}--right { 269 | padding-right: $margin; 270 | 271 | &.#{$prefix}-padding, 272 | &.#{$prefix}-padding--horizontal, 273 | &.#{$prefix}-padding--right { 274 | padding-right: $marginPlusPadding; 275 | } 276 | } 277 | } 278 | } 279 | 280 | // Classnames for different padding options 281 | @mixin grid-padding($breakpoint) { 282 | @if (map-get($breakpoint, padding) != null) { 283 | $padding: map-get($breakpoint, padding); 284 | 285 | .#{$prefix}-padding { 286 | padding: $padding; 287 | } 288 | 289 | .#{$prefix}-padding--bottom { 290 | padding-bottom: $padding; 291 | } 292 | 293 | .#{$prefix}-padding--left { 294 | padding-left: $padding; 295 | } 296 | 297 | .#{$prefix}-padding--right { 298 | padding-right: $padding; 299 | } 300 | 301 | .#{$prefix}-padding--top { 302 | padding-top: $padding; 303 | } 304 | 305 | .#{$prefix}-padding--horizontal { 306 | padding-left: $padding; 307 | padding-right: $padding; 308 | } 309 | 310 | .#{$prefix}-padding--vertical { 311 | padding-bottom: $padding; 312 | padding-top: $padding; 313 | } 314 | } 315 | } 316 | -------------------------------------------------------------------------------- /examples/material/css-gridish/scss/_sass-list-maps.scss: -------------------------------------------------------------------------------- 1 | /// _ 2 | /// | | 3 | /// ___ __ _ ___ ___ ______ _ __ ___ __ _ _ __ ___ ______ _ __ | |_ _ ___ 4 | /// / __|/ _` / __/ __|______| '_ ` _ \ / _` | '_ \/ __|______| '_ \| | | | / __| 5 | /// \__ \ (_| \__ \__ \ | | | | | | (_| | |_) \__ \ | |_) | | |_| \__ \ 6 | /// |___/\__,_|___/___/ |_| |_| |_|\__,_| .__/|___/ | .__/|_|\__,_|___/ 7 | /// | | | | 8 | /// |_| |_| 9 | /// Sass Maps Plus 0.9.2 10 | /// Advanced map and list-map manipulation for all versions of Sass 11 | /// MIT License 12 | /// @author Lu Nelson 13 | 14 | /// Global sort direction: either `asc` or `desc` 15 | /// @access public 16 | /// @group map-lists/map-maps 17 | $maps-sort-dir: "asc"; 18 | 19 | /// get value at nested or 'deep' key, per $keys list 20 | /// @access public 21 | /// @group maps 22 | /// @param {Map} $map - map 23 | /// @param {Arglist} $keys - nested keys 24 | /// @return {*} 25 | @function map-get-nested($map, $keys...) { 26 | @if length($map) == 0 { 27 | @return null; 28 | } 29 | @each $key in $keys { 30 | @if type-of($map) != "map" { 31 | @return $map; 32 | } 33 | $map: map-get($map, $key); 34 | } 35 | @return $map; 36 | } 37 | 38 | /// Sort a list-of-maps or map-of-maps, based on value at key(s) in maps 39 | /// @access public 40 | /// @group map-lists/map-maps 41 | /// @param {Map|List} $maps - Map of maps, or List of maps, to sort 42 | /// @param {Arglist} $keys - Chain of keys to the value that will be sorted for 43 | /// @return {Map|List} 44 | /// @require {function} map-get-nested 45 | @function maps-sort($maps, $keys...) { 46 | @if length($keys) == 0 { 47 | @return $maps; 48 | } 49 | 50 | @if length($maps) > 1 { 51 | $less: (); 52 | $equal: (); 53 | $greater: (); 54 | 55 | $map-of-maps: type-of($maps) == "map"; 56 | 57 | @if $map-of-maps { 58 | $seed-map: nth(nth($maps, ceil(length($maps) / 2)), 2); 59 | 60 | $seed-value: map-get-nested($seed-map, $keys...); 61 | 62 | // TODO: add code to handle case of non-number values (warn and return $maps) 63 | 64 | @each $key, $map in $maps { 65 | $curr-value: map-get-nested($map, $keys...); 66 | 67 | @if $curr-value == $seed-value { 68 | $equal: map-merge($equal, ($key: $map)); 69 | } @else if $curr-value < $seed-value { 70 | @if $maps-sort-dir == "asc" { 71 | $less: map-merge($less, ($key: $map)); 72 | } @else { 73 | $greater: map-merge($greater, ($key: $map)); 74 | } 75 | } @else { 76 | @if $maps-sort-dir == "asc" { 77 | $greater: map-merge($greater, ($key: $map)); 78 | } @else { 79 | $less: map-merge($less, ($key: $map)); 80 | } 81 | } 82 | } 83 | 84 | $less: maps-sort($less, $keys...); 85 | $greater: maps-sort($greater, $keys...); 86 | 87 | @return map-merge(map-merge($less, $equal), $greater); 88 | } @else { 89 | $seed-map: nth($maps, ceil(length($maps) / 2)); 90 | 91 | $seed-value: map-get-nested($seed-map, $keys...); 92 | 93 | @each $map in $maps { 94 | $curr-value: map-get-nested($map, $keys...); 95 | 96 | @if $curr-value == $seed-value { 97 | $equal: append($equal, $map); 98 | } @else if $curr-value < $seed-value { 99 | @if $maps-sort-dir == "asc" { 100 | $less: append($less, $map); 101 | } @else { 102 | $greater: append($greater, $map); 103 | } 104 | } @else { 105 | @if $maps-sort-dir == "asc" { 106 | $greater: append($greater, $map); 107 | } @else { 108 | $less: append($less, $map); 109 | } 110 | } 111 | } 112 | 113 | $less: maps-sort($less, $keys...); 114 | $greater: maps-sort($greater, $keys...); 115 | 116 | @return join(join($less, $equal), $greater); 117 | } 118 | } 119 | 120 | @return $maps; 121 | } 122 | -------------------------------------------------------------------------------- /examples/material/css-gridish/scss/_utilities.scss: -------------------------------------------------------------------------------- 1 | @import "functions"; 2 | @import "values"; 3 | @import "variables"; 4 | 5 | /// Function returns the value for a given breakpoint. 6 | /// @param {String} $breakpointName Breakpoint name. 7 | /// @return {Length} The breakpoint value in rems. 8 | @function get-breakpoint-value($breakpointName) { 9 | $breakpointValue: map-deep-get( 10 | $breakpointsAndArtboards, 11 | $breakpointName, 12 | "breakpoint" 13 | ); 14 | 15 | @return $breakpointValue * 1rem; 16 | } 17 | 18 | /// Returns a calc() expression that represents a fluid width at a given breakpoint. 19 | /// @param {String} $breakpointName A valid breakpoint. 20 | /// @param {Number} $columnSpan The number of columns to span across. 21 | /// @return {Length} A calc() expression representing fluid width. 22 | /// @example scss 23 | /// button { 24 | /// @include media-query('sm') { 25 | /// max-width: get-fluid-size('sm', 1); 26 | /// } 27 | /// } 28 | /// @output css 29 | /// @media screen and (min-width: 20rem) { 30 | /// button { 31 | /// max-width: 25vw; 32 | /// } 33 | /// } 34 | @function get-fluid-size($breakpointName, $columnSpan) { 35 | $breakpoint: map-get($breakpointsAndArtboards, $breakpointName); 36 | 37 | @if ($breakpoint == null or type-of($breakpoint) != "map") { 38 | @error "The provided breakpoint `#{$breakpointName}` is not a valid breakpoint found in breakpoints or extraArtboards in $grid-values. Please double-check your grid configuration."; 39 | } 40 | 41 | $columnTotal: map-get($breakpoint, columns); 42 | $margin: map-get($breakpoint, margin); 43 | 44 | @if ($columnTotal == null or type-of($columnTotal) != "number") { 45 | @error "The provided breakpoint `#{$breakpointName}` needs to have a total number of columns set in $grid-values. Please double-check your grid configuration."; 46 | } 47 | 48 | @if ($columnSpan == null or type-of($columnSpan) != "number") { 49 | @error "The number of columns to span for the breakpoint `#{$breakpointName}` must be a valid number. The provided column span value `#{$columnSpan}` is not a number"; 50 | } 51 | 52 | @if ($columnSpan > $columnTotal or $columnSpan <= 0) { 53 | @error "The number of columns to span for the breakpoint `#{$breakpointName}` must be greater than 0 and less than or equal to the total number of columns for this breakpoint. The provided column value `#{$columnSpan}` does not meet this criteria"; 54 | } 55 | 56 | $container: 100vw; 57 | // Last breakpoint is a max-width and should be a fixed number 58 | @if is-same-breakpoint($breakpoint, $last) { 59 | $container: map-get($breakpoint, breakpoint) * 1rem; 60 | } 61 | 62 | $multiplier: round-decimal($columnSpan / $columnTotal, 4, floor); 63 | 64 | // For IE, we can't have a 0 in the $fluidWidth calc(). 65 | @if ($margin == 0) { 66 | @return $container * $multiplier; 67 | } 68 | 69 | @return calc((#{$container} - #{$margin * 2}) * #{$multiplier}); 70 | } 71 | 72 | /// Function gets a calculated rem value for a fixed size. 73 | /// @param {Number} $unitQuantity Fixed nondimensional units. 74 | /// @return {Length} A calculated rem value. 75 | /// @example scss 76 | /// button { 77 | /// @include media-query('sm') { 78 | /// max-width: get-fixed-size(10); 79 | /// } 80 | /// } 81 | /// @output css 82 | /// @media screen and (min-width: 20rem) { 83 | /// button { 84 | /// max-width: 5rem; 85 | /// } 86 | /// } 87 | @function get-fixed-size($unitQuantity) { 88 | // Derive the base unit from the current row height of the grid 89 | $fixedUnit: map-get($grid-values, "rowHeight"); 90 | 91 | @if ($fixedUnit == null or type-of($fixedUnit) != "number") { 92 | @error "The rowHeight in $grid-values needs be a valid number. Please check your grid configuration."; 93 | } 94 | 95 | @if ($unitQuantity == null or type-of($unitQuantity) != "number") { 96 | @error "The provided fixed value `#{$unitQuantity}` to get-fixed-size() needs to be a valid number greater than 0."; 97 | } 98 | 99 | @return $unitQuantity * $fixedUnit * 1rem; 100 | } 101 | 102 | /// Utility for declaring mobile-first media queries. 103 | /// @param {String} $breakpointName The name of the breakpoint to set its width value to media query. 104 | @mixin media-query($breakpointName) { 105 | $breakpointValue: get-breakpoint-value($breakpointName); 106 | @if $breakpointValue == map-get($first, breakpoint) { 107 | @content; 108 | } @else { 109 | @media screen and (min-width: #{$breakpointValue}) { 110 | @content; 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /examples/material/css-gridish/scss/_values.scss: -------------------------------------------------------------------------------- 1 | $grid-values: ( 2 | prefix: material, 3 | breakpoints: ( 4 | xsmall: ( 5 | breakpoint: 22.5, 6 | columns: 4, 7 | gutter: 1rem, 8 | margin: 0 9 | ), 10 | small: ( 11 | breakpoint: 37.5, 12 | columns: 8, 13 | gutter: 1rem, 14 | margin: 0 15 | ), 16 | medium: ( 17 | breakpoint: 64, 18 | columns: 12, 19 | gutter: 2rem, 20 | margin: 0 21 | ), 22 | xlarge: ( 23 | breakpoint: 120, 24 | columns: 12, 25 | gutter: 2rem, 26 | margin: 0 27 | ) 28 | ), 29 | extraArtboards: ( 30 | large: 90 31 | ), 32 | rem: 16, 33 | rowHeight: 0.5, 34 | rows: 30, 35 | paths: null 36 | ); -------------------------------------------------------------------------------- /examples/material/css-gridish/scss/_variables.scss: -------------------------------------------------------------------------------- 1 | @import "values"; 2 | 3 | $prefix: gridish !default; 4 | @if map-get($grid-values, "prefix") and $prefix == "gridish" { 5 | $prefix: map-get($grid-values, "prefix"); 6 | } 7 | $extraBreakpoints: () !default; 8 | $breakpoints: add-padding(map-get($grid-values, "breakpoints")); 9 | $first: nth(nth($breakpoints, 1), 2); 10 | $last: nth(nth($breakpoints, -1), 2); 11 | $includeFlexFallback: false !default; 12 | $rowHeight: map-get($grid-values, "rowHeight"); 13 | $rows: map-get($grid-values, "rows"); 14 | $extraArtboards: map-get($grid-values, "extraArtboards"); 15 | $allBreakpoints: all-breakpoints( 16 | $breakpoints, 17 | $extraBreakpoints, 18 | $first, 19 | $last 20 | ); 21 | $breakpointsAndArtboards: all-breakpoints( 22 | $breakpoints, 23 | $extraArtboards, 24 | $first, 25 | $last 26 | ); 27 | -------------------------------------------------------------------------------- /examples/material/css-gridish/scss/material-grid-legacy.scss: -------------------------------------------------------------------------------- 1 | $includeFlexFallback: true; 2 | @import "core.scss"; 3 | 4 | @supports (display: grid) { 5 | .#{$prefix}-grid > *, 6 | .#{$prefix}-grid > [class*="#{$prefix}-grid__col--"] { 7 | min-width: initial; 8 | max-width: initial; 9 | width: initial; 10 | 11 | &.#{$prefix}-grid { 12 | display: grid; 13 | } 14 | } 15 | 16 | .#{$prefix}-grid > [class*="#{$prefix}-grid__height--"] { 17 | height: unset; 18 | max-height: unset; 19 | min-height: initial; 20 | } 21 | } 22 | 23 | .#{$prefix}-grid > script { 24 | display: none; 25 | } 26 | -------------------------------------------------------------------------------- /examples/material/css-gridish/scss/material-grid.scss: -------------------------------------------------------------------------------- 1 | @import "core.scss"; 2 | -------------------------------------------------------------------------------- /examples/material/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 111 | 112 | 113 | 114 | 128 |
129 | 146 |
147 |

Cards

148 |
149 |
150 |

Card Title

151 |

Card subtitle or description goes here.

152 |
153 |
154 |

Card Title

155 |

Card subtitle or description goes here.

156 |
157 |
158 |

Card Title

159 |

Card subtitle or description goes here.

160 |
161 |
162 |

Card Title

163 |

Card subtitle or description goes here.

164 |
165 |
166 |

Card Title

167 |

Card subtitle or description goes here.

168 |
169 |
170 |

Card Title

171 |

Card subtitle or description goes here.

172 |
173 |
174 |

Card Title

175 |

Card subtitle or description goes here.

176 |
177 |
178 |

Card Title

179 |

Card subtitle or description goes here.

180 |
181 |
182 |
183 | 184 | 185 | -------------------------------------------------------------------------------- /examples/material/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 32 | 33 | 34 | 35 |
36 |

CSS Gridish

37 |

Material Example

38 | 39 | 40 |
41 | 42 | 43 |
44 |
45 |

Learn more about 46 | CSS Gridish. 47 |

48 |

Also check out our examples of CSS Gridish making grid code for 49 | Bootstrap and 50 | Carbon. 51 |

52 |
53 | 54 | 79 | 80 | -------------------------------------------------------------------------------- /examples/material/intro.md: -------------------------------------------------------------------------------- 1 | # Material Design Grid 2 | 3 | An example of [CSS Gridish](../../../README.md) generating CSS Grid code, fallback flexbox code, dev documentation, and Sketch files based on the [Material breakpoint system.](https://material.io/guidelines/layout/responsive-ui.html) 4 | -------------------------------------------------------------------------------- /examples/material/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-gridish-example-carbon", 3 | "version": "0.0.1", 4 | "engines": { 5 | "node": ">=8.2.0" 6 | }, 7 | "repository": { 8 | "type": "git", 9 | "url": "git@ibm.com:ibm/css-gridish.git" 10 | }, 11 | "author": "James Y. Rauhut ", 12 | "license": "Apache-2.0", 13 | "scripts": { 14 | "build": "node ../../bin/index.js", 15 | "test": "true" 16 | }, 17 | "dependencies": {} 18 | } 19 | -------------------------------------------------------------------------------- /examples/material/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | -------------------------------------------------------------------------------- /extension/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2017 IBM 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. -------------------------------------------------------------------------------- /extension/icons/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/css-gridish/c5f16a541df485fa833f8f50299bd6a3f290a142/extension/icons/icon128.png -------------------------------------------------------------------------------- /extension/icons/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/css-gridish/c5f16a541df485fa833f8f50299bd6a3f290a142/extension/icons/icon16.png -------------------------------------------------------------------------------- /extension/icons/icon19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/css-gridish/c5f16a541df485fa833f8f50299bd6a3f290a142/extension/icons/icon19.png -------------------------------------------------------------------------------- /extension/icons/icon32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/css-gridish/c5f16a541df485fa833f8f50299bd6a3f290a142/extension/icons/icon32.png -------------------------------------------------------------------------------- /extension/icons/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/css-gridish/c5f16a541df485fa833f8f50299bd6a3f290a142/extension/icons/icon48.png -------------------------------------------------------------------------------- /extension/icons/icon64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/css-gridish/c5f16a541df485fa833f8f50299bd6a3f290a142/extension/icons/icon64.png -------------------------------------------------------------------------------- /extension/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CSS Gridish", 3 | "version": "1.0.1", 4 | "manifest_version": 2, 5 | "description": 6 | "Check how a webpage aligns with your grid design generated by CSS Gridish", 7 | "homepage_url": "https://github.com/ibm/css-gridish", 8 | "icons": { 9 | "16": "icons/icon16.png", 10 | "48": "icons/icon48.png", 11 | "128": "icons/icon128.png" 12 | }, 13 | "browser_action": { 14 | "default_title": "CSS Gridish", 15 | "default_popup": "src/browserAction/browserAction.html" 16 | }, 17 | "content_scripts": [ 18 | { 19 | "matches": ["http://*/*", "https://*/*"], 20 | "css": ["src/inject/inject.css"] 21 | }, 22 | { 23 | "matches": ["http://*/*", "https://*/*"], 24 | "js": ["src/inject/inject.js"] 25 | } 26 | ], 27 | "permissions": ["tabs", "storage", "http://*/*", "https://*/*"] 28 | } 29 | -------------------------------------------------------------------------------- /extension/src/browserAction/browserAction.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CSS Gridish 6 | 7 | 26 | 27 | 28 | 29 |
30 |

CSS Gridish

31 |

32 |

Upload your grid’s css-gridish.json to check the alignment of a webpage.

33 |

Press CTRL+G to toggle your grid, CTRL+L to toggle your layout.

34 |

Note: Refreshing already open webpages is necessary after installing CSS Gridish.

35 |

Change grid by uploading new css-gridish.json: 36 | 37 |

38 |
39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /extension/src/browserAction/browserAction.js: -------------------------------------------------------------------------------- 1 | function configChange() { 2 | var fileReader = new FileReader(); 3 | var success = function(content) { 4 | chrome.storage.sync.set({ cssGridish: JSON.parse(content) }, function() { 5 | console.log("Storage Succesful"); 6 | }); 7 | }; 8 | 9 | fileReader.onload = function(evt) { 10 | success(evt.target.result); 11 | }; 12 | fileReader.readAsText(document.getElementById("upload").files[0]); 13 | } 14 | 15 | document.getElementById("upload").addEventListener("change", configChange); 16 | 17 | chrome.storage.sync.get("cssGridish", function(object) { 18 | var gridConfig = object.cssGridish; 19 | if (object.cssGridish === {} || object.cssGridish === undefined) { 20 | chrome.storage.sync.set({ 21 | cssGridish: { 22 | prefix: "bx", 23 | breakpoints: { 24 | sm: { 25 | breakpoint: 20, 26 | columns: 12, 27 | gutter: "1.250rem", 28 | margin: "5vw" 29 | }, 30 | xxl: { 31 | breakpoint: 100, 32 | columns: 12, 33 | gutter: "1.250rem", 34 | margin: "5vw" 35 | } 36 | }, 37 | extraArtboards: { 38 | md: 48, 39 | lg: 62, 40 | xl: 75 41 | }, 42 | rem: 16, 43 | rowHeight: 0.5, 44 | rows: 30, 45 | paths: { 46 | intro: "intro.md" 47 | } 48 | } 49 | }); 50 | } 51 | 52 | document.getElementById("currentGrid").innerText = 53 | "Current grid: " + gridConfig.prefix + "-grid"; 54 | }); 55 | 56 | chrome.storage.onChanged.addListener(function(changes, area) { 57 | if (changes.cssGridish) { 58 | document.getElementById("currentGrid").innerText = 59 | "Current grid: " + changes.cssGridish.newValue.prefix + "-grid"; 60 | } 61 | }); 62 | -------------------------------------------------------------------------------- /extension/src/inject/inject.css: -------------------------------------------------------------------------------- 1 | .css-gridish-checker { 2 | left: 0; 3 | height: 100vh !important; 4 | margin: 0 auto; 5 | pointer-events: none; 6 | position: fixed; 7 | right: 0; 8 | top: 0; 9 | width: 100vw !important; 10 | z-index: 9999; 11 | } 12 | 13 | .css-gridish-checker__grid, 14 | .css-gridish-checker__layout { 15 | height: 100%; 16 | position: absolute; 17 | width: 100%; 18 | } 19 | 20 | .css-gridish-checker__grid { 21 | background: linear-gradient(to right, #c0c6cd 1px, transparent 1px), 22 | linear-gradient(to bottom, #c0c6cd 1px, transparent 1px); 23 | } 24 | 25 | .css-gridish-checker__layout { 26 | box-sizing: border-box; 27 | display: flex; 28 | } 29 | 30 | .css-gridish-checker__layout__col { 31 | background: #b8c1c1; 32 | display: none; 33 | flex: 1; 34 | opacity: 0.75; 35 | } 36 | -------------------------------------------------------------------------------- /extension/src/inject/inject.js: -------------------------------------------------------------------------------- 1 | var checker = document.createElement("div"); 2 | checker.className = "css-gridish-checker"; 3 | 4 | var checkerStyle = document.createElement("style"); 5 | checker.appendChild(checkerStyle); 6 | 7 | var grid = document.createElement("div"); 8 | grid.className = "css-gridish-checker__grid"; 9 | 10 | var layout = document.createElement("div"); 11 | layout.className = "css-gridish-checker__layout"; 12 | 13 | function createCol(breakpoint) { 14 | var col = document.createElement("div"); 15 | col.className = 16 | "css-gridish-checker__layout__col css-gridish-checker__layout__col--" + 17 | breakpoint; 18 | return col; 19 | } 20 | 21 | function createGrid(gridConfig) { 22 | checkerStyle.innerHTML = ""; 23 | grid.innerHTML = ""; 24 | layout.innerHTML = ""; 25 | 26 | var largestBreakpoint = Object.values(gridConfig.breakpoints) 27 | .map(breakpoint => breakpoint.breakpoint) 28 | .sort((a, b) => a - b) 29 | .slice(-1)[0]; 30 | checker.setAttribute( 31 | "style", 32 | "font-size: " + 33 | gridConfig.rem + 34 | "px; max-width: " + 35 | largestBreakpoint + 36 | "em;" 37 | ); 38 | 39 | // rowHeight 40 | var rowHeight = gridConfig.rowHeight; 41 | grid.setAttribute( 42 | "style", 43 | "background-size: " + rowHeight + "rem " + rowHeight + "rem;" 44 | ); 45 | 46 | // breakpoints 47 | var breakpoints = Object.values(gridConfig.breakpoints) 48 | .map((item, index) => { 49 | var result = item; 50 | result.name = Object.keys(gridConfig.breakpoints)[index]; 51 | return result; 52 | }) 53 | .sort((a, b) => a.breakpoint - b.breakpoint); 54 | for (var i = 0; i < breakpoints.length; i++) { 55 | var mediaQuery = 0; 56 | var previous = 0; 57 | if (i > 0) { 58 | previous = breakpoints[i - 1].columns; 59 | mediaQuery = breakpoints[i].breakpoint; 60 | } 61 | var newColumns = breakpoints[i].columns - previous; 62 | for (var j = 0; j < newColumns; j++) { 63 | layout.appendChild(createCol(breakpoints[i].name)); 64 | } 65 | 66 | checkerStyle.innerHTML = 67 | checkerStyle.innerHTML + 68 | ` 69 | @media (min-width: ${mediaQuery}rem) { 70 | .css-gridish-checker__layout { 71 | padding: 0 ${breakpoints[i].margin}; 72 | } 73 | 74 | .css-gridish-checker__layout__col { 75 | margin: 0 ${parseInt(breakpoints[i].gutter, 10) / 2}${ 76 | breakpoints[i].gutter.match(/[a-zA-Z]+/g)[0] 77 | }; 78 | } 79 | 80 | .css-gridish-checker__layout__col--${breakpoints[i].name} { 81 | display: initial; 82 | } 83 | } 84 | `; 85 | } 86 | } 87 | 88 | function toggleCSSGridishChecker(e) { 89 | if (e.ctrlKey && e.keyCode == 71) { 90 | if (!checker.contains(grid)) { 91 | checker.appendChild(grid); 92 | } else { 93 | grid.remove(); 94 | } 95 | } 96 | if (e.ctrlKey && e.keyCode == 76) { 97 | if (!checker.contains(layout)) { 98 | checker.appendChild(layout); 99 | } else { 100 | layout.remove(); 101 | } 102 | } 103 | 104 | if (e.ctrlKey && (e.keyCode == 71 || e.keyCode == 76)) { 105 | if (checker.contains(grid) || checker.contains(layout)) { 106 | document.body.appendChild(checker); 107 | } else { 108 | document.body.removeChild(checker); 109 | } 110 | } 111 | } 112 | 113 | document.addEventListener("keydown", toggleCSSGridishChecker, false); 114 | 115 | chrome.storage.sync.get("cssGridish", function(object) { 116 | var gridConfig = object.cssGridish; 117 | if (object.cssGridish === {} || object.cssGridish === undefined) { 118 | gridConfig = { 119 | prefix: "bx", 120 | breakpoints: { 121 | sm: { 122 | breakpoint: 20, 123 | columns: 12, 124 | gutter: "1.250rem", 125 | margin: "5vw" 126 | }, 127 | xxl: { 128 | breakpoint: 100, 129 | columns: 12, 130 | gutter: "1.250rem", 131 | margin: "5vw" 132 | } 133 | }, 134 | extraArtboards: { 135 | md: 48, 136 | lg: 62, 137 | xl: 75 138 | }, 139 | rem: 16, 140 | rowHeight: 0.5, 141 | rows: 30, 142 | paths: { 143 | intro: "intro.md" 144 | } 145 | }; 146 | } 147 | 148 | createGrid(gridConfig); 149 | }); 150 | 151 | chrome.storage.onChanged.addListener(function(changes, area) { 152 | if (changes.cssGridish) { 153 | createGrid(changes.cssGridish.newValue); 154 | } 155 | }); 156 | -------------------------------------------------------------------------------- /graphics/configDiagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/css-gridish/c5f16a541df485fa833f8f50299bd6a3f290a142/graphics/configDiagram.png -------------------------------------------------------------------------------- /graphics/graphics.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/css-gridish/c5f16a541df485fa833f8f50299bd6a3f290a142/graphics/graphics.sketch -------------------------------------------------------------------------------- /graphics/gridish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/css-gridish/c5f16a541df485fa833f8f50299bd6a3f290a142/graphics/gridish.png -------------------------------------------------------------------------------- /graphics/gridish_3times.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/css-gridish/c5f16a541df485fa833f8f50299bd6a3f290a142/graphics/gridish_3times.gif -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const browserSync = require("browser-sync").create(), 4 | gulp = require("gulp"), 5 | run = require("gulp-run"); 6 | 7 | gulp.task("build", function() { 8 | return run("npm run build").exec(); 9 | }); 10 | 11 | gulp.task("build:examples", function() { 12 | return run("npm run build:examples").exec(); 13 | }); 14 | 15 | gulp.task("refresh", ["build"], function(done) { 16 | browserSync.reload(); 17 | done(); 18 | }); 19 | 20 | gulp.task("refresh:examples", ["build:examples"], function(done) { 21 | browserSync.reload(); 22 | done(); 23 | }); 24 | 25 | gulp.task("watch", function() { 26 | browserSync.init({ 27 | server: { 28 | baseDir: "." 29 | } 30 | }); 31 | 32 | gulp.watch(["**/*.html"]).on("change", browserSync.reload); 33 | gulp.watch("src/**/*", ["refresh"]); 34 | gulp.watch("examples/**/*.json", ["refresh:examples"]); 35 | }); 36 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | CSS Gridish 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 175 | 176 | 177 | 178 |
179 | 180 |
181 |
182 |

CSS Gridish takes design specs of your product’s grid and builds out several resources for your team to use:

183 |
    184 |
  • - Sketch file with artboards and grid/layout settings for designers
  • 185 |
  • - CSS/SCSS code using CSS Grid with a CSS Flexbox fallback for developers
  • 186 |
  • - 187 | Google Chrome extension for anyone to check a webpage’s alignment
  • 189 |
190 |
191 | 196 | 201 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-gridish", 3 | "version": "2.0.0", 4 | "description": 5 | "Automatically build your grid design’s CSS Grid code, CSS Flexbox fallback code, Sketch artboards, and Chrome extension.", 6 | "engines": { 7 | "node": ">=8.2.0" 8 | }, 9 | "main": "bin/index.js", 10 | "repository": { 11 | "type": "git", 12 | "url": "git@ibm.com:ibm/css-gridish.git" 13 | }, 14 | "author": "James Y. Rauhut ", 15 | "license": "Apache-2.0", 16 | "dependencies": { 17 | "del": "^3.0.0", 18 | "gulp": "^3.9.1", 19 | "gulp-clean-css": "^3.9.2", 20 | "gulp-json-editor": "^2.2.1", 21 | "gulp-rename": "^1.2.2", 22 | "gulp-sass": "^3.1.0", 23 | "gulp-zip": "^4.1.0", 24 | "handlebars": "^4.0.11", 25 | "json-sass": "^1.3.5", 26 | "through2-map": "^3.0.0", 27 | "vinyl-paths": "^2.1.0", 28 | "vinyl-source-stream": "^2.0.0" 29 | }, 30 | "devDependencies": { 31 | "babel-cli": "^6.26.0", 32 | "babel-plugin-transform-object-rest-spread": "^6.26.0", 33 | "babel-preset-env": "^1.6.1", 34 | "browser-sync": "^2.23.5", 35 | "gulp-debug": "^3.2.0", 36 | "gulp-run": "^1.7.1" 37 | }, 38 | "scripts": { 39 | "build": "npm run build:src && npm run build:examples", 40 | "build:src": 41 | "cp -a src/. bin/ && babel src/index.js --out-file ./bin/index.js", 42 | "build:examples": 43 | "npm run build --prefix ./examples/bootstrap && npm run build --prefix ./examples/carbon && npm run build --prefix ./examples/material", 44 | "dev": "gulp watch", 45 | "start": "node bin/css-gridish.js", 46 | "test": "true" 47 | }, 48 | "bin": { 49 | "css-gridish": "bin/index.js" 50 | }, 51 | "keywords": ["css grid", "css flexbox", "css", "sass", "design system"], 52 | "babel": { 53 | "plugins": ["transform-object-rest-spread"], 54 | "presets": [ 55 | [ 56 | "env", 57 | { 58 | "targets": { 59 | "node": "6.10" 60 | } 61 | } 62 | ] 63 | ] 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const gulp = require("gulp"), 3 | cleanCSS = require("gulp-clean-css"), 4 | del = require("del"), 5 | fs = require("fs"), 6 | handlebars = require("handlebars"), 7 | jeditor = require("gulp-json-editor"), 8 | jsonSass = require("json-sass"), 9 | map = require("through2-map"), 10 | rename = require("gulp-rename"), 11 | sass = require("gulp-sass"), 12 | source = require("vinyl-source-stream"), 13 | vinylPaths = require("vinyl-paths"), 14 | zip = require("gulp-zip"); 15 | 16 | const dirRoot = process.cwd(); 17 | const routeConfig = `${dirRoot}/css-gridish.json`; 18 | const config = require(routeConfig); 19 | const intro = 20 | config.paths !== undefined && config.paths.intro !== undefined 21 | ? fs.readFileSync(`${dirRoot}/${config.paths.intro}`, "utf8") 22 | : ""; 23 | const route = 24 | config.paths !== undefined && config.paths.route !== undefined 25 | ? config.paths.route 26 | : "css-gridish"; 27 | const dirDest = `${dirRoot}/${route}`; 28 | const dirDestCss = `${dirDest}/\css`; 29 | const dirDestDesign = `${__dirname}/css-gridish-design.json`; 30 | const dirDestScss = `${dirDest}/s\css`; 31 | const dirDestSketch = `${dirDest}/sketch`; 32 | const prefix = config.prefix ? config.prefix : "gridish"; 33 | 34 | const artboard = require(`${__dirname}/sketch/artboard.json`); 35 | 36 | const parseUnit = function(value, width) { 37 | let parsed = value; 38 | if (value !== 0) { 39 | if (value.includes("vw")) { 40 | parsed = value.slice(0, -2) * width * 0.01; 41 | } else if (value.includes("rem")) { 42 | parsed = value.slice(0, -3) * config.rem; 43 | } else if (value.includes("px")) { 44 | parsed = value.slice(0, -2); 45 | } else if (value.includes("%")) { 46 | parsed = value.slice(0, -1) * width * 0.01; 47 | } 48 | } 49 | return parsed; 50 | }; 51 | 52 | handlebars.registerHelper("length", function(json) { 53 | return Object.keys(json).length; 54 | }); 55 | 56 | handlebars.registerHelper("math", function(lvalue, operator, rvalue, options) { 57 | lvalue = parseFloat(lvalue); 58 | rvalue = parseFloat(rvalue); 59 | 60 | return { 61 | "+": lvalue + rvalue, 62 | "-": lvalue - rvalue, 63 | "*": lvalue * rvalue, 64 | "/": lvalue / rvalue, 65 | "%": lvalue % rvalue 66 | }[operator]; 67 | }); 68 | 69 | gulp.task("clean", function() { 70 | return del([dirDestCss, dirDestScss, `${dirDest}/${prefix}-grid.sketch`]); 71 | }); 72 | 73 | gulp.task("css", ["scssRenameLegacy"], function() { 74 | return gulp 75 | .src(`${dirDestScss}/${prefix}-grid.s\css`) 76 | .pipe(sass().on("error", sass.logError)) 77 | .pipe(rename(`${prefix}-grid.\css`)) 78 | .pipe(gulp.dest(dirDestCss)) 79 | .pipe( 80 | cleanCSS({ 81 | level: 2 82 | }) 83 | ) 84 | .pipe(rename(`${prefix}-grid.min.\css`)) 85 | .pipe(gulp.dest(dirDestCss)); 86 | }); 87 | 88 | gulp.task("css-legacy", ["css"], function() { 89 | return gulp 90 | .src(`${dirDestScss}/${prefix}-grid-legacy.s\css`) 91 | .pipe(sass().on("error", sass.logError)) 92 | .pipe(rename(`${prefix}-grid-legacy.\css`)) 93 | .pipe(gulp.dest(dirDestCss)) 94 | .pipe( 95 | cleanCSS({ 96 | level: 2 97 | }) 98 | ) 99 | .pipe(rename(`${prefix}-grid-legacy.min.\css`)) 100 | .pipe(gulp.dest(dirDestCss)); 101 | }); 102 | 103 | gulp.task("docs", ["css-legacy"], function() { 104 | return gulp 105 | .src(`${__dirname}/docs/*.hbs`) 106 | .pipe( 107 | map.obj(chunk => { 108 | var template = handlebars.compile(chunk.contents.toString()); 109 | chunk.contents = new Buffer( 110 | template({ 111 | config: { 112 | ...config, 113 | classBreakpoints: Object.keys(config.breakpoints).slice(0, -1), 114 | intro 115 | } 116 | }) 117 | ); 118 | return chunk; 119 | }) 120 | ) 121 | .pipe( 122 | rename(path => { 123 | // a template file of the form AAAA.BBB.hbs produces output file AAAA.BBB 124 | var dot = path.basename.lastIndexOf("."); 125 | path.extname = path.basename.substring(dot); 126 | path.basename = path.basename.substring(0, dot); 127 | }) 128 | ) 129 | .pipe(gulp.dest(dirDest)); 130 | }); 131 | 132 | gulp.task("scss", ["valuesClean"], function() { 133 | return gulp.src(`${__dirname}/scss/**/*.s\css`).pipe(gulp.dest(dirDestScss)); 134 | }); 135 | 136 | gulp.task("scssRename", ["scss"], function() { 137 | return gulp 138 | .src(`${dirDestScss}/gridish-grid.s\css`) 139 | .pipe(vinylPaths(del)) 140 | .pipe(rename(`${prefix}-grid.s\css`)) 141 | .pipe(gulp.dest(dirDestScss)); 142 | }); 143 | 144 | gulp.task("scssRenameLegacy", ["scssRename"], function() { 145 | return gulp 146 | .src(`${dirDestScss}/gridish-grid-legacy.s\css`) 147 | .pipe(vinylPaths(del)) 148 | .pipe(rename(`${prefix}-grid-legacy.s\css`)) 149 | .pipe(gulp.dest(dirDestScss)); 150 | }); 151 | 152 | gulp.task("sketchClean", ["sketchZip"], function() { 153 | return del([dirDestSketch]); 154 | }); 155 | 156 | gulp.task("sketchFiles", ["docs"], function() { 157 | return gulp 158 | .src([ 159 | `${__dirname}/sketch/files/**/*`, 160 | `!${__dirname}/sketch/files/pages/BC333699-815E-4E1B-9816-9836EDA5B291.json` 161 | ]) 162 | .pipe(gulp.dest(dirDestSketch)); 163 | }); 164 | 165 | gulp.task("sketchPage", ["sketchFiles"], function() { 166 | // Add breakpoint values to extra artboards 167 | const originalBreakpoints = config.breakpoints; 168 | let allBreakpoints = originalBreakpoints; 169 | for (let i = 0; i < Object.values(config.extraArtboards).length; i++) { 170 | const name = Object.keys(config.extraArtboards)[i]; 171 | const value = Object.values(config.extraArtboards)[i]; 172 | let found = false; 173 | for (let j = 0; j < Object.values(originalBreakpoints).length; j++) { 174 | // should catch at max 175 | if ( 176 | Object.values(originalBreakpoints)[j + 1] !== undefined && 177 | Object.values(originalBreakpoints)[j + 1].breakpoint > value && 178 | !found 179 | ) { 180 | allBreakpoints[name] = { 181 | ...Object.values(originalBreakpoints)[j], 182 | breakpoint: value 183 | }; 184 | found = true; 185 | } else if (Object.values(originalBreakpoints)[i + 1] === undefined) { 186 | allBreakpoints[name] = { 187 | ...Object.values(originalBreakpoints)[i], 188 | breakpoint: value 189 | }; 190 | } 191 | } 192 | } 193 | 194 | // Sort all breakpoints by size 195 | let sorted = Object.values(allBreakpoints); 196 | for (let i = 0; i < sorted.length; i++) { 197 | sorted[i] = { 198 | ...sorted[i], 199 | name: Object.keys(allBreakpoints)[i] 200 | }; 201 | } 202 | sorted = sorted.sort(function(a, b) { 203 | return a.breakpoint - b.breakpoint; 204 | }); 205 | 206 | // Make artboards for each breakpoint 207 | let layers = []; 208 | let x = 0; 209 | for (let i = 0; i < sorted.length; i++) { 210 | x = i > 0 ? x + (sorted[i - 1].breakpoint + 1) * config.rem : 0; 211 | const values = sorted[i]; 212 | const width = values.breakpoint * config.rem; 213 | const margin = parseUnit(values.margin, width); 214 | const gutter = parseUnit(values.gutter, width); 215 | const gridWidth = width - margin * 2; 216 | const gutterWidth = gutter; 217 | 218 | layers.push({ 219 | ...artboard, 220 | name: `${values.name}-${width}px-${values.columns}`, 221 | do_objectID: artboard.do_objectID.slice(0, -1) + i, 222 | frame: { 223 | ...artboard.frame, 224 | width, 225 | x 226 | }, 227 | grid: { 228 | ...artboard.grid, 229 | gridSize: config.rowHeight * config.rem 230 | }, 231 | layout: { 232 | ...artboard.layout, 233 | columnWidth: 234 | (gridWidth - gutterWidth * values.columns) / values.columns, 235 | gutterWidth, 236 | horizontalOffset: margin, 237 | numberOfColumns: values.columns, 238 | totalWidth: gridWidth 239 | } 240 | }); 241 | } 242 | return gulp 243 | .src( 244 | `${__dirname}/sketch/files/pages/BC333699-815E-4E1B-9816-9836EDA5B291.json` 245 | ) 246 | .pipe( 247 | jeditor({ 248 | layers 249 | }) 250 | ) 251 | .pipe(gulp.dest(`${dirDestSketch}/pages`)); 252 | }); 253 | 254 | gulp.task("sketchZip", ["sketchPage"], function() { 255 | return gulp 256 | .src(`${dirDestSketch}/**/*`) 257 | .pipe(zip(`${prefix}-grid.zip`)) 258 | .pipe(rename(`${prefix}-grid.sketch`)) 259 | .pipe(vinylPaths(del)) 260 | .pipe(gulp.dest(dirDest)); 261 | }); 262 | 263 | gulp.task("values", ["valuesPrep"], function() { 264 | return fs 265 | .createReadStream(dirDestDesign) 266 | .pipe( 267 | jsonSass({ 268 | prefix: "$grid-values: " 269 | }) 270 | ) 271 | .pipe(source(routeConfig)) 272 | .pipe(rename("_values.scss")) 273 | .pipe(gulp.dest(dirDestScss)); 274 | }); 275 | 276 | gulp.task("valuesClean", ["values"], function() { 277 | return fs.unlinkSync(dirDestDesign); 278 | }); 279 | 280 | gulp.task("valuesPrep", ["clean"], function() { 281 | return fs.writeFileSync( 282 | dirDestDesign, 283 | JSON.stringify({ 284 | ...config, 285 | paths: null 286 | }) 287 | ); 288 | }); 289 | 290 | gulp.task("default", ["sketchClean"], function() { 291 | console.log( 292 | `CSS Gridish finished building your ${prefix} grid in ${dirDest}! 🏁` 293 | ); 294 | }); 295 | 296 | gulp.start("default"); 297 | -------------------------------------------------------------------------------- /src/scss/_core.scss: -------------------------------------------------------------------------------- 1 | @import "functions.scss"; 2 | @import "mixins.scss"; 3 | @import "variables.scss"; 4 | @import "utilities.scss"; 5 | 6 | html { 7 | font-size: map-get($grid-values, "rem") * 1px; 8 | } 9 | 10 | body { 11 | margin: 0; 12 | } 13 | 14 | .#{$prefix}-container { 15 | box-sizing: border-box; 16 | margin-left: auto; 17 | margin-right: auto; 18 | max-width: #{map-get($last, breakpoint)}rem; 19 | overflow-x: hidden; 20 | width: 100vw; 21 | } 22 | 23 | .#{$prefix}-container--left { 24 | margin-left: 0; 25 | } 26 | 27 | .#{$prefix}-container--right { 28 | margin-right: 0; 29 | } 30 | 31 | .#{$prefix}-grid { 32 | align-items: flex-start; 33 | box-sizing: border-box; 34 | @if $includeFlexFallback { 35 | display: flex; 36 | } 37 | display: grid; 38 | flex-wrap: wrap; 39 | position: relative; 40 | 41 | > * { 42 | box-sizing: border-box; 43 | 44 | :last-child, 45 | :last-child > :last-child, 46 | :last-child > :last-child > :last-child { 47 | margin-bottom: 0; 48 | } 49 | } 50 | } 51 | 52 | [class*="#{$prefix}-padding"] { 53 | box-sizing: border-box; 54 | } 55 | 56 | // Rules needed in legacy, but needed to change in CSS Grid 57 | @if $includeFlexFallback { 58 | .#{$prefix}-grid > * { 59 | width: 100%; 60 | } 61 | 62 | @supports (display: grid) { 63 | .#{$prefix}-grid { 64 | align-items: unset; 65 | } 66 | 67 | .#{$prefix}-grid > * { 68 | width: initial; 69 | } 70 | } 71 | } 72 | 73 | // Rules not needed in legacy, but needed in CSS Grid 74 | @supports (display: grid) { 75 | .#{$prefix}-grid > * { 76 | height: 100%; 77 | } 78 | } 79 | 80 | @include grid-legacy-wrapper($includeFlexFallback) { 81 | :root { 82 | @include grid-heights-fixed($rows); 83 | } 84 | } 85 | 86 | @each $name, $breakpoint in $allBreakpoints { 87 | @include media-query($name) { 88 | @if is-same-breakpoint($breakpoint, $last) == false { 89 | @include grid-legacy-heights($name); 90 | } 91 | @include grid-legacy-zeros($breakpoint, $name); 92 | @include grid-padding($breakpoint); 93 | @include grid($breakpoint, $name); 94 | @include grid-legacy-columns($breakpoint, $name); 95 | 96 | // Wrap all bleed/break classes and css variables in a CSS Grid support query 97 | @include grid-legacy-wrapper($includeFlexFallback) { 98 | @include grid-margin($breakpoint, $name); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/scss/_functions.scss: -------------------------------------------------------------------------------- 1 | @import "sass-list-maps"; 2 | 3 | // Transform the gutter property into a padding property for web 4 | @function add-padding($breakpoints) { 5 | $cleanBreakpoints: (); 6 | @each $name, $breakpoint in $breakpoints { 7 | $cleanBreakpoints: map-merge( 8 | $cleanBreakpoints, 9 | ( 10 | $name: 11 | map-merge($breakpoint, (padding: map-get($breakpoint, gutter) / 2)) 12 | ) 13 | ); 14 | } 15 | 16 | @return $cleanBreakpoints; 17 | } 18 | 19 | // Merge standard and custom breakpoints into list 20 | @function all-breakpoints($breakpoints, $extraBreakpoints, $first, $last) { 21 | $allBreakpoints: $breakpoints; 22 | @each $currentBreakpoint in $extraBreakpoints { 23 | $extraBreakpointName: nth($currentBreakpoint, 1); 24 | $extraBreakpointWidth: nth($currentBreakpoint, 2); 25 | $found: false; 26 | $match: null; 27 | @each $majorBreakpoint in $breakpoints { 28 | @if $found == false { 29 | @if map-get(nth($majorBreakpoint, 2), breakpoint) > 30 | $extraBreakpointWidth 31 | { 32 | $found: true; 33 | } @else { 34 | $match: $majorBreakpoint; 35 | } 36 | } 37 | } 38 | @if $extraBreakpointWidth > map-get($last, breakpoint) { 39 | $match: ( 40 | last, 41 | $last 42 | ); 43 | } 44 | @if $extraBreakpointWidth < map-get($first, breakpoint) { 45 | $match: ( 46 | first, 47 | $first 48 | ); 49 | } 50 | 51 | $newBreakpoint: map-merge( 52 | nth($match, 2), 53 | (breakpoint: $extraBreakpointWidth) 54 | ); 55 | $currentBreakpoint: ( 56 | $extraBreakpointName: 57 | map-merge(nth($match, 2), (breakpoint: $extraBreakpointWidth)) 58 | ); 59 | $allBreakpoints: map-merge($allBreakpoints, $currentBreakpoint); 60 | } 61 | 62 | @return maps-sort($allBreakpoints, breakpoint); 63 | } 64 | 65 | @function is-same-breakpoint($a, $b) { 66 | @return map-get($a, breakpoint) == map-get($b, breakpoint); 67 | } 68 | 69 | /// Traverse maps and retrieve deeply nested values: https://css-tricks.com/snippets/sass/deep-getset-maps/ 70 | /// @author Hugo Giraudel 71 | /// @param {Map} $map A sass map and any number of keys. 72 | /// @param {*} $keys Nested values. 73 | /// @return Nested values or nested map. 74 | @function map-deep-get($map, $keys...) { 75 | @each $key in $keys { 76 | $map: map-get($map, $key); 77 | } 78 | @return $map; 79 | } 80 | 81 | // _decimal.scss | MIT License | gist.github.com/terkel/4373420 82 | @function round-decimal($number, $digits: 0, $mode: round) { 83 | $n: 1; 84 | // $number must be a number 85 | @if type-of($number) != number { 86 | @warn "#{ $number } is not a number."; 87 | @return $number; 88 | } 89 | // $digits must be a unitless number 90 | @if type-of($digits) != number { 91 | @warn "#{ $digits } is not a number."; 92 | @return $number; 93 | } @else if not unitless($digits) { 94 | @warn "#{ $digits } has a unit."; 95 | @return $number; 96 | } 97 | @for $i from 1 through $digits { 98 | $n: $n * 10; 99 | } 100 | @if $mode == round { 101 | @return round($number * $n) / $n; 102 | } @else if $mode == ceil { 103 | @return ceil($number * $n) / $n; 104 | } @else if $mode == floor { 105 | @return floor($number * $n) / $n; 106 | } @else { 107 | @warn "#{ $mode } is undefined keyword."; 108 | @return $number; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Set the width of a grid’s column 2 | @mixin grid($breakpoint, $breakpointName) { 3 | @if (map-get($breakpoint, columns) != null) { 4 | $columnSize: get-fluid-size($breakpointName, 1); 5 | 6 | .#{$prefix}-grid { 7 | @if is-same-breakpoint($breakpoint, $first) { 8 | grid-auto-rows: minmax($rowHeight * 1rem, min-content); 9 | } 10 | grid-template-columns: repeat(auto-fill, $columnSize); 11 | 12 | &.#{$prefix}-grid--fixed-columns { 13 | grid-template-columns: repeat( 14 | auto-fill, 15 | map-get($breakpoint, breakpoint) * 16 | 1rem / 17 | map-get($breakpoint, columns) 18 | ); 19 | } 20 | 21 | &.#{$prefix}-grid--fluid-rows { 22 | grid-auto-rows: $columnSize; 23 | } 24 | 25 | @if is-same-breakpoint($breakpoint, $last) == false { 26 | > * { 27 | grid-column: span #{map-get($breakpoint, columns)}; 28 | } 29 | } 30 | } 31 | } 32 | } 33 | 34 | // Generate variables for commonly used rows 35 | @mixin grid-heights-fixed($rows) { 36 | @for $i from 1 to $rows { 37 | --#{$prefix}-height-#{$i}: get-fixed-size($i); 38 | } 39 | } 40 | 41 | // Set the width of a grid’s column for legacy grid 42 | @mixin grid-legacy-columns($breakpoint, $name) { 43 | // Do not make class if last media query 44 | @if is-same-breakpoint($breakpoint, $last) == false { 45 | // Loop each breakpoint to insert previous breakpoint classes inside this breakpoint’s media query 46 | // Ex: Make sure .yourPrefix-grid__col--sm--2 has correct sizes in the lg media query 47 | @each $currentName, $currentBreakpoint in $allBreakpoints { 48 | // Check if current breakpoint is not bigger than current media query 49 | @if map-get($breakpoint, breakpoint) >= 50 | map-get($currentBreakpoint, breakpoint) 51 | { 52 | // Loop each column in current breakpoint for new class 53 | // Ex: .yourPrefix-grid__col--sm--1, .yourPrefix-grid__col--sm--2, etc. 54 | @for $i from 1 through map-get($currentBreakpoint, columns) { 55 | $columnMultiplier: $i * 56 | map-get($breakpoint, columns) / 57 | map-get($currentBreakpoint, columns); 58 | $columnSize: get-fluid-size($name, $columnMultiplier); 59 | 60 | $isSecondToLast: is-same-breakpoint( 61 | $breakpoint, 62 | nth(nth($allBreakpoints, length($allBreakpoints) - 1), 2) 63 | ); 64 | 65 | $maxColumnSize: get-fluid-size( 66 | nth(nth($allBreakpoints, length($allBreakpoints)), 1), 67 | $columnMultiplier 68 | ); 69 | 70 | .#{$prefix}-grid__col--#{$currentName}--#{$i} { 71 | @if $includeFlexFallback { 72 | // If second-to-last media query, apply max-width instead of remaking classes in last media query 73 | @if $isSecondToLast { 74 | max-width: $maxColumnSize; 75 | } 76 | width: $columnSize; 77 | } 78 | grid-column: span #{$columnMultiplier}; 79 | 80 | @if is-same-breakpoint($breakpoint, $last) == false { 81 | &.#{$prefix}-grid > *:not([class*="#{$prefix}-grid__col"]) { 82 | grid-column: span #{$i}; 83 | } 84 | } 85 | } 86 | 87 | .#{$prefix}-grid--fluid-rows 88 | > .#{$prefix}-grid__height--#{$currentName}--#{$i} { 89 | grid-row: span $i; 90 | @if $includeFlexFallback { 91 | height: $columnSize; 92 | min-height: $columnSize; 93 | // If second-to-last media query, apply max-height instead of remaking classes in last media query 94 | @if $isSecondToLast { 95 | max-height: $maxColumnSize; 96 | } 97 | } 98 | } 99 | } 100 | } 101 | } 102 | } 103 | 104 | @if $includeFlexFallback { 105 | @if is-same-breakpoint($breakpoint, $last) { 106 | [class*="#{$prefix}-grid__col--"] { 107 | min-width: 0; 108 | } 109 | } 110 | } 111 | } 112 | 113 | // Set the height of an item for legacy grid 114 | @mixin grid-legacy-heights($name) { 115 | .#{$prefix}-grid__height--#{$name}--0 { 116 | height: 0; 117 | min-height: 0; 118 | } 119 | @for $i from 1 to $rows { 120 | .#{$prefix}-grid__height--#{$name}--#{$i} { 121 | grid-row: span $i; 122 | @if $includeFlexFallback { 123 | height: get-fixed-size($i); 124 | min-height: get-fixed-size($i); 125 | } 126 | } 127 | } 128 | } 129 | 130 | // If we need legacy grid, wrap this content in support tag 131 | @mixin grid-legacy-wrapper($includeFlexFallback) { 132 | @if $includeFlexFallback { 133 | @supports (display: grid) { 134 | @content; 135 | } 136 | } @else { 137 | @content; 138 | } 139 | } 140 | 141 | // Generate all classes for 0 and 0-only displaying, including custom breakpoints if they exist 142 | @mixin grid-legacy-zeros($breakpoint, $name) { 143 | // Undo previous breakpoint’s 0--only class 144 | @for $i from length($allBreakpoints) * -1 through -1 { 145 | $currentBreakpoint: nth($allBreakpoints, $i); 146 | @if map-get(nth($currentBreakpoint, 2), breakpoint) < 147 | map-get($breakpoint, breakpoint) 148 | { 149 | .#{$prefix}-grid__col--#{nth($currentBreakpoint, 1)}--0--only { 150 | display: block; 151 | } 152 | } 153 | } 154 | 155 | [class*="#{$prefix}-grid__col--#{$name}--"] { 156 | display: block; 157 | } 158 | 159 | .#{$prefix}-grid__col--#{$name}--0, 160 | .#{$prefix}-grid__col--#{$name}--0--only { 161 | display: none; 162 | } 163 | } 164 | 165 | // Set the width of a grid’s margin 166 | // and allow for a child to break out of the grid’s margin 167 | @mixin grid-margin($breakpoint, $name) { 168 | $nameToUse: $name; 169 | $margin: #{map-get($breakpoint, margin)}; 170 | $padding: #{map-get($breakpoint, padding)}; 171 | 172 | // If last breakpoint, we use the previous breakpoint name 173 | // to treat the last breakpoint as the max-width of the previous breakpoint 174 | @if is-same-breakpoint($breakpoint, $last) == true { 175 | $previousBreakpoint: nth( 176 | $allBreakpoints, 177 | index(map-keys($allBreakpoints), $name) - 1 178 | ); 179 | $nameToUse: nth($previousBreakpoint, 1); 180 | } 181 | 182 | // Undo previous breakpoint’s bleeds and breaks 183 | @if is-same-breakpoint($breakpoint, $first) == 184 | false and 185 | is-same-breakpoint($breakpoint, $last) == 186 | false 187 | { 188 | $previousBreakpoint: nth( 189 | $allBreakpoints, 190 | index(map-keys($allBreakpoints), $name) - 1 191 | ); 192 | $previousName: nth($previousBreakpoint, 1); 193 | $previousMargin: map-get(nth($previousBreakpoint, 2), margin); 194 | 195 | @if $previousMargin != 196 | null and 197 | $previousMargin != 198 | 0 and 199 | $previousMargin != 200 | "0" 201 | { 202 | [class^="#{$prefix}-container__bleed--#{$previousName}"], 203 | [class^="#{$prefix}-container__break--#{$previousName}"] { 204 | margin-left: 0; 205 | margin-right: 0; 206 | padding-left: 0; 207 | padding-right: 0; 208 | 209 | &[class^="#{$prefix}-padding"] { 210 | padding-left: $padding; 211 | padding-right: $padding; 212 | } 213 | } 214 | } 215 | } 216 | 217 | @if $margin != null and $margin != 0 and $margin != "0" { 218 | $marginPlusPadding: calc(#{$margin} + #{$padding}); 219 | @if $margin == "0" and $padding == "0" { 220 | $marginPlusPadding: 0; 221 | } @else if $margin == "0" { 222 | $marginPlusPadding: $padding; 223 | } @else if $padding == "0" { 224 | $marginPlusPadding: $margin; 225 | } 226 | 227 | .#{$prefix}-container { 228 | margin-left: auto; 229 | margin-right: auto; 230 | padding-left: $margin; 231 | padding-right: $margin; 232 | } 233 | 234 | .#{$prefix}-container--left { 235 | margin-left: 0; 236 | } 237 | 238 | .#{$prefix}-container--right { 239 | margin-right: 0; 240 | } 241 | 242 | .#{$prefix}-container__bleed--#{$nameToUse}, 243 | .#{$prefix}-container__bleed--#{$nameToUse}--left, 244 | .#{$prefix}-container__break--#{$nameToUse}, 245 | .#{$prefix}-container__break--#{$nameToUse}--left { 246 | margin-left: -#{$margin}; 247 | } 248 | 249 | .#{$prefix}-container__bleed--#{$nameToUse}, 250 | .#{$prefix}-container__bleed--#{$nameToUse}--right, 251 | .#{$prefix}-container__break--#{$nameToUse}, 252 | .#{$prefix}-container__break--#{$nameToUse}--right { 253 | margin-right: -#{$margin}; 254 | } 255 | 256 | .#{$prefix}-container__bleed--#{$nameToUse}, 257 | .#{$prefix}-container__bleed--#{$nameToUse}--left { 258 | padding-left: $margin; 259 | 260 | &.#{$prefix}-padding, 261 | &.#{$prefix}-padding--horizontal, 262 | &.#{$prefix}-padding--left { 263 | padding-left: $marginPlusPadding; 264 | } 265 | } 266 | 267 | .#{$prefix}-container__bleed--#{$nameToUse}, 268 | .#{$prefix}-container__bleed--#{$nameToUse}--right { 269 | padding-right: $margin; 270 | 271 | &.#{$prefix}-padding, 272 | &.#{$prefix}-padding--horizontal, 273 | &.#{$prefix}-padding--right { 274 | padding-right: $marginPlusPadding; 275 | } 276 | } 277 | } 278 | } 279 | 280 | // Classnames for different padding options 281 | @mixin grid-padding($breakpoint) { 282 | @if (map-get($breakpoint, padding) != null) { 283 | $padding: map-get($breakpoint, padding); 284 | 285 | .#{$prefix}-padding { 286 | padding: $padding; 287 | } 288 | 289 | .#{$prefix}-padding--bottom { 290 | padding-bottom: $padding; 291 | } 292 | 293 | .#{$prefix}-padding--left { 294 | padding-left: $padding; 295 | } 296 | 297 | .#{$prefix}-padding--right { 298 | padding-right: $padding; 299 | } 300 | 301 | .#{$prefix}-padding--top { 302 | padding-top: $padding; 303 | } 304 | 305 | .#{$prefix}-padding--horizontal { 306 | padding-left: $padding; 307 | padding-right: $padding; 308 | } 309 | 310 | .#{$prefix}-padding--vertical { 311 | padding-bottom: $padding; 312 | padding-top: $padding; 313 | } 314 | } 315 | } 316 | -------------------------------------------------------------------------------- /src/scss/_sass-list-maps.scss: -------------------------------------------------------------------------------- 1 | /// _ 2 | /// | | 3 | /// ___ __ _ ___ ___ ______ _ __ ___ __ _ _ __ ___ ______ _ __ | |_ _ ___ 4 | /// / __|/ _` / __/ __|______| '_ ` _ \ / _` | '_ \/ __|______| '_ \| | | | / __| 5 | /// \__ \ (_| \__ \__ \ | | | | | | (_| | |_) \__ \ | |_) | | |_| \__ \ 6 | /// |___/\__,_|___/___/ |_| |_| |_|\__,_| .__/|___/ | .__/|_|\__,_|___/ 7 | /// | | | | 8 | /// |_| |_| 9 | /// Sass Maps Plus 0.9.2 10 | /// Advanced map and list-map manipulation for all versions of Sass 11 | /// MIT License 12 | /// @author Lu Nelson 13 | 14 | /// Global sort direction: either `asc` or `desc` 15 | /// @access public 16 | /// @group map-lists/map-maps 17 | $maps-sort-dir: "asc"; 18 | 19 | /// get value at nested or 'deep' key, per $keys list 20 | /// @access public 21 | /// @group maps 22 | /// @param {Map} $map - map 23 | /// @param {Arglist} $keys - nested keys 24 | /// @return {*} 25 | @function map-get-nested($map, $keys...) { 26 | @if length($map) == 0 { 27 | @return null; 28 | } 29 | @each $key in $keys { 30 | @if type-of($map) != "map" { 31 | @return $map; 32 | } 33 | $map: map-get($map, $key); 34 | } 35 | @return $map; 36 | } 37 | 38 | /// Sort a list-of-maps or map-of-maps, based on value at key(s) in maps 39 | /// @access public 40 | /// @group map-lists/map-maps 41 | /// @param {Map|List} $maps - Map of maps, or List of maps, to sort 42 | /// @param {Arglist} $keys - Chain of keys to the value that will be sorted for 43 | /// @return {Map|List} 44 | /// @require {function} map-get-nested 45 | @function maps-sort($maps, $keys...) { 46 | @if length($keys) == 0 { 47 | @return $maps; 48 | } 49 | 50 | @if length($maps) > 1 { 51 | $less: (); 52 | $equal: (); 53 | $greater: (); 54 | 55 | $map-of-maps: type-of($maps) == "map"; 56 | 57 | @if $map-of-maps { 58 | $seed-map: nth(nth($maps, ceil(length($maps) / 2)), 2); 59 | 60 | $seed-value: map-get-nested($seed-map, $keys...); 61 | 62 | // TODO: add code to handle case of non-number values (warn and return $maps) 63 | 64 | @each $key, $map in $maps { 65 | $curr-value: map-get-nested($map, $keys...); 66 | 67 | @if $curr-value == $seed-value { 68 | $equal: map-merge($equal, ($key: $map)); 69 | } @else if $curr-value < $seed-value { 70 | @if $maps-sort-dir == "asc" { 71 | $less: map-merge($less, ($key: $map)); 72 | } @else { 73 | $greater: map-merge($greater, ($key: $map)); 74 | } 75 | } @else { 76 | @if $maps-sort-dir == "asc" { 77 | $greater: map-merge($greater, ($key: $map)); 78 | } @else { 79 | $less: map-merge($less, ($key: $map)); 80 | } 81 | } 82 | } 83 | 84 | $less: maps-sort($less, $keys...); 85 | $greater: maps-sort($greater, $keys...); 86 | 87 | @return map-merge(map-merge($less, $equal), $greater); 88 | } @else { 89 | $seed-map: nth($maps, ceil(length($maps) / 2)); 90 | 91 | $seed-value: map-get-nested($seed-map, $keys...); 92 | 93 | @each $map in $maps { 94 | $curr-value: map-get-nested($map, $keys...); 95 | 96 | @if $curr-value == $seed-value { 97 | $equal: append($equal, $map); 98 | } @else if $curr-value < $seed-value { 99 | @if $maps-sort-dir == "asc" { 100 | $less: append($less, $map); 101 | } @else { 102 | $greater: append($greater, $map); 103 | } 104 | } @else { 105 | @if $maps-sort-dir == "asc" { 106 | $greater: append($greater, $map); 107 | } @else { 108 | $less: append($less, $map); 109 | } 110 | } 111 | } 112 | 113 | $less: maps-sort($less, $keys...); 114 | $greater: maps-sort($greater, $keys...); 115 | 116 | @return join(join($less, $equal), $greater); 117 | } 118 | } 119 | 120 | @return $maps; 121 | } 122 | -------------------------------------------------------------------------------- /src/scss/_utilities.scss: -------------------------------------------------------------------------------- 1 | @import "functions"; 2 | @import "values"; 3 | @import "variables"; 4 | 5 | /// Function returns the value for a given breakpoint. 6 | /// @param {String} $breakpointName Breakpoint name. 7 | /// @return {Length} The breakpoint value in rems. 8 | @function get-breakpoint-value($breakpointName) { 9 | $breakpointValue: map-deep-get( 10 | $breakpointsAndArtboards, 11 | $breakpointName, 12 | "breakpoint" 13 | ); 14 | 15 | @return $breakpointValue * 1rem; 16 | } 17 | 18 | /// Returns a calc() expression that represents a fluid width at a given breakpoint. 19 | /// @param {String} $breakpointName A valid breakpoint. 20 | /// @param {Number} $columnSpan The number of columns to span across. 21 | /// @return {Length} A calc() expression representing fluid width. 22 | /// @example scss 23 | /// button { 24 | /// @include media-query('sm') { 25 | /// max-width: get-fluid-size('sm', 1); 26 | /// } 27 | /// } 28 | /// @output css 29 | /// @media screen and (min-width: 20rem) { 30 | /// button { 31 | /// max-width: 25vw; 32 | /// } 33 | /// } 34 | @function get-fluid-size($breakpointName, $columnSpan) { 35 | $breakpoint: map-get($breakpointsAndArtboards, $breakpointName); 36 | 37 | @if ($breakpoint == null or type-of($breakpoint) != "map") { 38 | @error "The provided breakpoint `#{$breakpointName}` is not a valid breakpoint found in breakpoints or extraArtboards in $grid-values. Please double-check your grid configuration."; 39 | } 40 | 41 | $columnTotal: map-get($breakpoint, columns); 42 | $margin: map-get($breakpoint, margin); 43 | 44 | @if ($columnTotal == null or type-of($columnTotal) != "number") { 45 | @error "The provided breakpoint `#{$breakpointName}` needs to have a total number of columns set in $grid-values. Please double-check your grid configuration."; 46 | } 47 | 48 | @if ($columnSpan == null or type-of($columnSpan) != "number") { 49 | @error "The number of columns to span for the breakpoint `#{$breakpointName}` must be a valid number. The provided column span value `#{$columnSpan}` is not a number"; 50 | } 51 | 52 | @if ($columnSpan > $columnTotal or $columnSpan <= 0) { 53 | @error "The number of columns to span for the breakpoint `#{$breakpointName}` must be greater than 0 and less than or equal to the total number of columns for this breakpoint. The provided column value `#{$columnSpan}` does not meet this criteria"; 54 | } 55 | 56 | $container: 100vw; 57 | // Last breakpoint is a max-width and should be a fixed number 58 | @if is-same-breakpoint($breakpoint, $last) { 59 | $container: map-get($breakpoint, breakpoint) * 1rem; 60 | } 61 | 62 | $multiplier: round-decimal($columnSpan / $columnTotal, 4, floor); 63 | 64 | // For IE, we can't have a 0 in the $fluidWidth calc(). 65 | @if ($margin == 0) { 66 | @return $container * $multiplier; 67 | } 68 | 69 | @return calc((#{$container} - #{$margin * 2}) * #{$multiplier}); 70 | } 71 | 72 | /// Function gets a calculated rem value for a fixed size. 73 | /// @param {Number} $unitQuantity Fixed nondimensional units. 74 | /// @return {Length} A calculated rem value. 75 | /// @example scss 76 | /// button { 77 | /// @include media-query('sm') { 78 | /// max-width: get-fixed-size(10); 79 | /// } 80 | /// } 81 | /// @output css 82 | /// @media screen and (min-width: 20rem) { 83 | /// button { 84 | /// max-width: 5rem; 85 | /// } 86 | /// } 87 | @function get-fixed-size($unitQuantity) { 88 | // Derive the base unit from the current row height of the grid 89 | $fixedUnit: map-get($grid-values, "rowHeight"); 90 | 91 | @if ($fixedUnit == null or type-of($fixedUnit) != "number") { 92 | @error "The rowHeight in $grid-values needs be a valid number. Please check your grid configuration."; 93 | } 94 | 95 | @if ($unitQuantity == null or type-of($unitQuantity) != "number") { 96 | @error "The provided fixed value `#{$unitQuantity}` to get-fixed-size() needs to be a valid number greater than 0."; 97 | } 98 | 99 | @return $unitQuantity * $fixedUnit * 1rem; 100 | } 101 | 102 | /// Utility for declaring mobile-first media queries. 103 | /// @param {String} $breakpointName The name of the breakpoint to set its width value to media query. 104 | @mixin media-query($breakpointName) { 105 | $breakpointValue: get-breakpoint-value($breakpointName); 106 | @if $breakpointValue == map-get($first, breakpoint) { 107 | @content; 108 | } @else { 109 | @media screen and (min-width: #{$breakpointValue}) { 110 | @content; 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/scss/_variables.scss: -------------------------------------------------------------------------------- 1 | @import "values"; 2 | 3 | $prefix: gridish !default; 4 | @if map-get($grid-values, "prefix") and $prefix == "gridish" { 5 | $prefix: map-get($grid-values, "prefix"); 6 | } 7 | $extraBreakpoints: () !default; 8 | $breakpoints: add-padding(map-get($grid-values, "breakpoints")); 9 | $first: nth(nth($breakpoints, 1), 2); 10 | $last: nth(nth($breakpoints, -1), 2); 11 | $includeFlexFallback: false !default; 12 | $rowHeight: map-get($grid-values, "rowHeight"); 13 | $rows: map-get($grid-values, "rows"); 14 | $extraArtboards: map-get($grid-values, "extraArtboards"); 15 | $allBreakpoints: all-breakpoints( 16 | $breakpoints, 17 | $extraBreakpoints, 18 | $first, 19 | $last 20 | ); 21 | $breakpointsAndArtboards: all-breakpoints( 22 | $breakpoints, 23 | $extraArtboards, 24 | $first, 25 | $last 26 | ); 27 | -------------------------------------------------------------------------------- /src/scss/gridish-grid-legacy.scss: -------------------------------------------------------------------------------- 1 | $includeFlexFallback: true; 2 | @import "core.scss"; 3 | 4 | @supports (display: grid) { 5 | .#{$prefix}-grid > *, 6 | .#{$prefix}-grid > [class*="#{$prefix}-grid__col--"] { 7 | min-width: initial; 8 | max-width: initial; 9 | width: initial; 10 | 11 | &.#{$prefix}-grid { 12 | display: grid; 13 | } 14 | } 15 | 16 | .#{$prefix}-grid > [class*="#{$prefix}-grid__height--"] { 17 | height: unset; 18 | max-height: unset; 19 | min-height: initial; 20 | } 21 | } 22 | 23 | .#{$prefix}-grid > script { 24 | display: none; 25 | } 26 | -------------------------------------------------------------------------------- /src/scss/gridish-grid.scss: -------------------------------------------------------------------------------- 1 | @import "core.scss"; 2 | -------------------------------------------------------------------------------- /src/sketch/artboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "_class": "artboard", 3 | "do_objectID": "CF812E16-6AB8-4E0D-AA6C-E98BE3E292AC", 4 | "exportOptions": { 5 | "_class": "exportOptions", 6 | "exportFormats": [], 7 | "includedLayerIds": [], 8 | "layerOptions": 0, 9 | "shouldTrim": false 10 | }, 11 | "frame": { 12 | "_class": "rect", 13 | "constrainProportions": false, 14 | "height": 600, 15 | "width": 320, 16 | "x": 173, 17 | "y": 103 18 | }, 19 | "isFlippedHorizontal": false, 20 | "isFlippedVertical": false, 21 | "isLocked": false, 22 | "isVisible": true, 23 | "layerListExpandedType": 0, 24 | "name": "artboard1", 25 | "nameIsFixed": true, 26 | "resizingConstraint": 63, 27 | "resizingType": 0, 28 | "rotation": 0, 29 | "shouldBreakMaskChain": true, 30 | "style": { 31 | "_class": "style", 32 | "endDecorationType": 0, 33 | "miterLimit": 10, 34 | "startDecorationType": 0 35 | }, 36 | "hasClickThrough": false, 37 | "layers": [], 38 | "backgroundColor": { 39 | "_class": "color", 40 | "alpha": 1, 41 | "blue": 1, 42 | "green": 1, 43 | "red": 1 44 | }, 45 | "grid": { 46 | "_class": "simpleGrid", 47 | "isEnabled": true, 48 | "gridSize": 8, 49 | "thickGridTimes": 0 50 | }, 51 | "hasBackgroundColor": false, 52 | "horizontalRulerData": { "_class": "rulerData", "base": 0, "guides": [] }, 53 | "includeBackgroundColorInExport": true, 54 | "includeInCloudUpload": true, 55 | "layout": { 56 | "_class": "layoutGrid", 57 | "isEnabled": true, 58 | "columnWidth": 48, 59 | "drawHorizontal": false, 60 | "drawHorizontalLines": false, 61 | "drawVertical": true, 62 | "gutterHeight": 12, 63 | "gutterWidth": 32, 64 | "guttersOutside": true, 65 | "horizontalOffset": 0, 66 | "numberOfColumns": 4, 67 | "rowHeightMultiplication": 5, 68 | "totalWidth": 320 69 | }, 70 | "resizesContent": false, 71 | "verticalRulerData": { "_class": "rulerData", "base": 0, "guides": [] } 72 | } 73 | -------------------------------------------------------------------------------- /src/sketch/files/document.json: -------------------------------------------------------------------------------- 1 | { 2 | "_class": "document", 3 | "do_objectID": "0FBB6CDA-F85E-40DB-B6D3-2A9FA7AEA2D3", 4 | "assets": { 5 | "_class": "assetCollection", 6 | "colors": [], 7 | "gradients": [], 8 | "imageCollection": { "_class": "imageCollection", "images": {} }, 9 | "images": [] 10 | }, 11 | "colorSpace": 0, 12 | "currentPageIndex": 0, 13 | "enableLayerInteraction": true, 14 | "enableSliceInteraction": true, 15 | "foreignSymbols": [], 16 | "layerStyles": { "_class": "sharedStyleContainer", "objects": [] }, 17 | "layerSymbols": { "_class": "symbolContainer", "objects": [] }, 18 | "layerTextStyles": { "_class": "sharedTextStyleContainer", "objects": [] }, 19 | "pages": [ 20 | { 21 | "_class": "MSJSONFileReference", 22 | "_ref_class": "MSImmutablePage", 23 | "_ref": "pages/BC333699-815E-4E1B-9816-9836EDA5B291" 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /src/sketch/files/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "commit": "b8111e3393c4ca1f2399ecfdfc1e9488029ebe7b", 3 | "pagesAndArtboards": { 4 | "BC333699-815E-4E1B-9816-9836EDA5B291": { 5 | "name": "Page 1", 6 | "artboards": { 7 | "CF812E16-6AB8-4E0D-AA6C-E98BE3E292AC": { "name": "artboard1" } 8 | } 9 | } 10 | }, 11 | "version": 97, 12 | "fonts": [], 13 | "compatibilityVersion": 93, 14 | "app": "com.bohemiancoding.sketch3", 15 | "autosaved": 0, 16 | "variant": "NONAPPSTORE", 17 | "created": { 18 | "commit": "b8111e3393c4ca1f2399ecfdfc1e9488029ebe7b", 19 | "appVersion": "48.2", 20 | "build": 47327, 21 | "app": "com.bohemiancoding.sketch3", 22 | "compatibilityVersion": 93, 23 | "version": 97, 24 | "variant": "NONAPPSTORE" 25 | }, 26 | "saveHistory": ["NONAPPSTORE.47327"], 27 | "appVersion": "48.2", 28 | "build": 47327 29 | } 30 | -------------------------------------------------------------------------------- /src/sketch/files/pages/BC333699-815E-4E1B-9816-9836EDA5B291.json: -------------------------------------------------------------------------------- 1 | { 2 | "_class": "page", 3 | "do_objectID": "BC333699-815E-4E1B-9816-9836EDA5B291", 4 | "exportOptions": { 5 | "_class": "exportOptions", 6 | "exportFormats": [], 7 | "includedLayerIds": [], 8 | "layerOptions": 0, 9 | "shouldTrim": false 10 | }, 11 | "frame": { 12 | "_class": "rect", 13 | "constrainProportions": false, 14 | "height": 300, 15 | "width": 300, 16 | "x": 0, 17 | "y": 0 18 | }, 19 | "isFlippedHorizontal": false, 20 | "isFlippedVertical": false, 21 | "isLocked": false, 22 | "isVisible": true, 23 | "layerListExpandedType": 0, 24 | "name": "Page 1", 25 | "nameIsFixed": false, 26 | "resizingConstraint": 63, 27 | "resizingType": 0, 28 | "rotation": 0, 29 | "shouldBreakMaskChain": false, 30 | "style": { 31 | "_class": "style", 32 | "endDecorationType": 0, 33 | "miterLimit": 10, 34 | "startDecorationType": 0 35 | }, 36 | "hasClickThrough": true, 37 | "horizontalRulerData": { "_class": "rulerData", "base": 0, "guides": [] }, 38 | "includeInCloudUpload": true, 39 | "verticalRulerData": { "_class": "rulerData", "base": 0, "guides": [] } 40 | } 41 | -------------------------------------------------------------------------------- /src/sketch/files/previews/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/css-gridish/c5f16a541df485fa833f8f50299bd6a3f290a142/src/sketch/files/previews/preview.png -------------------------------------------------------------------------------- /src/sketch/files/user.json: -------------------------------------------------------------------------------- 1 | { 2 | "BC333699-815E-4E1B-9816-9836EDA5B291": { 3 | "scrollOrigin": "{23, 32}", 4 | "zoomValue": 1 5 | }, 6 | "0FBB6CDA-F85E-40DB-B6D3-2A9FA7AEA2D3": { "pageListHeight": -1 } 7 | } 8 | --------------------------------------------------------------------------------