不久以前,所有 html 页面的布局还都是通过 tables、floats 以及其他的 CSS 属性来完成的。面对复杂页面的布局,却没有很好的办法。
然而 Flexbox 的出现,便轻松的解决了复杂的 web 布局。它是一种专注于创建稳定的响应式页面的布局模式,并可以轻松地正确对齐元素及其内容。如今已是大多数 Web 开发人员首选的 CSS 布局方式。
现在,又出现了一个构建 HTML 最佳布局体系的新竞争者。(霸主地位正在争夺中…)它就是强大的 CSS Grid 布局。直到本月月底,它也将在 Firefox 52 和 Chrome 57 上得到原生支持,相信不久也会得到其他浏览器兼容性的支持。
要了解这两个体系构建布局的方式,我们将通过相同的 HTML 页面,利用不同的布局方式 (即 Flexbox 与 CSS Grid)为大家区分。同时,你也可以通过文章顶部附近的下载按钮,下载演示项目进行对比,或者通过在线演示来察看它们:
demo 地址: https://demo.tutorialzine.com/2017/03/css-grid-vs-flexbox/
该页面的设计相对比较简单 – 它是由一个居中的容器组成,在其内部则包含了标头、主要内容部分、侧边栏和页脚。接下来,我们要完成同时保持 CSS 和 HTML 尽可能整洁的挑战事项:
如你所见,为了便于比较,我们将所有事项从简处理。那么,让我们从第一个挑战事项开始吧!
我们将从 Flexbox 解决方案开始。我们将为容器添加 display: flex 来指定为 Flex 布局,并指定子元素的垂直方向。
- .container {
- display: flex;
- flex - direction: column;
- }
现在我们需要使主要内容部分和侧边栏彼此相邻。由于 Flex 容器通常是单向的,所以我们需要添加一个包装器元素。
- <header></header>
- <div class="main-and-sidebar-wrapper">
- <section class="main"></section>
- <aside class="sidebar"></aside>
- </div>
- <footer></footer>
然后,我们给包装器在反向添加 display: flex 和 flex-direction 属性。
- .main - and - sidebar - wrapper {
- display: flex;
- flex - direction: row;
- }
最后一步,我们将设置主要内容部分与侧边栏的大小。通过 Flex 实现后,主要内容部分会比侧边栏大三倍。
- .main {
- flex: 3;
- margin-right: 60px;
- }
- .sidebar {
- flex: 1;
- }
如你所见,Flex 将其很好的实现了出来,但是仍需要相当多的 CSS 属性,并借助了额外的 HTML 元素。那么,让我们看看 CSS Grid 如何实现的。
针对本项目,有几种不同的 CSS Grid 解决方法,但是我们将使用网格模板区域语法来实现,因为它似乎最适合我们要完成的工作。
首先,我们将定义四个网格区域,所有的页面各一个:
- <header></header>
- <!-- Notice there isn't a wrapper this time -->
- <section class="main"></section>
- <aside class="sidebar"></aside>
- <footer></footer>
- header {
- grid-area: header;
- }
- .main {
- grid-area: main;
- }
- .sidebar {
- grid-area: sidebar;
- }
- footer {
- grid-area: footer;
- }
然后,我们会设置网格并分配每个区域的位置。初次接触 Grid 布局的朋友,可能感觉以下的代码会有些复杂,但当你了解了网格体系,就很容易掌握了。
- .container {
- display: grid;
- /* Define the size and number of columns in our grid.
- The fr unit works similar to flex:
- fr columns will share the free space in the row in proportion to their value.
- We will have 2 columns - the first will be 3x the size of the second. */
- grid-template-columns: 3fr 1fr;
- /* Assign the grid areas we did earlier to specific places on the grid.
- First row is all header.
- Second row is shared between main and sidebar.
- Last row is all footer. */
- grid-template-areas:
- "header header"
- "main sidebar"
- "footer footer";
- /* The gutters between each grid cell will be 60 pixels. */
- grid-gap: 60px;
- }
就是这样! 我们现在将遵循上述结构进行布局,甚至不需要我们处理任何的 margins 或 paddings 。
这一步的执行与上一步密切相关。对于 Flexbox 解决方案,我们将更改包装器的 flex-direction 属性,并调整一些 margins。
- @media (max-width: 600px) {
- .main-and-sidebar-wrapper {
- flex-direction: column;
- }
- .main {
- margin-right: 0;
- margin-bottom: 60px;
- }
- }
由于网页比较简单,所以我们在媒体查询上不需要太多的重写。但是,如果遇见更为复杂的布局,那么将会重新的定义相当多的内容。
由于我们已经定义了网格区域,所以我们只需要在媒体查询中重新排序它们。 我们可以使用相同的列设置。
- @media (max-width: 600px) {
- .container {
- /* Realign the grid areas for a mobile layout. */
- grid-template-areas:
- "header header"
- "main main"
- "sidebar sidebar"
- "footer footer";
- }
- }
或者,我们可以从头开始重新定义整个布局。
- @media (max-width: 600px) {
- .container {
- /* Redefine the grid into a single column layout. */
- grid-template-columns: 1fr;
- grid-template-areas:
- "header"
- "main"
- "sidebar"
- "footer";
- }
- }
我们的标头包含了导航和一个按钮的相关链接。我们希望导航朝左对齐,按钮向右对齐。而导航中的链接务必正确对齐,且彼此相邻。
- <header>
- <nav>
- <li><a href="#"><h1>Logo</h1></a></li>
- <li><a href="#">Link</a></li>
- <li><a href="#">Link</a></li>
- </nav>
- <button>Button</button>
- </header>
我们曾在一篇较早的文章中使用 Flexbox 做了类似的布局:响应式标头最简单的制作方法。这个技术很简单:
- header {
- display: flex;
- justify - content: space - between;
- }
现在导航列表和按钮已正确对齐。下来我们将使
来源: http://www.css88.com/archives/8642