├── .eslintrc ├── .gitignore ├── .jshintrc ├── .travis.yml ├── 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 └── images │ ├── browser-logos.jpg │ ├── grids.jpg │ ├── holy-grail.jpg │ ├── input-add-ons.jpg │ ├── kitten.jpg │ ├── media-object.jpg │ ├── sticky-footer.jpg │ └── vertical-centering.jpg ├── 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-lock.json ├── package.json └── templates ├── default.html ├── footer.html ├── head.html ├── header.html ├── holy-grail.html ├── home.html └── scripts.html /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "env": { 4 | "browser": true, 5 | "es6": true, 6 | "node": true, 7 | "mocha": true 8 | }, 9 | "globals": { 10 | "browser": false 11 | }, 12 | "extends": [ 13 | "eslint:recommended" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS or Editor folders 2 | .DS_Store 3 | 4 | # npm/yarn files 5 | node_modules 6 | *.log 7 | *.lock 8 | 9 | # Static site output 10 | _tmp/ 11 | solved-by-flexbox/ 12 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "browser": true, 3 | "boss": true, 4 | "esnext": true, 5 | "expr": true, 6 | "node": true, 7 | "quotmark": "single" 8 | } 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: node 3 | before_script: 4 | - npm install -g gulp-cli 5 | script: 6 | - export NODE_ENV=production 7 | - gulp 8 | 9 | deploy: 10 | - provider: pages 11 | skip-cleanup: true 12 | github-token: $GITHUB_TOKEN 13 | local-dir: solved-by-flexbox 14 | on: 15 | branch: zh 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Philip Walton 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Solved by Flexbox](https://magic-akari.github.io/solved-by-flexbox/) 2 | [](https://travis-ci.org/magic-akari/solved-by-flexbox) 3 | 4 | 一组示例用于展示曾经难于或无法单独用 CSS 解决的问题, 现在使用 Flexbox 让问题迎刃而解. 5 | 6 | [点击查看](https://magic-akari.github.io/solved-by-flexbox/) 7 | 8 | ## 在本地查看示例 9 | 10 | Solved by Flexbox 页面使用 [Node.js](http://nodejs.org/) 构建. 如果你已经安装 Node.js, 你可以运行下列命令来构建一份本地的拷贝. 11 | 12 | ```sh 13 | # 克隆这个 git 仓库并使用 cd 命令进入克隆的目录. 14 | git clone https://github.com/magic-akari/solved-by-flexbox 15 | cd solved-by-flexbox 16 | 17 | # 安装依赖 18 | npm install 19 | 20 | # 运行, 可以访问 http://localhost:4000 查看 21 | npm start 22 | ``` 23 | 24 | 这个命令会启动一个端口号为 4000 的本地服务. 在浏览器访问 [http://localhost:4000](http://localhost:4000) 即可查看页面. 如果你想使用不同的端口, 可以在 `npm start` 命令后传入参数: 25 | 26 | ```sh 27 | npm start -- -p 8080 28 | ``` 29 | 30 | 此外, 本地启动的服务会监听文件修改, 并自动重新按需构建. 这允许你测试代码, 在浏览器刷新, 并立即查看结果. 31 | 32 | ## 翻译 33 | 34 | 下面的翻译由热心的社区提供: 35 | 36 | * [Chinese](https://magic-akari.github.io/solved-by-flexbox/) 37 | * [Japanese](http://hashrock.github.io/solved-by-flexbox-ja/) 38 | * [Korean](https://hyunseob.github.io/solved-by-flexbox-kr/) 39 | 40 | 请注意, 翻译并非官方提供, 可能随着时间推移而过时. 你可以在 Github 上发送一个 [pull request](https://github.com/philipwalton/solved-by-flexbox/pull/new/master) 或者 [开一个 issue](https://github.com/philipwalton/solved-by-flexbox/issues/new) 提供你的翻译内容的链接. 41 | -------------------------------------------------------------------------------- /assets/css/base/custom-media.css: -------------------------------------------------------------------------------- 1 | @custom-media --break-sm (min-width: 384px); 2 | @custom-media --break-md (min-width: 576px); 3 | @custom-media --break-lg (min-width: 768px); 4 | 5 | @custom-media --high-dppx (-webkit-min-device-pixel-ratio: 1.5), 6 | (min-resolution: 144dpi), (min-resolution: 1.5dppx); 7 | -------------------------------------------------------------------------------- /assets/css/base/elements.css: -------------------------------------------------------------------------------- 1 | *, 2 | *::after, 3 | *::before { 4 | box-sizing: border-box; 5 | } 6 | 7 | html { 8 | height: 100%; 9 | color: hsl(0,0%,25%); 10 | font: 400 1em/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 11 | text-rendering: optimizeLegibility; 12 | 13 | text-align: justify; 14 | text-justify: inter-ideograph; 15 | -ms-text-justify: inter-ideograph; 16 | -moz-text-align-last:justify; 17 | -webkit-text-align-last:justify; 18 | } 19 | @media (--high-dppx) { 20 | html { 21 | font-weight: 300; 22 | } 23 | } 24 | 25 | h1 { 26 | font-weight: 300; 27 | font-size: 2em; 28 | -webkit-font-kerning: normal; 29 | letter-spacing: -.015em; 30 | line-height: 1; 31 | margin: .25em 0 .75em; 32 | } 33 | @media (--break-lg) { 34 | h1 { 35 | font-size: 2.5em; 36 | margin: .5em 0 1em; 37 | } 38 | } 39 | 40 | 41 | h2 { 42 | font-size: 1.333em; 43 | font-weight: 600; 44 | margin: 0 0 calc(1.5em/1.333); 45 | } 46 | 47 | h3 { 48 | font-size: 1em; 49 | font-weight: 600; 50 | margin: 0 0 1.5em; 51 | } 52 | 53 | p, 54 | pre { 55 | margin: 0 0 1.5em; 56 | } 57 | 58 | code, 59 | pre { 60 | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace 61 | } 62 | 63 | code { 64 | font-size: .9em; 65 | font-weight: normal; 66 | color: #000; 67 | } 68 | 69 | pre > code { 70 | font: inherit; 71 | color: inherit; 72 | } 73 | 74 | a { 75 | border-bottom: 1px dashed hsla(150, 45%, 50%, 0.5); 76 | color: hsl(150, 45%, 50%); 77 | text-decoration: none; 78 | } 79 | a:focus, 80 | a:hover { 81 | border-bottom: 1px solid hsl(150, 45%, 50%); 82 | } 83 | 84 | ol, 85 | ul { 86 | list-style: square; 87 | margin: 0 0 1.5em; 88 | padding: 0 0 0 1.5em; 89 | } 90 | 91 | li { 92 | margin-bottom: 0.333em; 93 | } 94 | 95 | 96 | figure { 97 | margin: 0; 98 | } 99 | 100 | strong { 101 | font-weight: 600; 102 | } 103 | -------------------------------------------------------------------------------- /assets/css/base/variables.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --space: 1.5em; 3 | --space-lg: 2em; 4 | --bg-color: hsl(150, 45%, 50%); 5 | } 6 | -------------------------------------------------------------------------------- /assets/css/components/aligner.css: -------------------------------------------------------------------------------- 1 | .Aligner { 2 | display: flex; 3 | align-items: center; 4 | min-height: 24em; 5 | justify-content: center; 6 | } 7 | 8 | .Aligner-item { 9 | flex: 1; 10 | } 11 | 12 | .Aligner-item--top { 13 | align-self: flex-start; 14 | } 15 | 16 | .Aligner-item--bottom { 17 | align-self: flex-end; 18 | } 19 | 20 | .Aligner-item--fixed { 21 | flex: none; 22 | max-width: 50%; 23 | } 24 | -------------------------------------------------------------------------------- /assets/css/components/browser.css: -------------------------------------------------------------------------------- 1 | .Browser { 2 | font-size: .8em; 3 | text-align: center; 4 | } 5 | 6 | .Browser-image { 7 | height: 64px; 8 | width: 64px; 9 | margin: 0 0.5em 0.5em; 10 | background: url('images/browser-logos.jpg') no-repeat 0 0; 11 | background-size: auto 100%; 12 | } 13 | 14 | .Browser--chrome > .Browser-image { 15 | background-position: 0 0; 16 | } 17 | 18 | .Browser--opera > .Browser-image { 19 | background-position: -64px 0; 20 | } 21 | 22 | .Browser--firefox > .Browser-image { 23 | background-position: -128px 0; 24 | } 25 | 26 | .Browser--safari > .Browser-image { 27 | background-position: -192px 0; 28 | } 29 | 30 | .Browser--ie > .Browser-image { 31 | background-position: -256px 0; 32 | } 33 | 34 | .Browser--edge > .Browser-image { 35 | background-position: -320px 0; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /assets/css/components/button.css: -------------------------------------------------------------------------------- 1 | .Button { 2 | transition: background-color 0.2s; 3 | display: inline-block; 4 | padding: 0.6em 1em; 5 | background: hsla(31, 15%, 50%, 0.15); 6 | color: inherit; 7 | border: 0; 8 | border-radius: 2px; 9 | cursor: pointer; 10 | font-size: 0.8125em; 11 | font-weight: 300; 12 | line-height: normal; 13 | text-decoration: none; 14 | white-space: nowrap; 15 | } 16 | .Button:focus { 17 | outline: thin dotted #666; 18 | text-decoration: none; 19 | } 20 | .Button:active, 21 | .Button:focus, 22 | .Button:hover { 23 | border: 0; 24 | background: hsla(31, 15%, 50%, 0.25); 25 | text-decoration: none; 26 | } 27 | 28 | .Button--action { 29 | background-color: hsl(150, 45%, 50%); 30 | color: #fff; 31 | } 32 | .Button--action:active, 33 | .Button--action:focus, 34 | .Button--action:hover { 35 | background-color: hsl(150, 45%, 40%); 36 | } 37 | 38 | .Button--wide { 39 | padding-right: 1.5em; 40 | padding-left: 1.5em; 41 | } 42 | -------------------------------------------------------------------------------- /assets/css/components/container.css: -------------------------------------------------------------------------------- 1 | .Container { 2 | max-width: 50em; 3 | margin: 0 auto; 4 | } 5 | -------------------------------------------------------------------------------- /assets/css/components/demo.css: -------------------------------------------------------------------------------- 1 | .Demo { 2 | width: 100%; 3 | padding: .8em 1em 0; 4 | background: hsla(31, 15%, 50%, 0.1); 5 | border-radius: 3px; 6 | } 7 | .Demo::after { 8 | content: '\00a0'; /* */ 9 | display: block; 10 | margin-top: 1em; 11 | height: 0px; 12 | visibility: hidden; 13 | } 14 | 15 | .Demo--spaced { 16 | margin-bottom: var(--space); 17 | } 18 | -------------------------------------------------------------------------------- /assets/css/components/error.css: -------------------------------------------------------------------------------- 1 | .Error { 2 | padding: 1em 1.5em; 3 | background: #c00; 4 | color: #fff; 5 | font-weight: 700; 6 | text-align: center; 7 | } 8 | -------------------------------------------------------------------------------- /assets/css/components/feature.css: -------------------------------------------------------------------------------- 1 | .Feature { 2 | 3 | } 4 | 5 | .Feature-figure { 6 | margin-bottom: 0.75em; 7 | border: 1px solid hsl(0, 0%, 85%); 8 | transition: border-color 0.2s; 9 | } 10 | 11 | .Feature-image { 12 | display: block; 13 | max-width: 100%; 14 | height: auto; 15 | border: 5px solid hsl(0, 100%, 100%); 16 | } 17 | 18 | .Feature-title { 19 | margin: 0 0 0.5em; 20 | color: hsl(0, 0%, 25%); 21 | text-align: center; 22 | transition: color 0.1s; 23 | } 24 | 25 | .Feature-description { 26 | margin: 0 0.75em; 27 | font-size: 0.8em; 28 | } 29 | 30 | .Feature a:active .Feature-figure, 31 | .Feature a:focus .Feature-figure, 32 | .Feature a:hover .Feature-figure { 33 | border-color: hsl(150, 45%, 50%); 34 | } 35 | 36 | .Feature a:active .Feature-title, 37 | .Feature a:focus .Feature-title, 38 | .Feature a:hover .Feature-title { 39 | color: hsl(150, 45%, 50%); 40 | } 41 | -------------------------------------------------------------------------------- /assets/css/components/footer.css: -------------------------------------------------------------------------------- 1 | .Footer { 2 | padding: 1.5rem 1.5rem; 3 | background: gray(25%); 4 | color: gray(60%); 5 | font-size: 0.85em; 6 | overflow-x: hidden; 7 | text-align: center; 8 | } 9 | 10 | .Footer a { 11 | padding-bottom: 1px; 12 | border: 0; 13 | color: gray(90%); 14 | } 15 | .Footer a:focus, 16 | .Footer a:active, 17 | .Footer a:hover { 18 | color: #fff; 19 | text-decoration: underline; 20 | } 21 | 22 | .Footer-credits { 23 | margin: 0; 24 | padding: 0; 25 | } 26 | 27 | .Footer-credit { 28 | display: block; 29 | margin: 0; 30 | } 31 | 32 | .Footer-creditSeparator { 33 | display: none; 34 | } 35 | 36 | /* If loading the social button fails */ 37 | .Footer-social a, 38 | .Footer-social iframe { 39 | display: inline-block; 40 | margin: 0 0 1em; 41 | vertical-align: top; 42 | } 43 | 44 | @media (--break-md) { 45 | .Footer-credit { 46 | display: inline-block; 47 | margin: 0 0.25em; 48 | } 49 | .Footer-creditSeparator { 50 | display: inline-block; 51 | padding: 0 0.25em; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /assets/css/components/grid.css: -------------------------------------------------------------------------------- 1 | .Grid { 2 | display: flex; 3 | flex-wrap: wrap; 4 | list-style: none; 5 | margin: 0; 6 | padding: 0; 7 | } 8 | 9 | .Grid-cell { 10 | flex: 1; 11 | } 12 | 13 | .Grid--flexCells > .Grid-cell { 14 | display: flex; 15 | } 16 | 17 | .Grid--top { 18 | align-items: flex-start; 19 | } 20 | 21 | .Grid--bottom { 22 | align-items: flex-end; 23 | } 24 | 25 | .Grid--center { 26 | align-items: center; 27 | } 28 | 29 | .Grid--justifyCenter { 30 | justify-content: center; 31 | } 32 | 33 | .Grid-cell--top { 34 | align-self: flex-start; 35 | } 36 | 37 | .Grid-cell--bottom { 38 | align-self: flex-end; 39 | } 40 | 41 | .Grid-cell--center { 42 | align-self: center; 43 | } 44 | 45 | .Grid-cell--autoSize { 46 | flex: none; 47 | } 48 | 49 | .Grid--fit > .Grid-cell { 50 | flex: 1; 51 | } 52 | 53 | .Grid--full > .Grid-cell { 54 | flex: 0 0 100%; 55 | } 56 | 57 | .Grid--1of2 > .Grid-cell { 58 | flex: 0 0 50%; 59 | } 60 | 61 | .Grid--1of3 > .Grid-cell { 62 | flex: 0 0 33.3333%; 63 | } 64 | 65 | .Grid--1of4 > .Grid-cell { 66 | flex: 0 0 25%; 67 | } 68 | 69 | @media (--break-sm) { 70 | .small-Grid--fit > .Grid-cell { 71 | flex: 1; 72 | } 73 | .small-Grid--full > .Grid-cell { 74 | flex: 0 0 100%; 75 | } 76 | .small-Grid--1of2 > .Grid-cell { 77 | flex: 0 0 50%; 78 | } 79 | .small-Grid--1of3 > .Grid-cell { 80 | flex: 0 0 33.3333%; 81 | } 82 | .small-Grid--1of4 > .Grid-cell { 83 | flex: 0 0 25%; 84 | } 85 | } 86 | 87 | @media (--break-md) { 88 | .med-Grid--fit > .Grid-cell { 89 | flex: 1; 90 | } 91 | .med-Grid--full > .Grid-cell { 92 | flex: 0 0 100%; 93 | } 94 | .med-Grid--1of2 > .Grid-cell { 95 | flex: 0 0 50%; 96 | } 97 | .med-Grid--1of3 > .Grid-cell { 98 | flex: 0 0 33.3333%; 99 | } 100 | .med-Grid--1of4 > .Grid-cell { 101 | flex: 0 0 25%; 102 | } 103 | } 104 | 105 | @media (--break-lg) { 106 | .large-Grid--fit > .Grid-cell { 107 | flex: 1; 108 | } 109 | .large-Grid--full > .Grid-cell { 110 | flex: 0 0 100%; 111 | } 112 | .large-Grid--1of2 > .Grid-cell { 113 | flex: 0 0 50%; 114 | } 115 | .large-Grid--1of3 > .Grid-cell { 116 | flex: 0 0 33.3333%; 117 | } 118 | .large-Grid--1of4 > .Grid-cell { 119 | flex: 0 0 25%; 120 | } 121 | } 122 | 123 | .Grid--gutters { 124 | margin: -1em 0 1em -1em; 125 | } 126 | .Grid--gutters > .Grid-cell { 127 | padding: 1em 0 0 1em; 128 | } 129 | 130 | .Grid--guttersLg { 131 | margin: -1.5em 0 1.5em -1.5em; 132 | } 133 | .Grid--guttersLg > .Grid-cell { 134 | padding: 1.5em 0 0 1.5em; 135 | } 136 | 137 | .Grid--guttersXl { 138 | margin: -2em 0 2em -2em; 139 | } 140 | .Grid--guttersXl > .Grid-cell { 141 | padding: 2em 0 0 2em; 142 | } 143 | 144 | @media (--break-sm) { 145 | .small-Grid--gutters { 146 | margin: -1em 0 1em -1em; 147 | } 148 | .small-Grid--gutters > .Grid-cell { 149 | padding: 1em 0 0 1em; 150 | } 151 | .small-Grid--guttersLg { 152 | margin: -1.5em 0 1.5em -1.5em; 153 | } 154 | .small-Grid--guttersLg > .Grid-cell { 155 | padding: 1.5em 0 0 1.5em; 156 | } 157 | .small-Grid--guttersXl { 158 | margin: -2em 0 2em -2em; 159 | } 160 | .small-Grid--guttersXl > .Grid-cell { 161 | padding: 2em 0 0 2em; 162 | } 163 | } 164 | 165 | @media (--break-md) { 166 | .med-Grid--gutters { 167 | margin: -1em 0 1em -1em; 168 | } 169 | .med-Grid--gutters > .Grid-cell { 170 | padding: 1em 0 0 1em; 171 | } 172 | .med-Grid--guttersLg { 173 | margin: -1.5em 0 1.5em -1.5em; 174 | } 175 | .med-Grid--guttersLg > .Grid-cell { 176 | padding: 1.5em 0 0 1.5em; 177 | } 178 | .med-Grid--guttersXl { 179 | margin: -2em 0 2em -2em; 180 | } 181 | .med-Grid--guttersXl > .Grid-cell { 182 | padding: 2em 0 0 2em; 183 | } 184 | } 185 | 186 | @media (--break-lg) { 187 | .large-Grid--gutters { 188 | margin: -1em 0 1em -1em; 189 | } 190 | .large-Grid--gutters > .Grid-cell { 191 | padding: 1em 0 0 1em; 192 | } 193 | .large-Grid--guttersLg { 194 | margin: -1.5em 0 1.5em -1.5em; 195 | } 196 | .large-Grid--guttersLg > .Grid-cell { 197 | padding: 1.5em 0 0 1.5em; 198 | } 199 | .large-Grid--guttersXl { 200 | margin: -2em 0 2em -2em; 201 | } 202 | .large-Grid--guttersXl > .Grid-cell { 203 | padding: 2em 0 0 2em; 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /assets/css/components/header.css: -------------------------------------------------------------------------------- 1 | .Header { 2 | padding: 1.5em; 3 | background-color: rgba(147, 128, 108, 0.1); 4 | text-align: center; 5 | } 6 | @media (--break-lg) { 7 | .Header { 8 | padding: 3em 1.5em; 9 | } 10 | } 11 | 12 | .Header-title { 13 | margin: 0 0 0.15em; 14 | font-size: 1.8em; 15 | font-weight: 600; 16 | line-height: 1; 17 | word-spacing: 0.08em; 18 | } 19 | .Header-title i { 20 | font-family: serif; 21 | font-style: italic; 22 | font-weight: 400; 23 | } 24 | .Header-title a { 25 | border: 0; 26 | color: inherit; 27 | font-weight: inherit; 28 | } 29 | .Header-title a:focus, .Header-title a:hover, .Header-title a:active { 30 | text-decoration: none; 31 | } 32 | @media (--break-lg) { 33 | .Header-title { 34 | font-size: 4em; 35 | } 36 | } 37 | 38 | .Header-subTitle { 39 | margin: 0 0 1.5em; 40 | font-size: 0.8em; 41 | font-weight: 300; 42 | white-space: nowrap; 43 | } 44 | @media (--break-lg) { 45 | .Header-subTitle { 46 | margin: 1em 0 1.75em; 47 | font-size: 1.1em; 48 | } 49 | } 50 | 51 | .Header-actions { 52 | display: flex; 53 | align-items: stretch; 54 | flex-direction: column; 55 | font-size: 0.9em; 56 | } 57 | @media (--break-sm) { 58 | .Header-actions { 59 | align-items: center; 60 | flex-direction: row; 61 | justify-content: center; 62 | } 63 | } 64 | @media (--break-lg) { 65 | .Header-actions { 66 | font-size: 1.1em; 67 | } 68 | } 69 | 70 | .Header-button:first-child { 71 | margin: 0 0 1em; 72 | } 73 | @media (--break-sm) { 74 | .Header-button:first-child { 75 | margin: 0 1em 0 0; 76 | } 77 | } 78 | 79 | @media (--break-lg) { 80 | .Header--cozy { 81 | display: flex; 82 | padding: 1.5em; 83 | align-items: center; 84 | } 85 | .Header--cozy .Header-titles { 86 | display: flex; 87 | align-items: baseline; 88 | } 89 | .Header--cozy .Header-title { 90 | font-size: 1.5em; 91 | } 92 | .Header--cozy .Header-subTitle { 93 | margin: 0 0 0 1em; 94 | font-size: 0.8em; 95 | font-weight: 300; 96 | color: gray; 97 | } 98 | .Header--cozy .Header-actions { 99 | flex: 1; 100 | justify-content: flex-end; 101 | font-size: 0.9em; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /assets/css/components/holy-grail.css: -------------------------------------------------------------------------------- 1 | /** 2 | * 1. Avoid the IE 10-11 `min-height` bug. 3 | * 2. Set `flex-shrink` to `0` to prevent some browsers from 4 | * letting these items shrink to smaller than their content's default 5 | * minimum size. See http://bit.ly/1Mn35US for details. 6 | * 3. Use `%` instead of `vh` since `vh` is buggy in older mobile Safari. 7 | */ 8 | 9 | .HolyGrail { 10 | display: flex; 11 | height: 100%; /* 1, 3 */ 12 | flex-direction: column; 13 | } 14 | 15 | .HolyGrail-header, 16 | .HolyGrail-footer { 17 | flex: none; /* 2 */ 18 | } 19 | 20 | .HolyGrail-body { 21 | display: flex; 22 | flex: 1 0 auto; /* 2 */ 23 | flex-direction: column; 24 | padding: var(--space); 25 | } 26 | 27 | .HolyGrail-content { 28 | margin-top: var(--space); 29 | } 30 | 31 | .HolyGrail-nav { 32 | order: -1; 33 | } 34 | 35 | .HolyGrail-nav, 36 | .HolyGrail-ads { 37 | padding: 1em; 38 | border-radius: 3px; 39 | background: rgba(147, 128, 108, 0.1); 40 | } 41 | 42 | @media (--break-lg) { 43 | .HolyGrail-body { 44 | flex-direction: row; 45 | } 46 | .HolyGrail-content { 47 | flex: 1; 48 | padding: 0 var(--space-lg); 49 | margin: 0; 50 | } 51 | .HolyGrail-nav, .HolyGrail-ads { 52 | flex: 0 0 12em; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /assets/css/components/image.css: -------------------------------------------------------------------------------- 1 | .Image { 2 | display: block; 3 | width: 40px; 4 | height: auto; 5 | margin-top: 0.2em; 6 | } 7 | 8 | .Image--tiny { 9 | width: 30px; 10 | } 11 | 12 | @media (--break-md) { 13 | .Image { 14 | width: 70px; 15 | } 16 | .Image--tiny { 17 | width: 40px; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /assets/css/components/input-add-on.css: -------------------------------------------------------------------------------- 1 | .InputAddOn { 2 | display: flex; 3 | margin-bottom: 1.5em; 4 | } 5 | 6 | .InputAddOn-field { 7 | flex: 1; 8 | } 9 | .InputAddOn-field:not(:first-child) { 10 | border-left: 0; 11 | } 12 | .InputAddOn-field:not(:last-child) { 13 | border-right: 0; 14 | } 15 | 16 | .InputAddOn-item { 17 | background-color: rgba(147, 128, 108, 0.1); 18 | color: #666666; 19 | font: inherit; 20 | font-weight: normal; 21 | } 22 | 23 | .InputAddOn-field, 24 | .InputAddOn-item { 25 | border: 1px solid rgba(147, 128, 108, 0.25); 26 | padding: 0.5em 0.75em; 27 | } 28 | .InputAddOn-field:first-child, 29 | .InputAddOn-item:first-child { 30 | border-radius: 2px 0 0 2px; 31 | } 32 | .InputAddOn-field:last-child, 33 | .InputAddOn-item:last-child { 34 | border-radius: 0 2px 2px 0; 35 | } 36 | -------------------------------------------------------------------------------- /assets/css/components/media.css: -------------------------------------------------------------------------------- 1 | .Media { 2 | display: flex; 3 | align-items: flex-start; 4 | margin-bottom: 1em; 5 | } 6 | 7 | .Media-figure { 8 | margin-right: 1em; 9 | } 10 | 11 | .Media-body { 12 | flex: 1; 13 | } 14 | .Media-body, 15 | .Media-body :last-child { 16 | margin-bottom: 0; 17 | } 18 | 19 | .Media-title { 20 | margin: 0 0 .5em; 21 | } 22 | 23 | .Media--center { 24 | align-items: center; 25 | } 26 | 27 | .Media--reverse > .Media-figure { 28 | order: 1; 29 | margin: 0 0 0 1em; 30 | } 31 | -------------------------------------------------------------------------------- /assets/css/components/notice.css: -------------------------------------------------------------------------------- 1 | .Notice { 2 | background-color: hsl(90, 100%, 93%); 3 | color: hsla(0, 0%, 0%, .6); 4 | font-size: .9em; 5 | margin-bottom: var(--space); 6 | padding: 1.2em 1.5em; 7 | } 8 | -------------------------------------------------------------------------------- /assets/css/components/section.css: -------------------------------------------------------------------------------- 1 | .Section { 2 | padding: 0 var(--space); 3 | } 4 | .Section:nth-child(2n) { 5 | background-color: hsla(31, 15%, 50%, 0.1); 6 | overflow: hidden; /* Contain margins. */ 7 | } 8 | .Section::before, 9 | .Section::after { 10 | content: '\00a0'; /* */ 11 | display: block; 12 | height: 0px; 13 | visibility: hidden; 14 | } 15 | .Section::before { 16 | margin-bottom: var(--space); 17 | } 18 | .Section::after { 19 | margin-top: var(--space); 20 | } 21 | @media (--break-lg) { 22 | .Section { 23 | padding: 0 var(--space-lg); 24 | } 25 | .Section::before { 26 | margin-bottom: var(--space-lg); 27 | } 28 | .Section::after { 29 | margin-top: var(--space-lg); 30 | } 31 | } 32 | 33 | .Section-heading { 34 | text-align: center; 35 | } 36 | 37 | @media (--break-lg) { 38 | .Section-list { 39 | padding: 0; 40 | margin: 0 calc(2 * var(--space-lg)) var(--space-lg); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /assets/css/components/site.css: -------------------------------------------------------------------------------- 1 | /** 2 | * 1. Avoid the IE 10-11 `min-height` bug. 3 | * 2. Set `flex-shrink` to `0` to prevent some browsers from 4 | * letting these items shrink to smaller than their content's default 5 | * minimum size. See http://bit.ly/1Mn35US for details. 6 | * 3. Use `%` instead of `vh` since `vh` is buggy in older mobile Safari. 7 | */ 8 | 9 | .Site { 10 | display: flex; 11 | flex-direction: column; 12 | height: 100%; /* 1, 3 */ 13 | } 14 | 15 | .Site-header, 16 | .Site-footer { 17 | flex: none; /* 2 */ 18 | } 19 | 20 | .Site-content { 21 | flex: 1 0 auto; /* 2 */ 22 | padding: var(--space) var(--space) 0; 23 | width: 100%; 24 | } 25 | .Site-content::after { 26 | content: '\00a0'; /* */ 27 | display: block; 28 | margin-top: var(--space); 29 | height: 0px; 30 | visibility: hidden; 31 | } 32 | @media (--break-lg) { 33 | .Site-content { 34 | padding-top: var(--space-lg); 35 | } 36 | .Site-content::after { 37 | margin-top: var(--space-lg); 38 | } 39 | } 40 | 41 | .Site-content--full { 42 | padding: 0; 43 | } 44 | .Site-content--full::after { 45 | content: none; 46 | } 47 | -------------------------------------------------------------------------------- /assets/css/main.css: -------------------------------------------------------------------------------- 1 | @import 'normalize.css'; 2 | @import 'suitcss-utils-display'; 3 | @import 'suitcss-utils-text'; 4 | 5 | @import './base/variables'; 6 | @import './base/custom-media'; 7 | @import './base/elements'; 8 | 9 | @import './components/aligner'; 10 | @import './components/browser'; 11 | @import './components/button'; 12 | @import './components/container'; 13 | @import './components/demo'; 14 | @import './components/error'; 15 | @import './components/feature'; 16 | @import './components/footer'; 17 | @import './components/grid'; 18 | @import './components/header'; 19 | @import './components/holy-grail'; 20 | @import './components/image'; 21 | @import './components/input-add-on'; 22 | @import './components/media'; 23 | @import './components/notice'; 24 | @import './components/section'; 25 | @import './components/site'; 26 | 27 | @import './utils/compat'; 28 | @import './utils/media'; 29 | @import './utils/size'; 30 | 31 | @import './vendor/font-awesome-extensions'; 32 | @import './vendor/highlight'; 33 | @import './vendor/twitter'; 34 | -------------------------------------------------------------------------------- /assets/css/utils/compat.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Fixes the min-height bug in IE10-11. 3 | * This class should be added to a container element as described in 4 | * Flexbug #3. See http://bit.ly/1gy8OJS for details. 5 | */ 6 | .u-ieMinHeightBugFix { 7 | display: flex; 8 | flex-direction: column; 9 | } 10 | -------------------------------------------------------------------------------- /assets/css/utils/media.css: -------------------------------------------------------------------------------- 1 | @import '../base/custom-media'; 2 | 3 | .u-full { 4 | width: 100% !important; 5 | flex: none !important; 6 | } 7 | 8 | .u-1of2 { 9 | width: 50% !important; 10 | flex: none !important; 11 | } 12 | 13 | .u-1of3 { 14 | width: 33.3333% !important; 15 | flex: none !important; 16 | } 17 | 18 | .u-2of3 { 19 | width: 66.6667% !important; 20 | flex: none !important; 21 | } 22 | 23 | .u-1of4 { 24 | width: 25% !important; 25 | flex: none !important; 26 | } 27 | 28 | .u-3of4 { 29 | width: 75% !important; 30 | flex: none !important; 31 | } 32 | 33 | @media (--break-sm) { 34 | .u-small-full { 35 | width: 100% !important; 36 | flex: none !important; 37 | } 38 | .u-small-1of2 { 39 | width: 50% !important; 40 | flex: none !important; 41 | } 42 | .u-small-1of3 { 43 | width: 33.3333% !important; 44 | flex: none !important; 45 | } 46 | .u-small-2of3 { 47 | width: 66.6667% !important; 48 | flex: none !important; 49 | } 50 | .u-small-1of4 { 51 | width: 25% !important; 52 | flex: none !important; 53 | } 54 | .u-small-3of4 { 55 | width: 75% !important; 56 | flex: none !important; 57 | } 58 | } 59 | 60 | @media (--break-md) { 61 | .u-med-full { 62 | width: 100% !important; 63 | flex: none !important; 64 | } 65 | .u-med-1of2 { 66 | width: 50% !important; 67 | flex: none !important; 68 | } 69 | .u-med-1of3 { 70 | width: 33.3333% !important; 71 | flex: none !important; 72 | } 73 | .u-med-2of3 { 74 | width: 66.6667% !important; 75 | flex: none !important; 76 | } 77 | .u-med-1of4 { 78 | width: 25% !important; 79 | flex: none !important; 80 | } 81 | .u-med-3of4 { 82 | width: 75% !important; 83 | flex: none !important; 84 | } 85 | } 86 | 87 | @media (--break-lg) { 88 | .u-large-full { 89 | width: 100% !important; 90 | flex: none !important; 91 | } 92 | .u-large-1of2 { 93 | width: 50% !important; 94 | flex: none !important; 95 | } 96 | .u-large-1of3 { 97 | width: 33.3333% !important; 98 | flex: none !important; 99 | } 100 | .u-large-2of3 { 101 | width: 66.6667% !important; 102 | flex: none !important; 103 | } 104 | .u-large-1of4 { 105 | width: 25% !important; 106 | flex: none !important; 107 | } 108 | .u-large-3of4 { 109 | width: 75% !important; 110 | flex: none !important; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /assets/css/utils/size.css: -------------------------------------------------------------------------------- 1 | .u-smaller { 2 | font-size: 0.85em; 3 | } 4 | 5 | .u-bigger { 6 | font-size: 1.2em; 7 | } 8 | -------------------------------------------------------------------------------- /assets/css/vendor/font-awesome-extensions.css: -------------------------------------------------------------------------------- 1 | .icon-big { 2 | font-size: 1.5em; 3 | } 4 | -------------------------------------------------------------------------------- /assets/css/vendor/highlight.css: -------------------------------------------------------------------------------- 1 | @import "highlight.js/styles/github"; 2 | 3 | pre { 4 | border-radius: 3px; 5 | background: hsla(31, 15%, 50%, 0.1); 6 | font-size: 0.85em; 7 | margin-bottom: calc(var(--space)/0.85); 8 | overflow-x: auto; 9 | padding: 1.25em 1.5em; 10 | } 11 | -------------------------------------------------------------------------------- /assets/css/vendor/twitter.css: -------------------------------------------------------------------------------- 1 | .twitter-follow-button { 2 | width: 230px !important; 3 | } 4 | 5 | .twitter-color { 6 | color: #00ACED; 7 | } 8 | -------------------------------------------------------------------------------- /assets/images/browser-logos.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magic-akari/solved-by-flexbox/33c8e269e31ba31be2e1ad35f0e86cb7513013e8/assets/images/browser-logos.jpg -------------------------------------------------------------------------------- /assets/images/grids.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magic-akari/solved-by-flexbox/33c8e269e31ba31be2e1ad35f0e86cb7513013e8/assets/images/grids.jpg -------------------------------------------------------------------------------- /assets/images/holy-grail.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magic-akari/solved-by-flexbox/33c8e269e31ba31be2e1ad35f0e86cb7513013e8/assets/images/holy-grail.jpg -------------------------------------------------------------------------------- /assets/images/input-add-ons.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magic-akari/solved-by-flexbox/33c8e269e31ba31be2e1ad35f0e86cb7513013e8/assets/images/input-add-ons.jpg -------------------------------------------------------------------------------- /assets/images/kitten.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magic-akari/solved-by-flexbox/33c8e269e31ba31be2e1ad35f0e86cb7513013e8/assets/images/kitten.jpg -------------------------------------------------------------------------------- /assets/images/media-object.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magic-akari/solved-by-flexbox/33c8e269e31ba31be2e1ad35f0e86cb7513013e8/assets/images/media-object.jpg -------------------------------------------------------------------------------- /assets/images/sticky-footer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magic-akari/solved-by-flexbox/33c8e269e31ba31be2e1ad35f0e86cb7513013e8/assets/images/sticky-footer.jpg -------------------------------------------------------------------------------- /assets/images/vertical-centering.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magic-akari/solved-by-flexbox/33c8e269e31ba31be2e1ad35f0e86cb7513013e8/assets/images/vertical-centering.jpg -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Solved by Flexbox", 3 | "tagline": "更干净,无奇技淫巧的 CSS", 4 | "description": "A showcase of problems once hard or impossible to solve with CSS alone, now made trivially easy with Flexbox." 5 | } 6 | -------------------------------------------------------------------------------- /demos/grids.md: -------------------------------------------------------------------------------- 1 | --- 2 | template: default.html 3 | title: 更棒,更简洁的栅格系统 4 | excerpt: Flexbox 满足了我们大部分对于栅格系统的需求。尺寸、对齐仅用一两个属性就能搞定。 5 | --- 6 | 7 | 现今大部分栅格系统都使用了两种布局方式中的一种:浮动 (`float`) 或者 內联块 (`inline-block`)。但是它们的初衷均不是真的用于布局 (layout),也因此导致了诸多的问题和限制。 8 | 9 | 10 | 11 | 使用浮动 (float) 需要清除浮动,因此牵连出了一堆布局问题,最臭名昭著的是清除一个元素的浮动有时会强制它出现在一个不相关的页面部分的下边 (例如 [Bootstrap issue](https://github.com/twbs/bootstrap/issues/295#issuecomment-2282969) )。并且,使用清除浮动通常会同时使用 before 和 after 两个伪元素,导致你不能将该伪元素使用于其他用途。 12 | 13 | 14 | 15 | 内联块布局最著名的问题是 [内联块之间空白问题](http://css-tricks.com/fighting-the-space-between-inline-block-elements/), 以及其所有 [解决方案](http://davidwalsh.name/remove-whitespace-inline-block) 都是 [奇技淫巧](https://github.com/suitcss/components-grid/blob/master/lib/grid.css#L30) 和 [恼人](https://twitter.com/thierrykoblentz/status/305152267374428160) 的。 16 | 17 | 18 | 19 | Flexbox 布局不仅结局了这些问题,还开启全新可能性的新世界的大门。 20 | 21 | 22 | 23 | ## Flexbox 栅格系统特性 24 | 25 | 26 | 27 | 栅格系统通常有数不清的尺寸选项,但是通常情况你仅仅想要一个两栏或三栏的栅格系统。既然如此,我们为什么一定要把尺寸属性 (sizing classes) 写到每一个格子 (cell) 里? 28 | 29 | 30 | 31 | 下列是我对于一个理想的栅格系统的标准。幸运的是,Flexbox 布局满足了大部分特性。 32 | 33 | 34 | 35 | - 每一行里的每一个栅格默认都是等宽等高。默认自适应。 36 | - 为了足够灵活,能够添加尺寸属性到单独的栅格中。没有添加的,仍然简单地平分剩下的可用空间。 37 | - 支持响应式布局,可以添加媒体查询到栅格中。 38 | - 每一个栅格可以在垂直方向上置顶,置底,居中。 39 | - 如果让所有栅格拥有一致的大小和对齐方式,在容器上添加属性,子元素能够继承,而不需要无意义的重复。 40 | - 栅格能够任意的嵌套。 41 | 42 | 48 | 49 | ### 基础栅格系统 50 | 51 | 52 | 53 | 下面的栅格没有指定特定的宽度,它们自然的平分每一行的空间并撑满每一个行,并且高度默认都是相等的。 54 | 55 | 56 | 57 |
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ac nisl quis massa vulputate adipiscing. Vivamus sit amet risus ligula. Nunc eu pulvinar augue.
35 |Donec imperdiet sem leo, id rutrum risus aliquam vitae. Cras tincidunt porta mauris, vel feugiat mauris accumsan eget.
44 |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.
55 |Donec imperdiet sem leo, id rutrum risus aliquam vitae. Vestibulum ac turpis non lacus dignissim dignissim eu sed dui.
73 |Nunc nec fermentum dolor. Duis at iaculis turpis. Sed rutrum elit ac egestas dapibus. Duis nec consequat enim.
84 |Phasellus vel felis purus. Aliquam consequat pellentesque dui, non mollis erat dictum sit amet. Curabitur non quam dictum, consectetur arcu in, vehicula justo.
102 |108 | Mauris porta arcu id magna adipiscing lacinia at congue lacus. Vivamus blandit quam quis tincidunt egestas. Etiam posuere lectus sed sapien malesuada molestie. 109 |
110 |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.
119 |Rutrum risus aliquam vitae.
122 |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.
138 |Donec imperdiet sem leo, id rutrum risus aliquam vitae.
141 |148 | 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. 149 |
150 |…
166 |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.
29 |CSS 长期以来缺乏合适的布局机制。 变形,动画,滤镜,对这门语言来说都很有用,但是都没有解决 Web 开发者长期抱怨的主要问题。
9 | 10 |终于,多亏了 Flexbox 布局,我们有了解决方案。
11 | 12 |这个页面并不是另一个 CSS 框架。主要目的是展示曾经很困难甚至无法单独用 CSS 解决的问题,现在被 Flexbox 布局轻松解决。随着最近释出的 Internet Explorer 11 和 Safari 6.1,最新的 Flexbox 语法已经被每一个的现代浏览器支持。
13 | 14 |检查下边的 demo 。查看浏览器的网页审查工具或者深入 源代码 查看,一旦 Flexbox 成为主流,CSS 布局代码将会变得多么的简单。
15 | 16 |{{ demo.excerpt }}
33 |display:flexbox
)。display:box
)。该页面的所有关于 Flexbox 解决特定问题的示例。都没有被设计用来解决浏览器的兼容性。一些浏览器不完全支持 Flexbox 布局的最新语法,所以,很遗憾,一些兼容性工作是需要的。
101 | 102 |兼容性工作的代码没有展示在示例中,但是如果你好奇实现的细节,你可以查看源代码。每一个 demo 都有指向其源代码的链接,里边有完整的兼容性代码,以及文档注释,所以不用担心,去看一看吧。
103 | 104 |Flexbox 布局自动化兼容性工具由 autoprefixer 提供。如果你没使用 autoprefixer 来写 Flexbox 代码,那么,你可能会犯一些可怕的错误。
105 | 106 |在示例代码和源文件中使用的类名来自于 SUIT CSS,基于 BEM 方法。每个示例包含的可重用的 CSS 组件允许你复制修改适应你自己的项目。每个示例页面提供了各自组件的链接。
107 | 108 |如果你发现了错误或者想提供一些额外的示例,欢迎在 Github 上开一个 issue 或者提交一个 pull request。
109 | 110 |以下翻译由社区热心提供:
117 | 118 | 123 |请注意,翻译并非官方提供,可能随着时间推移而过时。你可以在 Github 上发送一个 pull request 或者 开一个 issue 提供你的翻译内容的链接。
124 | 125 |该文档基于 Solved by Flexbox 原始英文版本的 CC-BY 授权协议,由 阿卡琳 独自翻译。
131 |欢迎任何关于翻译或其建议。请在 Github 上给我发送 pull request 或者 开一个 issue
132 |