Repository: philipwalton/solved-by-flexbox Branch: master Commit: 01af9bc0c2c8 Files: 51 Total size: 73.6 KB Directory structure: gitextract_6lnvp84o/ ├── .eslintrc ├── .gitignore ├── .jshintrc ├── LICENSE ├── README.md ├── assets/ │ ├── css/ │ │ ├── base/ │ │ │ ├── custom-media.css │ │ │ ├── elements.css │ │ │ └── variables.css │ │ ├── components/ │ │ │ ├── aligner.css │ │ │ ├── browser.css │ │ │ ├── button.css │ │ │ ├── container.css │ │ │ ├── demo.css │ │ │ ├── error.css │ │ │ ├── feature.css │ │ │ ├── footer.css │ │ │ ├── grid.css │ │ │ ├── header.css │ │ │ ├── holy-grail.css │ │ │ ├── image.css │ │ │ ├── input-add-on.css │ │ │ ├── media.css │ │ │ ├── notice.css │ │ │ ├── section.css │ │ │ └── site.css │ │ ├── main.css │ │ ├── utils/ │ │ │ ├── compat.css │ │ │ ├── media.css │ │ │ └── size.css │ │ └── vendor/ │ │ ├── font-awesome-extensions.css │ │ ├── highlight.css │ │ └── twitter.css │ └── main.js ├── config.json ├── demos/ │ ├── grids.md │ ├── holy-grail.md │ ├── input-add-ons.md │ ├── media-object.md │ ├── sticky-footer.md │ └── vertical-centering.md ├── gulpfile.js ├── index.html ├── package.json ├── rollup.config.js └── templates/ ├── default.html ├── footer.html ├── head.html ├── header.html ├── holy-grail.html ├── home.html └── scripts.html ================================================ FILE CONTENTS ================================================ ================================================ FILE: .eslintrc ================================================ { "parser": "babel-eslint", "env": { "browser": true, "es6": true, "node": true, "mocha": true }, "globals": { "browser": false }, "extends": [ "eslint:recommended" ] } ================================================ FILE: .gitignore ================================================ # OS or Editor folders .DS_Store # npm/yarn files node_modules *.log *.lock # Static site output _tmp/ solved-by-flexbox/ ================================================ FILE: .jshintrc ================================================ { "browser": true, "boss": true, "esnext": true, "expr": true, "node": true, "quotmark": "single" } ================================================ FILE: LICENSE ================================================ Copyright (c) 2015 Philip Walton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Solved by Flexbox A showcase of problems once hard or impossible to solve with CSS alone, now made trivially easy with Flexbox. [View Site](https://philipwalton.github.io/solved-by-flexbox/) ## Viewing the Site Locally The Solved by Flexbox site can be built with [Node.js](http://nodejs.org/). If you have Node.js installed on your system, you can run the following commands to build and serve a local copy. ```sh # Clone the git repository and cd into the cloned directory. git clone https://github.com/philipwalton/solved-by-flexbox.git cd solved-by-flexbox # Install the dependencies npm install # Build and serve the site at http://localhost:4000 npm start ``` This starts up a local server on port 4000. To view the site in your browser, navigate to [http://localhost:4000](http://localhost:4000). If you want to use a different port, you can pass the port number as an argument to `npm start`: ```sh npm start -- -p 8080 ``` In addition to building the site and serving it locally, this will also listen for any changes and rebuild the site as needed. This allows you to play around with the code, refresh the browser, and see your changes instantly. ## Translations The following translations have been graciously provided by the community: * [Chinese](https://hufan-akari.github.io/solved-by-flexbox/) * [Japanese](http://hashrock.github.io/solved-by-flexbox-ja/) * [Korean](https://hyunseob.github.io/solved-by-flexbox-kr/) Please note that translations are unofficial and may be inaccurate or out of date. To submit your own translation, please submit a [pull request](https://github.com/philipwalton/solved-by-flexbox/pull/new/master) or [open an issue](https://github.com/philipwalton/solved-by-flexbox/issues/new) and link to your translated content. ================================================ FILE: assets/css/base/custom-media.css ================================================ @custom-media --break-sm (min-width: 384px); @custom-media --break-md (min-width: 576px); @custom-media --break-lg (min-width: 768px); @custom-media --high-dppx (-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 144dpi), (min-resolution: 1.5dppx); ================================================ FILE: assets/css/base/elements.css ================================================ *, *::after, *::before { box-sizing: border-box; } html { height: 100%; color: hsl(0,0%,25%); font: 400 1em/1.4 'Open Sans', sans-serif; text-rendering: optimizeLegibility; } @media (--high-dppx) { html { font-weight: 300; } } h1 { font-weight: 300; font-size: 2em; -webkit-font-kerning: normal; letter-spacing: -.015em; line-height: 1; margin: .25em 0 .75em; } @media (--break-lg) { h1 { font-size: 2.5em; margin: .5em 0 1em; } } h2 { font-size: 1.333em; font-weight: 600; margin: 0 0 calc(1.5em/1.333); } h3 { font-size: 1em; font-weight: 600; margin: 0 0 1.5em; } p, pre { margin: 0 0 1.5em; } code, pre { font-family: 'Menlo', 'Monaco', monospace; } code { font-size: .9em; font-weight: normal; color: #000; } pre > code { font: inherit; color: inherit; } a { border-bottom: 1px dashed hsla(150, 45%, 50%, 0.5); color: hsl(150, 45%, 50%); text-decoration: none; } a:focus, a:hover { border-bottom: 1px solid hsl(150, 45%, 50%); } ol, ul { list-style: square; margin: 0 0 1.5em; padding: 0 0 0 1.5em; } li { margin-bottom: 0.333em; } figure { margin: 0; } strong { font-weight: 600; } ================================================ FILE: assets/css/base/variables.css ================================================ :root { --space: 1.5em; --space-lg: 2em; --bg-color: hsl(150, 45%, 50%); } ================================================ FILE: assets/css/components/aligner.css ================================================ .Aligner { display: flex; align-items: center; min-height: 24em; justify-content: center; } .Aligner-item { flex: 1; } .Aligner-item--top { align-self: flex-start; } .Aligner-item--bottom { align-self: flex-end; } .Aligner-item--fixed { flex: none; max-width: 50%; } ================================================ FILE: assets/css/components/browser.css ================================================ .Browser { font-size: .8em; text-align: center; } .Browser-image { height: 64px; width: 64px; margin: 0 0.5em 0.5em; background: url('images/browser-logos.jpg') no-repeat 0 0; background-size: auto 100%; } .Browser--chrome > .Browser-image { background-position: 0 0; } .Browser--opera > .Browser-image { background-position: -64px 0; } .Browser--firefox > .Browser-image { background-position: -128px 0; } .Browser--safari > .Browser-image { background-position: -192px 0; } .Browser--ie > .Browser-image { background-position: -256px 0; } .Browser--edge > .Browser-image { background-position: -320px 0; } ================================================ FILE: assets/css/components/button.css ================================================ .Button { transition: background-color 0.2s; display: inline-block; padding: 0.6em 1em; background: hsla(31, 15%, 50%, 0.15); color: inherit; border: 0; border-radius: 2px; cursor: pointer; font-size: 0.8125em; font-weight: 300; line-height: normal; text-decoration: none; white-space: nowrap; } .Button:focus { outline: thin dotted #666; text-decoration: none; } .Button:active, .Button:focus, .Button:hover { border: 0; background: hsla(31, 15%, 50%, 0.25); text-decoration: none; } .Button--action { background-color: hsl(150, 45%, 50%); color: #fff; } .Button--action:active, .Button--action:focus, .Button--action:hover { background-color: hsl(150, 45%, 40%); } .Button--wide { padding-right: 1.5em; padding-left: 1.5em; } ================================================ FILE: assets/css/components/container.css ================================================ .Container { max-width: 50em; margin: 0 auto; } ================================================ FILE: assets/css/components/demo.css ================================================ .Demo { width: 100%; padding: .8em 1em 0; background: hsla(31, 15%, 50%, 0.1); border-radius: 3px; } .Demo::after { content: '\00a0'; /*   */ display: block; margin-top: 1em; height: 0px; visibility: hidden; } .Demo--spaced { margin-bottom: var(--space); } ================================================ FILE: assets/css/components/error.css ================================================ .Error { padding: 1em 1.5em; background: #c00; color: #fff; font-weight: 700; text-align: center; } ================================================ FILE: assets/css/components/feature.css ================================================ .Feature { } .Feature-figure { margin-bottom: 0.75em; border: 1px solid hsl(0, 0%, 85%); transition: border-color 0.2s; } .Feature-image { display: block; max-width: 100%; height: auto; border: 5px solid hsl(0, 100%, 100%); } .Feature-title { margin: 0 0 0.5em; color: hsl(0, 0%, 25%); text-align: center; transition: color 0.1s; } .Feature-description { margin: 0 0.75em; font-size: 0.8em; } .Feature a:active .Feature-figure, .Feature a:focus .Feature-figure, .Feature a:hover .Feature-figure { border-color: hsl(150, 45%, 50%); } .Feature a:active .Feature-title, .Feature a:focus .Feature-title, .Feature a:hover .Feature-title { color: hsl(150, 45%, 50%); } ================================================ FILE: assets/css/components/footer.css ================================================ .Footer { padding: 1.5rem 1.5rem; background: hsl(0, 0%, 25%); color: hsl(0, 0%, 60%); font-size: 0.85em; overflow-x: hidden; text-align: center; } .Footer a { padding-bottom: 1px; border: 0; color: hsl(0, 0%, 90%); } .Footer a:focus, .Footer a:active, .Footer a:hover { color: #fff; text-decoration: underline; } .Footer-credits { margin: 0; padding: 0; } .Footer-credit { display: block; margin: 0; } .Footer-creditSeparator { display: none; } /* The GitHub button updates the link to be a span */ .Footer-social > span { margin-right: 1em; } /* If loading the social button fails */ .Footer-social a, .Footer-social iframe { display: inline-block; margin: 0 0 1em; vertical-align: top; } @media (--break-md) { .Footer-credit { display: inline-block; margin: 0 0.25em; } .Footer-creditSeparator { display: inline-block; padding: 0 0.25em; } } ================================================ FILE: assets/css/components/grid.css ================================================ .Grid { display: flex; flex-wrap: wrap; list-style: none; margin: 0; padding: 0; } .Grid-cell { flex: 1; } .Grid--flexCells > .Grid-cell { display: flex; } .Grid--top { align-items: flex-start; } .Grid--bottom { align-items: flex-end; } .Grid--center { align-items: center; } .Grid--justifyCenter { justify-content: center; } .Grid-cell--top { align-self: flex-start; } .Grid-cell--bottom { align-self: flex-end; } .Grid-cell--center { align-self: center; } .Grid-cell--autoSize { flex: none; } .Grid--fit > .Grid-cell { flex: 1; } .Grid--full > .Grid-cell { flex: 0 0 100%; } .Grid--1of2 > .Grid-cell { flex: 0 0 50%; } .Grid--1of3 > .Grid-cell { flex: 0 0 33.3333%; } .Grid--1of4 > .Grid-cell { flex: 0 0 25%; } @media (--break-sm) { .small-Grid--fit > .Grid-cell { flex: 1; } .small-Grid--full > .Grid-cell { flex: 0 0 100%; } .small-Grid--1of2 > .Grid-cell { flex: 0 0 50%; } .small-Grid--1of3 > .Grid-cell { flex: 0 0 33.3333%; } .small-Grid--1of4 > .Grid-cell { flex: 0 0 25%; } } @media (--break-md) { .med-Grid--fit > .Grid-cell { flex: 1; } .med-Grid--full > .Grid-cell { flex: 0 0 100%; } .med-Grid--1of2 > .Grid-cell { flex: 0 0 50%; } .med-Grid--1of3 > .Grid-cell { flex: 0 0 33.3333%; } .med-Grid--1of4 > .Grid-cell { flex: 0 0 25%; } } @media (--break-lg) { .large-Grid--fit > .Grid-cell { flex: 1; } .large-Grid--full > .Grid-cell { flex: 0 0 100%; } .large-Grid--1of2 > .Grid-cell { flex: 0 0 50%; } .large-Grid--1of3 > .Grid-cell { flex: 0 0 33.3333%; } .large-Grid--1of4 > .Grid-cell { flex: 0 0 25%; } } .Grid--gutters { margin: -1em 0 1em -1em; } .Grid--gutters > .Grid-cell { padding: 1em 0 0 1em; } .Grid--guttersLg { margin: -1.5em 0 1.5em -1.5em; } .Grid--guttersLg > .Grid-cell { padding: 1.5em 0 0 1.5em; } .Grid--guttersXl { margin: -2em 0 2em -2em; } .Grid--guttersXl > .Grid-cell { padding: 2em 0 0 2em; } @media (--break-sm) { .small-Grid--gutters { margin: -1em 0 1em -1em; } .small-Grid--gutters > .Grid-cell { padding: 1em 0 0 1em; } .small-Grid--guttersLg { margin: -1.5em 0 1.5em -1.5em; } .small-Grid--guttersLg > .Grid-cell { padding: 1.5em 0 0 1.5em; } .small-Grid--guttersXl { margin: -2em 0 2em -2em; } .small-Grid--guttersXl > .Grid-cell { padding: 2em 0 0 2em; } } @media (--break-md) { .med-Grid--gutters { margin: -1em 0 1em -1em; } .med-Grid--gutters > .Grid-cell { padding: 1em 0 0 1em; } .med-Grid--guttersLg { margin: -1.5em 0 1.5em -1.5em; } .med-Grid--guttersLg > .Grid-cell { padding: 1.5em 0 0 1.5em; } .med-Grid--guttersXl { margin: -2em 0 2em -2em; } .med-Grid--guttersXl > .Grid-cell { padding: 2em 0 0 2em; } } @media (--break-lg) { .large-Grid--gutters { margin: -1em 0 1em -1em; } .large-Grid--gutters > .Grid-cell { padding: 1em 0 0 1em; } .large-Grid--guttersLg { margin: -1.5em 0 1.5em -1.5em; } .large-Grid--guttersLg > .Grid-cell { padding: 1.5em 0 0 1.5em; } .large-Grid--guttersXl { margin: -2em 0 2em -2em; } .large-Grid--guttersXl > .Grid-cell { padding: 2em 0 0 2em; } } ================================================ FILE: assets/css/components/header.css ================================================ .Header { padding: 1.5em; background-color: rgba(147, 128, 108, 0.1); text-align: center; } @media (--break-lg) { .Header { padding: 3em 1.5em; } } .Header-title { margin: 0 0 0.15em; font-size: 1.8em; font-weight: 600; line-height: 1; word-spacing: 0.08em; } .Header-title i { font-family: serif; font-style: italic; font-weight: 400; } .Header-title a { border: 0; color: inherit; font-weight: inherit; } .Header-title a:focus, .Header-title a:hover, .Header-title a:active { text-decoration: none; } @media (--break-lg) { .Header-title { font-size: 4em; } } .Header-subTitle { margin: 0 0 1.5em; font-size: 0.8em; font-weight: 300; white-space: nowrap; } @media (--break-lg) { .Header-subTitle { margin: 1em 0 1.75em; font-size: 1.1em; } } .Header-actions { display: flex; align-items: stretch; flex-direction: column; font-size: 0.9em; } @media (--break-sm) { .Header-actions { align-items: center; flex-direction: row; justify-content: center; } } @media (--break-lg) { .Header-actions { font-size: 1.1em; } } .Header-button:first-child { margin: 0 0 1em; } @media (--break-sm) { .Header-button:first-child { margin: 0 1em 0 0; } } @media (--break-lg) { .Header--cozy { display: flex; padding: 1.5em; align-items: center; } .Header--cozy .Header-titles { display: flex; align-items: baseline; } .Header--cozy .Header-title { font-size: 1.5em; } .Header--cozy .Header-subTitle { margin: 0 0 0 1em; font-size: 0.8em; font-weight: 300; color: gray; } .Header--cozy .Header-actions { flex: 1; justify-content: flex-end; font-size: 0.9em; } } ================================================ FILE: assets/css/components/holy-grail.css ================================================ /** * 1. Avoid the IE 10-11 `min-height` bug. * 2. Set `flex-shrink` to `0` to prevent some browsers from * letting these items shrink to smaller than their content's default * minimum size. See http://bit.ly/1Mn35US for details. * 3. Use `%` instead of `vh` since `vh` is buggy in older mobile Safari. */ .HolyGrail { display: flex; height: 100%; /* 1, 3 */ flex-direction: column; } .HolyGrail-header, .HolyGrail-footer { flex: none; /* 2 */ } .HolyGrail-body { display: flex; flex: 1 0 auto; /* 2 */ flex-direction: column; padding: var(--space); } .HolyGrail-content { margin-top: var(--space); } .HolyGrail-nav { order: -1; } .HolyGrail-nav, .HolyGrail-ads { padding: 1em; border-radius: 3px; background: rgba(147, 128, 108, 0.1); } @media (--break-lg) { .HolyGrail-body { flex-direction: row; } .HolyGrail-content { flex: 1; padding: 0 var(--space-lg); margin: 0; } .HolyGrail-nav, .HolyGrail-ads { flex: 0 0 12em; } } ================================================ FILE: assets/css/components/image.css ================================================ .Image { display: block; width: 40px; height: auto; margin-top: 0.2em; } .Image--tiny { width: 30px; } @media (--break-md) { .Image { width: 70px; } .Image--tiny { width: 40px; } } ================================================ FILE: assets/css/components/input-add-on.css ================================================ .InputAddOn { display: flex; margin-bottom: 1.5em; } .InputAddOn-field { flex: 1; } .InputAddOn-field:not(:first-child) { border-left: 0; } .InputAddOn-field:not(:last-child) { border-right: 0; } .InputAddOn-item { background-color: rgba(147, 128, 108, 0.1); color: #666666; font: inherit; font-weight: normal; } .InputAddOn-field, .InputAddOn-item { border: 1px solid rgba(147, 128, 108, 0.25); padding: 0.5em 0.75em; } .InputAddOn-field:first-child, .InputAddOn-item:first-child { border-radius: 2px 0 0 2px; } .InputAddOn-field:last-child, .InputAddOn-item:last-child { border-radius: 0 2px 2px 0; } ================================================ FILE: assets/css/components/media.css ================================================ .Media { display: flex; align-items: flex-start; margin-bottom: 1em; } .Media-figure { margin-right: 1em; } .Media-body { flex: 1; } .Media-body, .Media-body :last-child { margin-bottom: 0; } .Media-title { margin: 0 0 .5em; } .Media--center { align-items: center; } .Media--reverse > .Media-figure { order: 1; margin: 0 0 0 1em; } ================================================ FILE: assets/css/components/notice.css ================================================ .Notice { background-color: hsl(90, 100%, 93%); color: hsla(0, 0%, 0%, .6); font-size: .9em; margin-bottom: var(--space); padding: 1.2em 1.5em; } ================================================ FILE: assets/css/components/section.css ================================================ .Section { padding: 0 var(--space); } .Section:nth-child(2n) { background-color: hsla(31, 15%, 50%, 0.1); overflow: hidden; /* Contain margins. */ } .Section::before, .Section::after { content: '\00a0'; /*   */ display: block; height: 0px; visibility: hidden; } .Section::before { margin-bottom: var(--space); } .Section::after { margin-top: var(--space); } @media (--break-lg) { .Section { padding: 0 var(--space-lg); } .Section::before { margin-bottom: var(--space-lg); } .Section::after { margin-top: var(--space-lg); } } .Section-heading { text-align: center; } @media (--break-lg) { .Section-list { padding: 0; margin: 0 calc(2 * var(--space-lg)) var(--space-lg); } } ================================================ FILE: assets/css/components/site.css ================================================ /** * 1. Avoid the IE 10-11 `min-height` bug. * 2. Set `flex-shrink` to `0` to prevent some browsers from * letting these items shrink to smaller than their content's default * minimum size. See http://bit.ly/1Mn35US for details. * 3. Use `%` instead of `vh` since `vh` is buggy in older mobile Safari. */ .Site { display: flex; flex-direction: column; height: 100%; /* 1, 3 */ } .Site-header, .Site-footer { flex: none; /* 2 */ } .Site-content { flex: 1 0 auto; /* 2 */ padding: var(--space) var(--space) 0; width: 100%; } .Site-content::after { content: '\00a0'; /*   */ display: block; margin-top: var(--space); height: 0px; visibility: hidden; } @media (--break-lg) { .Site-content { padding-top: var(--space-lg); } .Site-content::after { margin-top: var(--space-lg); } } .Site-content--full { padding: 0; } .Site-content--full::after { content: none; } ================================================ FILE: assets/css/main.css ================================================ @import 'normalize.css'; @import 'suitcss-utils-display'; @import 'suitcss-utils-text'; @import './base/variables'; @import './base/custom-media'; @import './base/elements'; @import './components/aligner'; @import './components/browser'; @import './components/button'; @import './components/container'; @import './components/demo'; @import './components/error'; @import './components/feature'; @import './components/footer'; @import './components/grid'; @import './components/header'; @import './components/holy-grail'; @import './components/image'; @import './components/input-add-on'; @import './components/media'; @import './components/notice'; @import './components/section'; @import './components/site'; @import './utils/compat'; @import './utils/media'; @import './utils/size'; @import './vendor/font-awesome-extensions'; @import './vendor/highlight'; @import './vendor/twitter'; ================================================ FILE: assets/css/utils/compat.css ================================================ /** * Fixes the min-height bug in IE10-11. * This class should be added to a container element as described in * Flexbug #3. See http://bit.ly/1gy8OJS for details. */ .u-ieMinHeightBugFix { display: flex; flex-direction: column; } ================================================ FILE: assets/css/utils/media.css ================================================ @import '../base/custom-media'; .u-full { width: 100% !important; flex: none !important; } .u-1of2 { width: 50% !important; flex: none !important; } .u-1of3 { width: 33.3333% !important; flex: none !important; } .u-2of3 { width: 66.6667% !important; flex: none !important; } .u-1of4 { width: 25% !important; flex: none !important; } .u-3of4 { width: 75% !important; flex: none !important; } @media (--break-sm) { .u-small-full { width: 100% !important; flex: none !important; } .u-small-1of2 { width: 50% !important; flex: none !important; } .u-small-1of3 { width: 33.3333% !important; flex: none !important; } .u-small-2of3 { width: 66.6667% !important; flex: none !important; } .u-small-1of4 { width: 25% !important; flex: none !important; } .u-small-3of4 { width: 75% !important; flex: none !important; } } @media (--break-md) { .u-med-full { width: 100% !important; flex: none !important; } .u-med-1of2 { width: 50% !important; flex: none !important; } .u-med-1of3 { width: 33.3333% !important; flex: none !important; } .u-med-2of3 { width: 66.6667% !important; flex: none !important; } .u-med-1of4 { width: 25% !important; flex: none !important; } .u-med-3of4 { width: 75% !important; flex: none !important; } } @media (--break-lg) { .u-large-full { width: 100% !important; flex: none !important; } .u-large-1of2 { width: 50% !important; flex: none !important; } .u-large-1of3 { width: 33.3333% !important; flex: none !important; } .u-large-2of3 { width: 66.6667% !important; flex: none !important; } .u-large-1of4 { width: 25% !important; flex: none !important; } .u-large-3of4 { width: 75% !important; flex: none !important; } } ================================================ FILE: assets/css/utils/size.css ================================================ .u-smaller { font-size: 0.85em; } .u-bigger { font-size: 1.2em; } ================================================ FILE: assets/css/vendor/font-awesome-extensions.css ================================================ .icon-big { font-size: 1.5em; } ================================================ FILE: assets/css/vendor/highlight.css ================================================ @import "highlight.js/styles/github"; pre { border-radius: 3px; background: hsla(31, 15%, 50%, 0.1); font-size: 0.85em; margin-bottom: calc(var(--space)/0.85); overflow-x: auto; padding: 1.25em 1.5em; } ================================================ FILE: assets/css/vendor/twitter.css ================================================ .twitter-follow-button { width: 235px !important; } .twitter-color { color: #00ACED; } ================================================ FILE: assets/main.js ================================================ import {getCLS, getFCP, getFID, getLCP} from 'web-vitals'; const thresholds = { CLS: [0.1, 0.25], FCP: [1800, 3000], FID: [100, 300], LCP: [2500, 4000], } function getRating(value, thresholds) { if (value > thresholds[1]) { return 'poor'; } if (value > thresholds[0]) { return 'ni'; } return 'good'; } function sendToGoogleAnalytics({name, value, delta, id}) { gtag('event', name, { value: Math.round(name === 'CLS' ? delta * 1000 : delta), event_category: 'Web Vitals', event_label: getRating(value, thresholds[name]), event_id: id, non_interaction: true, }); } getCLS(sendToGoogleAnalytics); getFCP(sendToGoogleAnalytics); getFID(sendToGoogleAnalytics); getLCP(sendToGoogleAnalytics); ================================================ FILE: config.json ================================================ { "title": "Solved by Flexbox", "tagline": "Cleaner, hack-free CSS", "description": "A showcase of problems once hard or impossible to solve with CSS alone, now made trivially easy with Flexbox." } ================================================ FILE: demos/grids.md ================================================ --- template: default.html title: Better, Simpler Grid Systems excerpt: Flexbox gives us most of the features we want from a grid system out of the box. And sizing and alignment are just one or two properties away. --- Most grid systems today use one of two layout methods: `float` or `inline-block`. But neither of these methods were really intended to be used for layout and as a result have pretty significant problems and limitations. Using floats requires clearing them which has a whole host of layout issues, most notoriously that clearing an element sometimes forces it below an unrelated part of the page (take this [Bootstrap issue](https://github.com/twbs/bootstrap/issues/295#issuecomment-2282969) for example). In addition, clearing floats usually requires using both before and after pseudo-elements, preventing you from using them for something else. Inline block layouts must address the problem of [white-space between inline-block items](http://css-tricks.com/fighting-the-space-between-inline-block-elements/), and all of the [solutions](http://davidwalsh.name/remove-whitespace-inline-block) to that problem are [hacky](https://github.com/suitcss/components-grid/blob/master/lib/grid.css#L30) and [annoying](https://twitter.com/thierrykoblentz/status/305152267374428160). Flexbox not only eliminates these problems, it opens up an entirely new world of possibilities. ## Features of a Flexbox Grid System Grid systems usually come with a myriad of sizing options, but the vast majority of the time you just want two or three elements side-by-side. Given this, why should we be required to put sizing classes on every single cell? Listed below are some of my criteria for an ideal grid system. Fortunately, with Flexbox we get most of these features for free. - By default, each grid cell is the same width and height as every other cell in the row. Basically they all size to fit by default. - For finer control, you can add sizing classes to individual cells. Without these classes, the cells simply divide up the available space as usual. - For responsive grids, you can add media query-specific classes to the cells. - Individual cells can be aligned vertically to the top, bottom, or middle. - When you want all of the cells in a grid to have the same sizing, media, or alignment values, you should be able to just add a single class to the container to avoid unnecessary repetition. - Grids can be nested as many levels deep as needed. ### Basic Grids The grid cells below do not specify any widths, they just naturally space themselves equally and expand to fit the entire row. They're also equal height by default.
1/2
1/2
1/3
1/3
1/3
1/4
1/4
1/4
1/4
Full-height, even when my content doesn't fill the space.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum mollis velit non gravida venenatis. Praesent consequat lectus purus, ut scelerisque velit condimentum eu. Maecenas sagittis ante ut turpis varius interdum. Quisque tellus ipsum, eleifend non ipsum id, suscipit ultricies neque.
### Individual Sizing When equal widths aren't what you want, you can add sizing classes to individual cells. Cells without sizing classes simply divide up the remaining space as normal. The cells below labeled "auto" do not have sizing classes specified.
1/2
auto
auto
auto
1/3
1/4
auto
1/3
### Responsive Responsive Grids work by adding media classes to the Grid cells or containers. When those media values are met, the grids automatically adjust accordingly. The cells below should be full width by default and scaled to fit above `48em`. Resize your browser to see them in action.
Full / Halves
Full / Halves
Full / Thirds
Full / Thirds
Full / Thirds
### Grid-ception Grid components are infinitely nestable inside of other grid components.
1/3
1/2
1/2
1/3
## Alignment Features ### Top-aligned Grid Cells
This cell should be top-aligned.
Pellentesque sagittis vel erat ac laoreet. Phasellus ac aliquet enim, eu aliquet sem. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed pulvinar porta leo, eu ultricies nunc sollicitudin vitae. Curabitur pulvinar dolor lectus, quis porta turpis ullamcorper nec. Quisque eget varius turpis, quis iaculis nibh.
This cell should be top-aligned.
### Bottom-aligned Grid Cells
This cell should be bottom-aligned.
Curabitur pulvinar dolor lectus, quis porta turpis ullamcorper nec. Quisque eget varius turpis, quis iaculis nibh. Ut interdum ligula id metus hendrerit cursus. Integer eu leo felis. Aenean commodo ultrices nunc, sit amet blandit elit gravida in.
This cell should be bottom-aligned.
### Vertically Centered Grid Cells
This cell should be vertically-centered with the cell to its right.
Curabitur pulvinar dolor lectus, quis porta turpis ullamcorper nec. Quisque eget varius turpis, quis iaculis nibh. Ut interdum ligula id metus hendrerit cursus. Integer eu leo felis. Aenean commodo ultrices nunc, sit amet blandit elit gravida in. Sed est ligula, ornare ac nisi adipiscing, iaculis facilisis tellus. Nullam vel facilisis libero. Duis semper lobortis elit, vitae dictum erat.
### Mixed Vertical Alignment
This cell should be top aligned.
Curabitur pulvinar dolor lectus, quis porta turpis ullamcorper nec. Quisque eget varius turpis, quis iaculis nibh. Ut interdum ligula id metus hendrerit cursus. Integer eu leo felis. Aenean commodo ultrices nunc, sit amet blandit elit gravida in. Sed est ligula, ornare ac nisi adipiscing, iaculis facilisis tellus.
This cell should be center-aligned.
This cell should be bottom-aligned.
## The HTML ```html
``` ## The CSS ### Basic Grid Styles ```css .Grid { display: flex; } .Grid-cell { flex: 1; } ``` ### Grid Style Modifiers ```css /* With gutters */ .Grid--gutters { margin: -1em 0 0 -1em; } .Grid--gutters > .Grid-cell { padding: 1em 0 0 1em; } /* Alignment per row */ .Grid--top { align-items: flex-start; } .Grid--bottom { align-items: flex-end; } .Grid--center { align-items: center; } /* Alignment per cell */ .Grid-cell--top { align-self: flex-start; } .Grid-cell--bottom { align-self: flex-end; } .Grid-cell--center { align-self: center; } ``` ### Responsive Modifiers (a mobile-first approach) ```css /* Base classes for all media */ .Grid--fit > .Grid-cell { flex: 1; } .Grid--full > .Grid-cell { flex: 0 0 100%; } .Grid--1of2 > .Grid-cell { flex: 0 0 50% } .Grid--1of3 > .Grid-cell { flex: 0 0 33.3333% } .Grid--1of4 > .Grid-cell { flex: 0 0 25% } /* Small to medium screens */ @media (min-width: 24em) { .small-Grid--fit > .Grid-cell { flex: 1; } .small-Grid--full > .Grid-cell { flex: 0 0 100%; } .small-Grid--1of2 > .Grid-cell { flex: 0 0 50% } .small-Grid--1of3 > .Grid-cell { flex: 0 0 33.3333% } .small-Grid--1of4 > .Grid-cell { flex: 0 0 25% } } /* Large screens */ @media (min-width: 48em) { .large-Grid--fit > .Grid-cell { flex: 1; } .large-Grid--full > .Grid-cell { flex: 0 0 100%; } .large-Grid--1of2 > .Grid-cell { flex: 0 0 50% } .large-Grid--1of3 > .Grid-cell { flex: 0 0 33.3333% } .large-Grid--1of4 > .Grid-cell { flex: 0 0 25% } } ``` View the full [source](https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/grid.css) for the `Grid` component used in this demo on Github. ================================================ FILE: demos/holy-grail.md ================================================ --- template: holy-grail.html title: Holy Grail Layout excerpt: This classic problem has been challenging CSS hackers for years, yet none of the historical solutions have fully solved it. With Flexbox, it's finally possible. --- The [Holy Grail Layout](http://en.wikipedia.org/wiki/Holy_Grail_(web_design)) is a classic CSS problem with various solutions presented over time. If you're unfamiliar with the history of the Holy Grail layout, this [A List Apart article](http://alistapart.com/article/holygrail) offers a pretty good summary and links to a few of the more well-known solutions. At its core, the Holy Grail Layout is a page with a header, footer, and three columns. The center column contains the main content, and the left and right columns contain supplemental content like ads or navigation. Most CSS solutions to this problem aim to meet a few goals: - They should have a fluid center with fixed-width sidebars. - The center column (main content) should appear first in the HTML source. - All columns should be the same height, regardless of which column is actually the tallest. - They should require minimal markup. - The footer should "stick" to the bottom of the page when content is sparse. Unfortunately, because of the nature of these goals and the original limitations of CSS, none of the classic solutions to this problem were ever able to satisfy all of them. With Flexbox, a complete solution is finally possible. ## The HTML ```html
``` ## The CSS Getting the center content row to stretch and the footer to stick to the bottom is solved with the same technique shown in the [Sticky Footer](../sticky-footer/) example. The only difference is the center row of the Holy Grail layout (`.HolyGrail-body`) needs to be `display:flex` in order to properly arrange its children. ```css .HolyGrail { display: flex; min-height: 100vh; flex-direction: column; } .HolyGrail-body { display: flex; flex: 1; } ``` Styling three equal-height columns with a fluid center and fixed-width sidebars is just as easy: ```css .HolyGrail-content { flex: 1; } .HolyGrail-nav, .HolyGrail-ads { /* 12em is the width of the columns */ flex: 0 0 12em; } .HolyGrail-nav { /* put the nav on the left */ order: -1; } ``` ### Being Responsive The Holy Grail layout came from an era of Web design when pretty much everyone was browsing on a computer. But with the increasing number of mobile devices and the rising popularity of responsive design, the Holy Grail layout has gone mostly out of fashion. Either way, with Flexbox, creating a mobile-first and mobile-friendly version of the Holy Grail layout is easy. The gist is to simply make the center section `flex-direction:column` by default and then `flex-direction:row` for larger screens. Here's a complete example that is responsive and mobile-first. You can also resize this browser window to see it in action. ```css .HolyGrail, .HolyGrail-body { display: flex; flex-direction: column; } .HolyGrail-nav { order: -1; } @media (min-width: 768px) { .HolyGrail-body { flex-direction: row; flex: 1; } .HolyGrail-content { flex: 1; } .HolyGrail-nav, .HolyGrail-ads { /* 12em is the width of the columns */ flex: 0 0 12em; } } ``` View the full [source](https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/holy-grail.css) for the `HolyGrail` component used in this demo on Github. ================================================ FILE: demos/input-add-ons.md ================================================ --- template: default.html title: Input Add-ons excerpt: Creating full-width, fluid input/button pairs has been impossible for most of the history of CSS. With Flexbox it couldn't be easier. --- Because of the way input sizing works in CSS, it's almost impossible to append or prepend another element to it and have the input field behave fluidly and take up the remaining space. The only existing way to do this is to either know the exact width of the input, or to use something like `display:table-cell`, which has its own set of problems, most notably the difficulty with positioning anything absolutely inside of the add-on in certain browsers. With Flexbox, all these problems go away, and the code is trivially simple. In addition, you get the input field and the input add-on to be the same height for free.

Add-on Prepended

Amount

Add-on Appended

## Appended and Prepended Add-ons
## The HTML ```html
``` ## The CSS ```css .InputAddOn { display: flex; } .InputAddOn-field { flex: 1; /* field styles */ } .InputAddOn-item { /* item styles */ } ``` View the full [source](https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/input-add-on.css) for the `InputAddOn` component used in this demo on Github. ================================================ FILE: demos/media-object.md ================================================ --- template: default.html title: Media Object excerpt: Create media objects with fixed or varying figure sizes without worrying about overflow, clearfixing, or block formatting context hacks. --- The [media object](http://www.stubbornella.org/content/2010/06/25/the-media-object-saves-hundreds-of-lines-of-code) is the poster-child of Object Oriented CSS (OOCSS). Its simplicity and utility have converted many a CSS developer (myself included) to the OOCSS methodology. But like most CSS layout techniques, the media object must resort to tricks and hacks to accomplish its goals. The media object's body must prevent text from wrapping below the image by either creating a [block formatting context](http://www.stubbornella.org/content/2013/07/31/re-visiting-the-secret-power-of-block-fomatting-context/) or using a left margin/padding equal to the width of the image. The media object must also clearfix its body which requires either `overflow:hidden` or having to use the pseudo-elements. With Flexbox these problems are solved. In addition, Flexbox allows us to vertically align the media object figure however we want. We can also easily align the figure to the right without needing to change the source order. ## Basic Examples
Kitten

Standard Media Object

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ac nisl quis massa vulputate adipiscing. Vivamus sit amet risus ligula. Nunc eu pulvinar augue.

Kitten

Standard Media Object

Donec imperdiet sem leo, id rutrum risus aliquam vitae. Cras tincidunt porta mauris, vel feugiat mauris accumsan eget.

Kitten

Media Object Reversed

Phasellus vel felis purus. Aliquam consequat pellentesque dui, non mollis erat dictum sit amet. Curabitur non quam dictum, consectetur arcu in, vehicula justo. Donec tortor massa, eleifend nec viverra in, aliquet at eros. Mauris laoreet condimentum mauris, non tempor massa fermentum ut. Integer gravida pharetra cursus. Nunc in suscipit nunc.

## Non-images

Using Icons

Donec imperdiet sem leo, id rutrum risus aliquam vitae. Vestibulum ac turpis non lacus dignissim dignissim eu sed dui.

Vertically Centering the Figure

Nunc nec fermentum dolor. Duis at iaculis turpis. Sed rutrum elit ac egestas dapibus. Duis nec consequat enim.

## Nested Media Objects
Kitten

Media Object Title

Phasellus vel felis purus. Aliquam consequat pellentesque dui, non mollis erat dictum sit amet. Curabitur non quam dictum, consectetur arcu in, vehicula justo.

Kitten

Mauris porta arcu id magna adipiscing lacinia at congue lacus. Vivamus blandit quam quis tincidunt egestas. Etiam posuere lectus sed sapien malesuada molestie.

Kitten

Vestibulum ac turpis non lacus dignissim dignissim eu sed dui. Proin a ligula sit amet massa malesuada mattis eu a ante. Nunc porttitor sed quam quis sollicitudin. Vestibulum ac turpis non lacus dignissim dignissim eu sed dui.

Rutrum risus aliquam vitae.

Kitten

Media Object Title

Phasellus vel felis purus. Aliquam consequat pellentesque dui, non mollis erat dictum sit amet. Curabitur non quam dictum, consectetur arcu in, vehicula justo. Donec tortor massa, eleifend nec viverra in, aliquet at eros. Mauris laoreet condimentum mauris, non tempor massa fermentum ut.

Donec imperdiet sem leo, id rutrum risus aliquam vitae.

Kitten

Mauris porta arcu id magna adipiscing lacinia at congue lacus. Vivamus blandit quam quis tincidunt egestas. Etiam posuere lectus sed sapien malesuada molestie. Aliquam vitae pharetra dolor. Nullam non mattis nunc.

## The HTML ```html

