by Cameron Jenkinson
卡梅伦·詹金森(Cameron Jenkinson)
通过重新创建熟悉的布局来学习CSS网格:Airbnb,Youtube等 (Learn CSS Grid by recreating familiar layouts: Airbnb, Youtube and more)
I learn best by example and I’m guessing you have arrived here because you do as well. I’ve found learning the features of CSS Grid much easier by re-creating the layouts of products and websites I’m familiar with.
我以身作则,学得最好,我猜你也来这里是因为你也这样做。 通过重新创建我熟悉的产品和网站的布局,我发现学习CSS Grid的功能要容易得多。
For each layout I’ve used a single main view as the basis for understanding how it would be constructed using the CSS Grid.
对于每种布局,我都使用一个主视图作为基础,以了解如何使用CSS Grid构造它。
As a note: I’ve omitted most of the intricate details on how the layout is handled (animations, data, etc.) so that the focus is on exploring the layout and how grid features work. So, please bear in mind that the layouts may not behave exactly as they do officially.
注意:我省略了有关如何处理布局的大多数复杂细节(动画,数据等),因此重点放在探索布局以及网格功能如何工作上。 因此,请记住,布局的行为可能与正式布局不完全相同。
My aim is for this article is to serve as a reference point and a guide to bootstrapping similar layouts with relatively little code (which is why CSS Grid is good at what it does).
我的目的是作为本文的参考点和指南,以较少的代码引导相似的布局(这就是CSS Grid擅长于其功能的原因)。
I plan to add additional layouts to this post overtime.
我计划在此职位上加班。
Last updated: 11th of December 2017
上次更新: 2017年12月11日
Current layouts:
当前布局:
- Airbnb home page Airbnb主页
- YouTube home page YouTube首页
- Pinterest home view Pinterest主视图
Coming up:
接下来:
- Soundcloud 声云
- Bloomberg 彭博社
- Huffington Post 赫芬顿邮报
CSS网格 (CSS Grids)
What is the CSS Grid?
什么是CSS网格?
CSS Grid Layout excels at dividing a page into major regions, or defining the relationship in terms of size, position, and layer, between parts of a control built from HTML primitives.
CSS Grid Layout 擅长将页面划分为主要区域,或根据HTML原语构建的控件各部分之间在大小,位置和层方面定义关系。
Like tables, grid layout enables an author to align elements into columns and rows. However, many more layouts are either possible or easier with CSS Grid than they were with tables. For example, a grid container’s child elements could position themselves so they actually overlap and layer, similar to CSS positioned elements. — MDN
像表格一样,网格布局使作者能够将元素对齐到列和行中。 但是,与表格相比,CSS Grid可以实现更多的布局,也可以使布局更容易。 例如,网格容器的子元素可以定位自己,以便它们实际上重叠并分层,类似于CSS定位的元素。 — MDN
In short, CSS Grid provides a set of layout controls and tools that existing implementations of column and row based layouts created from using widths and float properties.
简而言之,CSS Grid提供了一组布局控件和工具,可以通过使用width和float属性创建基于列和行的布局的现有实现。
CSS Grid is also more than this. It can dynamically update properties based on rules you define (such as: “when the browser is this width, do this”). Hence, I believe it is the future of front-end layout approaches.
CSS Grid不仅限于此。 它可以根据您定义的规则动态更新属性(例如:“当浏览器达到此宽度时,请执行此操作” ) 。 因此,我相信这是前端布局方法的未来。
For those new to the concept of a grid itself: a grid is a set of lines (think of it like an old math working book) where it has horizontal and vertical lines that enable placement of elements to be defined.
对于那些不熟悉网格本身的概念的人来说:网格是一组线(就像旧的数学工作手册一样 ),其中有水平和垂直线,可以定义元素的位置。
网格术语: (Grid terminology:)
网格容器 (Grid Container)
The grid container is the parent that will hold all of the items placed on the grid. It defines the initial state of the grid lines (vertical and horizontal).
网格容器是父容器,它将保存放置在网格上的所有项目。 它定义了网格线的初始状态(垂直和水平)。
To create a CSS Grid, you simply add display: grid;
to the wrapper or container that you’re working with in your document.
要创建CSS网格,只需添加display: grid;
到您在文档中使用的包装器或容器。
网格项 (Grid Item)
All of the children of the grid container are referenced as grid item
.
网格容器的所有子代均被称为网格item
。
网格线 (Grid Line)
The grid lines represent the vertical columns (column grid lines) and horizontal (row grid lines).
网格线代表垂直列(列网格线)和水平(行网格线)。
There are two properties grid-template-columns
and grid-template-rows
that are used to define the grid lines of the layout.
有两个属性grid-template-columns
和grid-template-rows
用于定义布局的网格线。
grid-template-columns
defines the column placement and grid-template-rows
defines the row placement.
grid-template-columns
定义列位置, grid-template-rows
定义行位置。
网格单元 (Grid Cell)
This is the smallest area within the grid layout which is the space defined by four grid lines.
这是网格布局中的最小区域,该区域是由四个网格线定义的空间。
网格面积 (Grid Area)
A grid area is a specific named container area that holds grid cells defined by grid lines.
网格区域是一个特定的命名容器区域,其中包含由网格线定义的网格单元。
通过示例学习CSS网格 (Learning CSS Grid through example)
1.爱彼迎 (1. Airbnb)
文件格式: (Document Layout:)
<div class="wrapper"> <header class="header">Airbnb</header> <article class="content"> <div class="panel"> <img src="#" /> <span>Home name</span> </div> <!-- Rest of the home items ... --> </article> <aside class="sidebar">Sidebar - Map</aside> </div>
主电网: (Main Grid:)
.wrapper { margin: 0 auto; display: grid; grid-template-columns: 65% 35%; grid-gap: 16px;}
The wrapper
class defines the grid container, the one that holds the core document blocks (article
which is the area that the home items are contained, aside
which is the sidebar map).
wrapper
类定义了一个网格容器,该网格容器用于存放核心文档块( article
是包含主页项的区域, aside
是侧边栏图)。
After the display: grid
property has been set the layout has been actually defined as a grid where we can use the grid-template-columns
to declare track-size
of the columns using percentages.
在设置了display: grid
属性后,实际上已将布局定义为一个网格,在这里我们可以使用grid-template-columns
来使用百分比声明grid-template-columns
track-size
。
The track-size
can be a length, a percentage, or a fraction of the free space in the grid (using the fr
unit).
track-size
可以是网格中可用空间的长度,百分比或分数(使用fr
单位)。
.content { padding: 8px; display: grid; margin: 0 auto; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)) ; grid-auto-rows: minmax(264px, auto); grid-gap: 16px;}
The main grid contains a secondary container (a sub grid) with a class-name of .content
. This represents the area of article element which holds all of the home items.
主网格包含一个二级容器(一个子网格),其类名称为.content
。 这代表了包含所有首页项目的article元素区域。
The sub-grid is defined with both columns as well as rows so that all of the items can be sized to fit.
子网格既定义有列又定义了行,以便可以调整所有项目的大小以适合它们。
There are a few new things being used here so let’s break each of them down.
这里使用了一些新事物,所以让我们逐一分解。
When defining the columns we used repeat(auto-fill, minmax(300px, 1fr));
as:
在定义列时,我们使用了repeat(auto-fill, minmax(300px, 1fr));
如:
repeat()
essentially avoids the repetition of the declaring the track size for each column, but it gets more interesting when it’s used together with auto-fill
.
repeat()
本质上避免了重复声明每一列的轨道大小,但是当它与auto-fill
一起使用时,它会变得更加有趣。
When auto-fill
is given as the repetition number, if the grid container has a definite size or max size in the relevant axis, then the number of repetitions is the largest possible positive integer that does not cause the grid to overflow its grid container.
当将auto-fill
指定为重复编号时,如果网格容器在相关轴上具有确定的大小或最大大小,则重复次数是最大可能的正整数,不会导致网格溢出其网格容器 。
By using auto-fill
with repeat()
, we’ve told the Grid to figure out how many items it can fit within the container size automatically without us having to do any additional calculations.
通过将auto-fill
与repeat()
,我们告诉Grid可以自动计算出多少个项目可以容纳在容器大小内,而无需进行任何其他计算。
minmax
defines a size range greater than or equal to min
and less than or equal to max
.
minmax
定义一个大小范围,该范围大于或等于min
且小于或等于max
。
If max <
min, then max is ignored and minmax(min,m
ax) is treated as
min. As a maximum, a value sets the track’s flex factor it is invalid as a minimum.
如果max <
min,则将max忽略nd minmax(min,m
as
nd minmax(min,m
ax)视为min。 最大值是将轨道的弹性系数设置为最小值,而最小值是无效的。
The fr
unit allows you to set the size of a track as a fraction of the free space of the grid container.
fr
单位允许您将轨道的大小设置为网格容器的可用空间的一部分。
For example, the following will set each item to one third the width of the grid container:
例如,以下将把每个项目设置为网格容器宽度的三分之一:
minmax
allow us to specific the width the item must remain fixed at whilst re-sizing.
minmax
允许我们指定重新调整大小时项目必须保持固定的宽度。
With the columns declared we move onto the rows grid-auto-rows: minmax(275px, auto);
声明了列之后,我们移至grid-auto-rows: minmax(275px, auto);
We’ve utilizedminmax
again here to specific the maximum height of each item being placed on the sub-grid, in this case every home will be 275px.
我们在这里再次利用minmax
来指定放置在子网格上的每个项目的最大高度,在这种情况下,每个房屋的高度为275px。
As a maximum, it is identical to max-content. As a minimum, it represents the largest minimum size (as specified by min-width/min-height) of the grid items occupying the grid track.
最大值与max-content相同。 至少,它代表占用网格轨道的网格项目的最大最小尺寸(由min-width / min-height指定 )。
auto
is used instead of 1fr
in the column declaration because we want the width of the item to automatically change based on the width of the column.
在列声明中使用auto
代替1fr
,因为我们希望项目的宽度根据列的宽度自动更改。
@media (max-width: 1100px) { .wrapper { grid-template-columns: 1fr; } .sidebar { display: none; } .content { width: 100%; grid-template-columns: repeat(auto-fill, minmax(360px, 1fr) ) ; grid-auto-rows: minmax(300px, auto); } }
The great thing about the CSS grids in this example is that the layout only required one media query to create a simple responsive layout.
在此示例中,关于CSS网格的伟大之处在于,该布局仅需要一个媒体查询即可创建简单的响应式布局。
Before I settled on this one breakpoint I set up individual ones for tablet, mobile and so on but I found that it created a jolty change in the size of the home items when re-sizing on the browser so I stuck with one which provided a smoother experience.
在确定这个断点之前,我为平板电脑,移动设备等设置了单独的断点,但是我发现在重新调整浏览器大小时,它会导致首页大小的变化,因此我坚持使用了一个断点。更流畅的体验。
The key difference in the layout within the media query is that the main grid which initially contained two columns defined by percentages now has one column defined with the track-size of 1fr
(I’ve also hid the sidebar as per the behaviour in production).
媒体查询中布局的主要区别在于,最初包含以百分比定义的两列的主网格现在具有以1fr
的轨道大小定义的一列(我也根据生产中的行为隐藏了侧边栏) 。
Then, for each item the same properties and methods are used but the key difference is that I’ve increased the height and width of the items (360px, 300px
).
然后,对于每个项目,使用相同的属性和方法,但主要区别是我增加了项目的高度和宽度( 360px, 300px
)。
That’s it for the Airbnb homes page, please review the CodePen example above to see how it works responsively.
Airbnb主页页面就是这样,请查看上面的CodePen示例以查看其如何响应。
2. YouTube (2. YouTube)
文件格式: (Document Layout:)
<div class="wrapper"> <header class="header">Youtube</header> <aside class="sidebar">Sidebar</aside> <article class="content"> <div class="panel"> <img class="panel-img" src="#"> <span class="panel-title">Title of the video</span> <br> <span class="panel-subtitle">346,112 views</span> </div> <!-- Rest of the video items ... --> </article> </div>
主电网: (Main Grid:)
.wrapper { margin: 0 auto; display: grid; grid-template-columns: 15% 85%; grid-gap: 16px;}
The wrapper
class is used again to define the main grid. There are two columns in the main grid that are associated with the <artic
le>; and &
lt;aside> tags on the document.
wrapper
类再次用于定义主网格。 主网格中有两列与<artic
le>关联; and &
; and &
lt; aside>标签。
I’ve used percentages to define the the track-size
of the two columns.
我使用百分比定义了两列的track-size
。
.content { padding-right: 64px; padding-left: 64px; display: grid; margin: 0 auto; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); grid-auto-rows: minmax(150px, auto); grid-gap: 8px;}
Another sub-grid has been denoted using the .content
property again where it will hold all of the video items.
再次使用.content
属性表示了另一个子网格,该子网格将保存所有视频项。
Please review the Airbnb example above for further explanations of the properties and methods below.
请查看上面的Airbnb示例,以获取有关以下属性和方法的进一步说明。
We’ve then defined the grid columns using repeat(auto-fill, minmax(200px, 1fr));
where every video item will be 300px wide and will automatically fill out the 1fr
column using auto-fill
.
然后,我们使用repeat(auto-fill, minmax(200px, 1fr));
定义网格列repeat(auto-fill, minmax(200px, 1fr));
其中每个视频项目的宽度1fr
300px,并会使用auto-fill
自动填充1fr
列。
The rows have been defined using the minmax
method grid-auto-rows: minmax(150px, auto);
where every item has a max width of 200px. The minmax
specifies the maximum height of each item being placed on the sub-grid, in this case every home will be a max of 150px.
这些行已使用minmax
方法grid-auto-rows: minmax(150px, auto);
每个项目的最大宽度为200px。 minmax
指定放置在子网格上的每个项目的最大高度,在这种情况下,每个房屋的最大高度为150px。
@media (max-width: 1200px) { .wrapper { grid-template-columns: 2fr; } .sidebar { display: none; } .content { width: 100%; grid-template-columns: repeat(auto-fill, minmax(200px, 2fr)); grid-auto-rows: minmax(150px, auto); }}@media (max-width: 768px) { .content { padding-right: 48px; padding-left: 48px; grid-template-columns: repeat(3, minmax(200px, 3fr)); grid-auto-rows: minmax(150px, auto); }}@media (max-width: 700px) { .content { padding-right: 116px; padding-left: 116px; grid-template-columns: repeat(2, minmax(200px, 2fr)); grid-auto-rows: minmax(150px, auto); }}
There are three different breakpoints used to reflect the responsive layout behavior of the YouTube home page.
可以使用三个不同的断点来反映YouTube主页的响应式布局行为。
The key difference in layout within them is that we hide the sidebar and define different columns for the video items.
它们内部布局的主要区别在于,我们隐藏了侧边栏,并为视频项定义了不同的列。
For tablet and below, the column amounts are set to 3fr
meaning there is 3 specific columns the videos can fit inside until it reaches mobile where it’s fixed to 2fr
two columns.
对于平板电脑及以下平板电脑,列数量设置为3fr
这意味着视频可以容纳3个特定列,直到视频到达移动设备(固定在2fr
两列)。
As the layout shrinks the padding around the video items (left, right) increases, ensuring the size of the thumbnails do not increase.
随着布局的缩小,视频项(左,右)周围的填充增加,从而确保缩略图的大小不会增加。
Please review the CodePen example above to see how it works.
请查看上面的CodePen示例以了解其工作原理。
3. Pinterest (3. Pinterest)
文件格式: (Document Layout:)
<div class="wrapper"> <header class="header">Pinterest</header> <article class="content"> <div class="panel tall-panel"> <img class="panel-img" src="#" /> </div> <!-- Rest of the pin items ... --> </article> </div>
主电网: (Main Grid:)
.wrapper { margin: 0 auto; display: grid; grid-template-columns: 1fr; grid-gap: 16px;}
In the wrapper
class, we define the main grid container and one single column with the track size set to 1fr
.
在wrapper
类中,我们定义了主网格容器和一列,轨道大小设置为1fr
。
.content { padding-right: 40px; padding-left: 40px; display: grid; margin: 0 auto; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); grid-auto-rows: minmax(200px, auto); grid-gap: 16px;}
The secondary grid contains all of the pinned items, denoted with the .content
class name where we defined the columns and rows.
辅助网格包含所有固定的项,在我们定义列和行的地方以.content
类名表示。
When defining the columns we used repeat(auto-fill, minmax(240px, 1fr));
在定义列时,我们使用了repeat(auto-fill, minmax(240px, 1fr));
With the colums declared we move onto the rows grid-auto-rows: minmax(200px, auto);
声明了列之后,我们转到grid-auto-rows: minmax(200px, auto);
We’ve utilised minmax
again here to specific the maximum width of each item being placed on the sub-grid, in this case every home will be 200px.
我们在这里再次利用minmax
来指定放置在子网格上的每个项目的最大宽度,在这种情况下,每个房屋将为200px。
auto
is used instead of 1fr
in the column declaration because we want the width of the item to automatically change based on the width of the column.
在列声明中使用auto
代替1fr
,因为我们希望项目的宽度根据列的宽度自动更改。
@media (max-width: 1200px) { .content { padding-right: 72px; padding-left: 72px; width: 100%; grid-template-columns: repeat(3, minmax(220px, 1fr) ) ; grid-auto-rows: minmax(200px, auto); } }
A simple media query is used to create a responsive layout where we update the .content
class with additional padding around the pins. The key detail on how we handle the pins at this point is changing the auto-fill
value in the repeat method to 3
which tells the grid we want no less than three columns at this view port.
一个简单的媒体查询用于创建一个响应式布局,在该布局中,我们通过在引脚周围附加填充物来更新.content
类。 关于如何处理引脚的关键细节是将重复方法中的auto-fill
值更改为3
,这将告诉网格我们在此视口处希望不少于三列。
That’s it for the Pinterest, a relatively simple layout compare to the others. please review the CodePen example above to see how it works responsively
Pinterest就是这样,与其他布局相比,布局相对简单。 请查看上面的CodePen示例,以了解其响应方式
That’s all for now, I’ll be adding additional layouts throughout the next year and I hope to further the complexity of the layouts each time.
到此为止,明年我将添加其他布局,我希望每次都可以进一步增加布局的复杂性。
进一步学习: (Further learning:)
Most of the key learnings and the basis of this post was from Rachel Andrew’s gridbyexample
这篇文章的大部分关键学习内容和内容均来自Rachel Andrew的gridbyexample
For creating a grid system from scratch check out what Stuart Robson put together
要从头开始创建网格系统,请查看Stuart Robson编写的内容
Originally published at cameronjjenkinson.com.
最初发布在cameronjjenkinson.com 。