``` ## The CSS ```css .Media { display: flex; align-items: flex-start; } .Media-figure { margin-right: 1em; } .Media-body { flex: 1; } ``` View the full [source](https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/media.css) for the `Media` component used in this demo on Github. ================================================ FILE: demos/sticky-footer.md ================================================ --- template: default.html title: Sticky Footer excerpt: Getting your footer to stick to the bottom of sparsely contented pages has always been tricky. And if the footer's height is unknown, it's basically impossible. Not so anymore. ---
Click the button below to hide the contents of this page. Notice how the footer sticks to the bottom of the window even when there's not enough content to fill the page.
Getting the footer to stick to the bottom of pages with sparse content is something just about every Web developer has tried to tackle at some point in his or her career. And, for the most part, it's a solved problem. Yet all the [existing solutions](http://ryanfait.com/resources/footer-stick-to-bottom-of-page/) have one significant shortcoming — they don't work if the height of your footer is unknown. Flexbox is a perfect fit for this type of problem. While mostly known for laying out content in the horizontal direction, Flexbox actually works just as well for vertical layout problems. All you have to do is wrap the vertical sections in a flex container and choose which ones you want to expand. They'll automatically take up all the available space in their container. In the example below, the container is set to the height of the window, and the content area is told to expand as needed. *(Note: in the vertical direction you need to specify a height for the container. This is different from the horizontal direction, which automatically expands to fit.)* ## The HTML ```xml
``` ## The CSS ```css .Site { display: flex; min-height: 100vh; flex-direction: column; } .Site-content { flex: 1; } ``` View the full [source](https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css) for the `Site` component used in this demo on Github.
================================================ FILE: demos/vertical-centering.md ================================================ --- template: default.html title: Vertical Centering excerpt: This classic problem has been challenging CSS hackers for years, yet none of the historical solutions have fully solved it. With Flexbox, it's finally possible. --- The lack of good ways to vertically center elements in CSS has been a dark blemish on its reputation for pretty much its entire existence. What makes matters worse is the techniques that do work for vertical centering are obscure and unintuitive, while the obvious choices (like `vertical-align:middle`) never seem to work when you need them. The current landscape of [vertical centering options](http://css-tricks.com/centering-in-the-unknown/) ranges from negative margins to `display:table-cell` to ridiculous hacks involving full-height pseudo-elements. Yet even though these techniques sometimes get the job done, they don't work in every situation. What if the thing you want to center is of unknown dimensions and isn't the only child of its parent? What if you could use the pseudo-element hack, but you need those pseudo-elements for something else? With Flexbox, you can stop worrying. You can align anything (vertically or horizontally) quite painlessly with the `align-items`, `align-self`, and `justify-content` properties.

I'm Centered!

This box is both vertically and horizontally centered. Even if the text in this box changes to make it wider or taller, the box will still be centered. Go ahead, give it a try. Just click to edit the text.

Unlike some of the existing vertical alignment techniques, with Flexbox the presence of sibling elements doesn't affect their ability to be vertically aligned.
Top
Centered
Bottom
## The HTML ```html
``` ## The CSS ```css .Aligner { display: flex; align-items: center; justify-content: center; } .Aligner-item { max-width: 50%; } .Aligner-item--top { align-self: flex-start; } .Aligner-item--bottom { align-self: flex-end; } ``` View the full [source](https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/aligner.css) for the `Aligner` component used in this demo on Github. ================================================ FILE: gulpfile.js ================================================ const connect = require('connect'); const cssnano = require('cssnano'); const fs = require('fs-extra'); const frontMatter = require('front-matter'); const globby = require('globby'); const gulp = require('gulp'); const he = require('he'); const hljs = require('highlight.js'); const htmlMinifier = require('html-minifier'); const MarkdownIt = require('markdown-it'); const nunjucks = require('nunjucks'); const path = require('path'); const postcss = require('postcss'); const atImport = require('postcss-import'); const postcssPresetEnv = require('postcss-preset-env'); const serveStatic = require('serve-static'); const sh = require('shelljs'); const {argv} = require('yargs'); const isProd = () => process.env.NODE_ENV == 'production'; /** * The output directory for all the built files. */ const DEST = './solved-by-flexbox'; /** * The base public path of the site. */ const PUBLIC_PATH = path.join('/', DEST, '/'); nunjucks.configure('templates', {autoescape: false, noCache: true}); /** * Renders markdown content as HTML with syntax highlighted code blocks. * @param {string} content A markdown string. * @return {string} The rendered HTML. */ const renderMarkdown = (content) => { const md = new MarkdownIt({ html: true, typographer: true, highlight: (code, lang) => { code = lang ? hljs.highlight(lang, code).value : // Since we're not using highlight.js here, we need to // espace the html, but we have to unescape first in order // to avoid double escaping. he.escape(he.unescape(code)); return code; }, }); return md.render(content); }; gulp.task('pages', async () => { const baseData = await fs.readJSON('./config.json'); const overrides = { baseUrl: PUBLIC_PATH, env: process.env.NODE_ENV || 'development' }; const site = Object.assign({demos: []}, baseData, overrides); const processContent = async (pagePath) => { const slug = path.basename(pagePath, path.extname(pagePath)); const permalink = site.baseUrl + (slug === 'index' ? '' : 'demos/' + slug + '/'); const fileContents = await fs.readFile(pagePath, 'utf-8'); const {body, attributes} = frontMatter(fileContents); const data = { site, page: { content: body, slug, permalink, ...attributes, }, }; if (path.extname(pagePath) == '.md') { data.page.content = renderMarkdown(data.page.content); } data.page.content = nunjucks.renderString(data.page.content, data); return data; } const renderPage = async (data) => { let html = nunjucks.render(data.page.template, data); if (process.env.NODE_ENV === 'production') { html = htmlMinifier.minify(html, { removeComments: true, collapseWhitespace: true, collapseBooleanAttributes: true, removeAttributeQuotes: true, removeRedundantAttributes: true, useShortDoctype: true, removeEmptyAttributes: true, minifyJS: true, minifyCSS: true, }); }; const outputPath = path.join(data.page.permalink.slice(1), 'index.html'); await fs.outputFile(outputPath, html); }; const demoPaths = await globby('./demos/**/*'); for (const demoPath of demoPaths) { const data = await processContent(demoPath); // Add the page data to the site demos. site.demos.push(data.page); await renderPage(data); }; const pagePaths = await globby('*.html'); for (const pagePath of pagePaths) { const data = await processContent(pagePath); await renderPage(data); }; }); gulp.task('images', () => { return gulp.src('./assets/images/**/*') .pipe(gulp.dest(path.join(DEST, 'images'))); }); gulp.task('css', async () => { const src = './assets/css/main.css'; const css = await fs.readFile(src, 'utf-8'); const plugins = [ atImport(), postcssPresetEnv({ stage: 0, browsers: '> 1%, last 2 versions, Safari > 5, ie > 9, Firefox ESR', }), ]; if (process.env.NODE_ENV === 'production') { plugins.push(cssnano({ preset: ['default', {discardComments: {removeAll: true}}], })); } const result = await postcss(plugins).process(css, {from: src}); await fs.outputFile(path.join(DEST, path.basename(src)), result.css); }); gulp.task('javascript', async () => { await sh.exec('rollup -c'); }); gulp.task('default', gulp.parallel('css', 'images', 'javascript', 'pages')); gulp.task('serve', gulp.series('default', () => { let port = argv.port || argv.p || 4000; connect().use(serveStatic('./')).listen(port); gulp.watch('./assets/css/**/*.css', gulp.series('css')); gulp.watch('./assets/images/*', gulp.series('images')); gulp.watch('./assets/main.js', gulp.series('javascript')); gulp.watch(['*.html', './demos/*', './templates/*'], gulp.series('pages')); })); gulp.task('deploy', gulp.series('default', (done) => { if (process.env.NODE_ENV != 'production') { throw new Error('Deploying requires NODE_ENV to be set to production'); } const repoUrl = 'git@github.com:philipwalton/solved-by-flexbox.git'; // Create a temporary directory and // checkout the existing gh-pages branch. sh.rm('-rf', '_tmp'); sh.mkdir('_tmp'); sh.cd('_tmp'); sh.exec('git init'); sh.exec('git remote add origin ' + repoUrl); sh.exec('git pull origin gh-pages'); // Delete all the existing files and add // the new ones from the build directory. sh.rm('-rf', './*'); sh.cp('-rf', path.join('..', DEST, '/*'), './'); sh.exec('git add -A'); // Commit and push the changes to // the gh-pages branch. sh.exec('git commit -m "Deploy site"'); sh.exec('git branch -m gh-pages'); sh.exec('git push origin gh-pages'); // Clean up. sh.cd('..'); sh.rm('-rf', '_tmp'); sh.rm('-rf', DEST); done(); })); ================================================ FILE: index.html ================================================ --- template: home.html ---

Introduction

CSS has been lacking proper layout mechanisms for far too long. Transitions, animations, filters, all of these are great and useful additions to the language, but they don't address the major problems that Web developers have been complaining about for what seems like an eternity.

Finally, thanks to Flexbox, we have a solution.

This site is not another CSS framework. Instead, its purpose is to showcase problems once hard or impossible to solve with CSS alone, now made trivially easy with Flexbox. With the release of Internet Explorer 11 and Safari 6.1, the latest Flexbox spec is now supported in every modern browser.

Check out the demos below. View the styles in the Web inspector or dive into the source to see just how easy CSS layout becomes with Flexbox.

Showcase

Browser Support

Caveats and Known Issues

About the Code

All of the code samples on this site show how to solve a particular design problem with Flexbox. They show just the code that's needed to make the demos work in a spec-compliant browser. Some browsers do not fully comply with the latest version of the spec, so sadly, a few workarounds were necessary.

Workarounds for non-compliant browsers are not shown in the code samples, but if you're curious about those implementation details, you can check out the source files. Each demo links to its source, and all browser-specific workarounds are well-documented, so don't be afraid to take a look.

The vendor prefixing and translating of current flex properties to their legacy equivalents is all handled by autoprefixer. If you're writing Flexbox code and not using autoprefixer, well, you're making a horrible mistake.

The class naming convention used in the code samples and source files is taken from SUIT CSS, which is based on BEM methodologies. Each example includes one or more reusable CSS components allowing you to adapt or copy these patterns in to your own projects. Links are provided to their respective components on each example page.

If you find a mistake or would like to suggest an additional example, feel free to open an issue or submit a pull request on Github.

Translations

The following translations have been graciously provided by the community:

Please note that translations are unofficial and may be inaccurate or out of date. To submit your own translation, please submit a pull request or open an issue on GitHub and link to your translated content.

================================================ FILE: package.json ================================================ { "name": "solved-by-flexbox", "description": "A showcase of problems once hard or impossible to solve with CSS alone, now made trivially easy with Flexbox.", "homepage": "https://philipwalton.github.io/solved-by-flexbox", "repository": { "type": "git", "url": "https://github.com/philipwalton/solved-by-flexbox.git" }, "license": "MIT", "scripts": { "build": "gulp", "start": "gulp serve", "deploy": "rm -rf solved-by-flexbox && NODE_ENV=production gulp deploy" }, "devDependencies": { "@rollup/plugin-node-resolve": "^11.0.0", "autoprefixer": "^10.0.4", "connect": "^3.7.0", "cssnano": "^4.1.10", "dot-prop": ">=4.2.1", "front-matter": "^4.0.2", "fs-extra": "^9.0.1", "globby": "^11.0.1", "gulp": "^4.0.2", "he": "^1.2.0", "highlight.js": "^10.4.0", "html-minifier": "^4.0.0", "markdown-it": "^12.0.2", "normalize.css": "^8.0.1", "nunjucks": "3.2.2", "postcss": "^8.1.10", "postcss-import": "^13.0.0", "postcss-preset-env": "^6.7.0", "rollup": "^2.34.0", "rollup-plugin-terser": "^7.0.2", "serve-static": "^1.14.1", "shelljs": "^0.8.4", "suitcss-utils-display": "^1.0.2", "suitcss-utils-text": "^1.0.0", "web-vitals": "^1.0.1", "yargs": "^16.1.1" } } ================================================ FILE: rollup.config.js ================================================ import nodeResolve from '@rollup/plugin-node-resolve'; import {terser} from 'rollup-plugin-terser'; const plugins = [ nodeResolve(), ] if (process.env.NODE_ENV === 'production') { plugins.push(terser({module: true})); } export default { plugins, input: 'assets/main.js', output: { dir: 'solved-by-flexbox', format: 'esm', }, }; ================================================ FILE: templates/default.html ================================================ {% include 'head.html' %}

{{ page.title }}

{{ page.content }}
{% include 'scripts.html' %} ================================================ FILE: templates/footer.html ================================================ Star @philwalton Tweet ================================================ FILE: templates/head.html ================================================ {% if page.title %}{{ page.title }} — {% endif %}{{ site.title }} — {{ site.tagline }} ================================================ FILE: templates/header.html ================================================

Solved by Flexbox

{{ site.tagline }}

  View Project Source   Spread the Word
================================================ FILE: templates/holy-grail.html ================================================ {% include 'head.html' %}

{{ page.title }}

{{ page.content }}
{% include 'scripts.html' %} ================================================ FILE: templates/home.html ================================================ {% include 'head.html' %}
{{ page.content }}
{% include 'scripts.html' %} ================================================ FILE: templates/scripts.html ================================================