CSS Grid is one of the most amazing parts of the CSS language. It gives us a ton of new tools we can use to create sophisticated and fluid layouts.
CSS 网格是 CSS 语言中最令人惊奇的部分之一。它为我们提供了大量新工具,可用于创建复杂且流畅的布局。
It's also surprisingly complex. It took me quite a while to truly become comfortable with CSS Grid!
它也非常复杂。我花了很长时间才真正熟悉 CSS Grid!
In this tutorial, I'm going to share the biggest 💡 lightbulb moments I've had in my own journey with CSS Grid. You'll learn the fundamentals of this layout mode, and see how to do some pretty cool stuff with it. ✨
在本教程中,我将分享我在 CSS Grid 之旅中经历过的最伟大的💡灯泡时刻。您将学习这种布局模式的基础知识,并了解如何用它做一些非常酷的事情。 ✨
Link to this headingMental model 心智模型
CSS is comprised of several different layout algorithms, each designed for different types of user interfaces. The default layout algorithm, Flow layout, is designed for digital documents. Table layout is designed for tabular data. Flexbox is designed for distributing items along a single axis.
CSS 由多种不同的布局算法组成,每种算法针对不同类型的用户界面而设计。默认布局算法 “流布局” 是为数字文档设计的。表格布局是为表格数据设计的。 Flexbox 设计用于沿单个轴分配项目。
CSS Grid is the latest and greatest layout algorithm. It's incredibly powerful: we can use it to build complex layouts that fluidly adapt based on a number of constraints.
CSS Grid 是最新、最好的布局算法。它的功能非常强大:我们可以用它来构建复杂的布局,并根据许多约束条件进行流畅地适应。
The most unusual part of CSS Grid, in my opinion, is that the grid structure, the rows and columns, are defined purely in CSS:
在我看来,CSS 网格最不寻常的部分是网格结构、行和列纯粹是在 CSS 中定义的:
With CSS Grid, a single DOM node is sub-divided into rows and columns. In this tutorial, we're highlighting the rows/columns with dashed lines, but in reality, they're invisible.
使用 CSS Grid,单个 DOM 节点被细分为行和列。在本教程中,我们用虚线突出显示行 / 列,但实际上,它们是不可见的。
This is super weird! In every other layout mode, the only way to create compartments like this is by adding more DOM nodes. In Table layout, for example, each row is created with a <tr>
, and each cell within that row using <td>
or <th>
:
这实在是太奇怪了!在所有其他布局模式中,创建这样的隔间的唯一方法是添加更多 DOM 节点。例如,在表布局中,每行均使用 <tr>
创建,该行中的每个单元格均使用 <td>
或 <th>
创建:
<table>
<tbody>
<!-- First row -->
<tr>
<!-- Cells in the first row -->
<td></td>
<td></td>
<td></td>
</tr>
<!-- Second row -->
<tr>
<!-- Cells in the second row -->
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Unlike Table layout, CSS Grid lets us manage the layout entirely from within CSS. We can slice up the container however we wish, creating compartments that our grid children can use as anchors.
与表格布局不同,CSS 网格允许我们完全从 CSS 内部管理布局。我们可以按照自己的意愿对容器进行切片,创建网格子节点可以用作锚点的隔间。
Link to this headingGrid flow 网格流
We opt in to the Grid layout mode with the display
property:
我们使用 display
属性选择网格布局模式:
.wrapper {
display: grid;
}
By default, CSS Grid uses a single column, and will create rows as needed, based on the number of children. This is known as an implicit grid, since we aren't explicitly defining any structure.
默认情况下,CSS 网格使用单列,并根据子项的数量根据需要创建行。这称为隐式网格,因为我们没有显式定义任何结构。
Here's how this works: 这是它的工作原理:
Implicit grids are dynamic; rows will be added and removed based on the number of children. Each child gets its own row.
隐式网格是动态的;将根据子项的数量添加和删除行。每个孩子都有自己的行。
By default, the height of the grid parent is determined by its children. It grows and shrinks dynamically. Interestingly, this isn't even a “CSS Grid” thing; the grid parent is still using Flow layout, and block elements in Flow layout grow vertically to contain their content. Only the children are arranged using Grid layout.
默认情况下,网格父级的高度由其子级确定。它动态地增长和收缩。有趣的是,这甚至不是一个 “CSS 网格” 的东西;而是一个东西。网格父级仍然使用流式布局,流式布局中的块元素垂直增长以包含其内容。只有子级使用网格布局进行排列。
But what if we give the grid a fixed height? In that case, the total surface area is divided into equally-sized rows:
但是如果我们给网格一个固定的高度呢?在这种情况下,总表面积被分成大小相等的行:
.parent {
display: grid;
height: 300px;
}
Link to this headingGrid Construction 电网建设
By default, CSS Grid will create a single-column layout. We can specify columns using the grid-template-columns
property:
默认情况下,CSS Grid 将创建单列布局。我们可以使用 grid-template-columns
属性指定列:
Code Playground 代码游乐场
Result 结果
By passing two values to grid-template-columns
— 25%
and 75%
— I'm telling the CSS Grid algorithm to slice the element up into two columns.
通过将两个值传递给 grid-template-columns
— 25%
和 75%
— 我告诉 CSS 网格算法将元素分成两列。
Columns can be defined using any valid CSS <length-percentage> value(opens in new tab), including pixels, rems, viewport units, and so on. Additionally, we also gain access to a new unit, the fr
unit:
可以使用任何有效的 CSS <length-percentage> 值定义列(在新选项卡中打开) ,包括像素、rems、视口单位等。此外,我们还可以使用一个新单位, fr
单位:
Code Playground 代码游乐场
Result 结果
fr
stands for “fraction”. In this example, we're saying that the first column should consume 1 unit of space, while the second column consumes 3 units of space. That means there are 4 total units of space, and this becomes the denominator. The first column eats up ¼ of the available space, while the second column consumes ¾.fr
代表 “分数”。在此示例中,我们说第一列应消耗 1 个单位的空间,而第二列应消耗 3 个单位的空间。这意味着总共有 4 个空间单位,这就是分母。第一列占用 1/4 的可用空间,而第二列占用 3/4。
The fr
unit brings Flexbox-style flexibility to CSS Grid. Percentages and <length>
values create hard constraints, while fr
columns are free to grow and shrink as required, to contain their contents.
Try shrinking this container to see the difference:
.parent {
display: grid;
grid-template-columns: 1fr 3fr;
}
In this scenario, our first column has a cuddly ghost that has been given an explicit width of 55px. But what if the column is too small to contain it?
- Percentage-based columns are rigid, and so our ghost image will overflow, spilling out of the column.
fr
-based columns are flexible, and so the column won't shrink below its minimum content size, even if that means breaking the proportions.
To be more precise: the fr
unit distributes extra space. First, column widths will be calculated based on their contents. If there's any leftover space, it'll be distributed based on the fr
values. This is very similar to flex-grow
, as discussed in my Interactive Guide to Flexbox.
In general, this flexibility is a good thing. Percentages are too strict.
We can see a perfect example of this with gap
. gap
is a magical CSS property that adds a fixed amount of space between all of the columns and rows within our grid.
Check out what happens when we toggle between percentages and fractions:
.parent {
display: grid;
grid-template-columns: 1fr 3fr;
gap: 16px;
}
Notice how the contents spill outside the grid parent when using percentage-based columns? This happens because percentages are calculated using the total grid area. The two columns consume 100% of the parent's content area, and they aren't allowed to shrink. When we add 16px of gap
, the columns have no choice but to spill beyond the container.
The fr
unit, by contrast, is calculated based on the extra space. In this case, the extra space has been reduced by 16px, for the gap
. The CSS Grid algorithm distributes the remaining space between the two grid columns.
Link to this headingImplicit and explicit rows
What happens if we add more than two children to a two-column grid?
Well, let's give it a shot:
Code Playground
Result
Interesting! Our grid gains a second row. The grid algorithm wants to ensure that every child has its own grid cell. It’ll spawn new rows as-needed to fulfill this goal. This is handy in situations where we have a variable number of items (eg. a photo grid), and we want the grid to expand automatically.
In other situations, though, we want to define the rows explicitly, to create a specific layout. We can do that with the grid-template-rows
property:
Code Playground
Result
By defining both grid-template-rows
and grid-template-columns
, we've created an explicit grid. This is perfect for building page layouts, like the This was the name given to the most common layout in the days of the early web: a header, sidebar, main content area, and footer. layout at the top of this tutorial.
Link to this headingThe repeat helper
Let's suppose we're building a calendar:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
CSS Grid is a wonderful tool for this sort of thing. We can structure it as a 7-column grid, with each column consuming 1 unit of space:
.calendar {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
}
This works, but it's a bit annoying to have to count each of those 1fr
’s. Imagine if we had 50 columns!
Fortunately, there's a nicer way to solve for this:
.calendar {
display: grid;
grid-template-columns: repeat(7, 1fr);
}
The repeat
function will do the copy/pasting for us. We're saying we want 7 columns that are each 1fr
wide.
Here's the playground showing the full code, if you're curious:
Code Playground
Result
Link to this headingAssigning children 分配孩子
By default, the CSS Grid algorithm will assign each child to the first unoccupied grid cell, much like how a tradesperson might lay tiles in a bathroom floor.
默认情况下,CSS 网格算法会将每个子项分配给第一个未占用的网格单元,就像技工在浴室地板上铺设瓷砖的方式一样。
Here's the cool thing though: we can assign our items to whichever cells we want! Children can even span across multiple rows/columns.
不过,这很酷:我们可以将项目分配到我们想要的任何单元格!孩子们甚至可以跨越多行 / 列。
Here's an interactive demo that shows how this works. Click/press and drag to place a child in the gridIf you're not using a pointer device like a mouse or touchscreen, keyboard-based controls have also been provided. Check out the “Help” screen below for more information.:
这是一个交互式演示,展示了其工作原理。单击 / 按下并拖动以将子项放置在网格中 如果您不使用鼠标或触摸屏等指针设备,还提供了基于键盘的控件。查看下面的 “帮助” 屏幕以获取更多信息。
碳 6 0
7.199999999999999 6
12 6
C 16.8 6
18 0
24 0
Z"> :
.parent {
display: grid;
grid-template-columns:
repeat(4, 1fr);
grid-template-rows:
repeat(4, 1fr);
}
.child {
grid-row: 1 / 4;
grid-column: 1;
}
The grid-row
and grid-column
properties allow us to specify which track(s) our grid child should occupy.grid-row
和 grid-column
属性允许我们指定网格子项应占用的轨道。
If we want the child to occupy a single row or column, we can specify it by its number. grid-column: 3
will set the child to sit in the third column.
如果我们希望子元素占据一行或一列,我们可以通过它的编号来指定它。 grid-column: 3
将设置孩子坐在第三列。
Grid children can also stretch across multiple rows/columns. The syntax for this uses a slash to delineate start and end:
网格子项还可以跨多行 / 列延伸。其语法使用斜杠来描绘开始和结束:
.child {
grid-column: 1 / 4;
}
At first glance, this looks like a fraction, ¼. In CSS, though, the slash character is not used for division, it's used to separate groups of values. In this case, it allows us to set the start and end columns in a single declaration.
乍一看,这看起来像一个分数,1/4。但在 CSS 中,斜杠字符不用于除法,而是用于分隔值组。在这种情况下,它允许我们在单个声明中设置开始列和结束列。
It's essentially a shorthand for this:
它本质上是一个简写:
.child {
grid-column-start: 1;
grid-column-end: 4;
}
There's a sneaky gotcha here: The numbers we're providing are based on the column lines, not the column indexes.
这里有一个偷偷摸摸的陷阱:我们提供的数字基于列行,而不是列索引。
It'll be easiest to understand this gotcha with a diagram:
通过图表最容易理解这个问题:
.child {
grid-row: 2 / 4;
grid-column: 1 / 4;
}
Confusingly, a 4-column grid actually has 5 column lines. When we assign a child to our grid, we anchor them using these lines. If we want our child to span the first 3 columns, it needs to start on the 1st line and end on the 4th line.
令人困惑的是,4 列网格实际上有 5 条列线。当我们将一个子项分配给网格时,我们使用这些线来锚定它们。如果我们希望我们的孩子跨越前 3 列,它需要从第一行开始到第四行结束。
Link to this headingGrid areas 网格区域
Alright, time to talk about one of the coolest parts of CSS Grid. 😄
好吧,是时候谈谈 CSS Grid 最酷的部分之一了。 😄
Let's suppose we're building this layout:
假设我们正在构建这个布局:
Using what we've learned so far, we could structure it like this:
利用我们迄今为止所学到的知识,我们可以将其构造如下:
.grid {
display: grid;
grid-template-columns: 2fr 5fr;
grid-template-rows: 50px 1fr;
}
.sidebar {
grid-column: 1;
grid-row: 1 / 3;
}
.header {
grid-column: 2;
grid-row: 1;
}
.main {
grid-column: 2;
grid-row: 2;
}
This works, but there's a more ergonomic way to do this: grid areas.
这是可行的,但是有一种更符合人体工程学的方法可以做到这一点:网格区域。
Here's what it looks like:
它看起来是这样的:
.parent {
display: grid;
grid-template-columns: 2fr 5fr;
grid-template-rows: 50px 1fr;
grid-template-areas:
'sidebar header'
'sidebar main';
}
.child {
grid-area: sidebar;
}
Like before, we're defining the grid structure with grid-template-columns
and grid-template-rows
. But then, we have this curious declaration:
像以前一样,我们使用 grid-template-columns
和 grid-template-rows
定义网格结构。但是,我们有这个奇怪的声明:
.parent {
grid-template-areas:
'sidebar header'
'sidebar main';
}
Here's how this works: We're drawing out the grid we want to create, almost as if we were making Art made out of typographical characters. Popular in the days of command-line computing.. Each line represents a row, and each word is a name we're giving to a particular slice of the grid. See how it sorta looks like the grid, visually?
这是它的工作原理:我们正在绘制我们想要创建的网格,几乎就像我们在制作 。每条线代表一行,每个单词都是我们为网格的特定切片指定的名称。看看它在视觉上看起来像网格吗?
Then, instead of assigning a child with grid-column
and grid-row
, we assign it with grid-area
!
然后,我们不是用 grid-column
和 grid-row
分配子级,而是用 grid-area
分配它!
When we want a particular area to span multiple rows or columns, we can repeat the name of that area in our template. In this example, the “sidebar” area spans both rows, and so we write sidebar
for both cells in the first column.
当我们希望特定区域跨越多行或多列时,我们可以在模板中重复该区域的名称。在此示例中,“侧边栏” 区域跨越两行,因此我们为第一列中的两个单元格编写 sidebar
。
Should we use areas, or rows/columns? When building explicit layouts like this, I really like using areas. It allows me to give semantic meaning to my grid assignments, instead of using inscrutable row/column numbers. That said, areas work best when the grid has a fixed number of rows and columns. grid-column
and grid-row
can be useful for implicit grids.
我们应该使用区域还是行 / 列?当构建这样的显式布局时,我真的很喜欢使用区域。它允许我为网格分配赋予语义意义,而不是使用难以理解的行 / 列号。也就是说,当网格具有固定数量的行和列时,区域效果最佳。 grid-column
和 grid-row
对于隐式网格很有用。
Link to this headingBeing mindful of keyboard users
留意键盘用户
There's a big gotcha when it comes to grid assignments: tab order will still be based on DOM position, not grid position.
在网格分配方面有一个很大的问题: Tab 顺序仍然基于 DOM 位置,而不是网格位置。
It'll be easier to explain with an example. In this playground, I've set up a group of buttons, and arranged them with CSS Grid:
用一个例子来解释会更容易。在这个 Playground 中,我设置了一组按钮,并使用 CSS 网格排列它们:
Code Playground 代码游乐场
Result 结果
In the “RESULT” pane, the buttons appear to be in order. By reading from left to right, and from top to bottom, we go from one to six.
在 “结果” 窗格中,按钮似乎按顺序排列。通过从左到右、从上到下阅读,我们从一到六。
If you're using a device with a keyboard, try to tab through these buttons. You can do this by clicking the first button in the top left (“One”), and then pressing Tab to move through the buttons one at a time.
如果您使用的是带键盘的设备,请尝试按 Tab 键浏览这些按钮。您可以通过单击左上角的第一个按钮(“One”),然后按 Tab 一次移动一个按钮。
You should see something like this:
你应该看到这样的东西:
The focus outline jumps around the page without rhyme or reason, from the user's perspective. This happens because the buttons are being focused based on the order they appear in the DOM.
从用户的角度来看,焦点轮廓在页面上毫无规律地跳跃。发生这种情况是因为按钮是根据它们在 DOM 中出现的顺序获得焦点的。
To fix this, we should re-order the grid children in the DOM so that they match the visual order, so that I can tab through from left to right, and from top to bottom.
为了解决这个问题,我们应该重新排序 DOM 中的网格子项,使它们与视觉顺序匹配,这样我就可以从左到右、从上到下进行 Tab 浏览。*This will even work correctly for right-to-left languages like Arabic and Hebrew; CSS Grid columns will be mirrored in these languages, with column 1 being on the right instead of the left. And so, the same DOM order works for all languages.
Link to this headingAlignment 结盟
In all the examples we've seen so far, our columns and rows stretch to fill the entire grid container. This doesn't need to be the case, however!
在到目前为止我们看到的所有示例中,我们的列和行都拉伸以填充整个网格容器。然而,情况并不一定如此!
For example, let's suppose we define two columns that are each 90px wide. As long as the grid parent is larger than 180px, there will be some dead space at the end:
例如,假设我们定义两列,每列宽度为 90 像素。只要网格父级大于 180px,末尾就会出现一些死角:
We can control the distribution of the columns using the justify-content
property:
我们可以使用 justify-content
属性控制列的分布:
.parent {
display: grid;
grid-template-columns: 90px 90px;
justify-content: start;
}
If you're familiar with the Flexbox layout algorithm, this probably feels pretty familiar. CSS Grid builds on the alignment properties first introduced with Flexbox, taking them even further.
如果您熟悉 Flexbox 布局算法,这可能会感觉非常熟悉。 CSS Grid 建立在 Flexbox 首次引入的对齐属性的基础上,进一步发展了它们。
The big difference is that we're aligning the columns, not the items themselves. Essentially, justify-content
lets us arrange the compartments of our grid, distributing them across the grid however we wish.
最大的区别在于我们对齐的是列,而不是项目本身。本质上, justify-content
让我们可以安排网格的各个部分,按照我们的意愿将它们分布在网格上。
If we want to align the items themselves within their columns, we can use the justify-items
property:
如果我们想在列中对齐项目本身,我们可以使用 justify-items
属性:
.parent {
display: grid;
grid-template-columns: 90px 90px;
justify-content: center;
justify-items: center;
}
When we plop a DOM node into a grid parent, the default behaviour is for it to stretch across that entire column, just like how a <div>
in Flow layout will stretch horizontally to fill its container. With justify-items
, however, we can tweak that behaviour.
当我们将 DOM 节点放入网格父级时,默认行为是它延伸到整个列,就像流布局中的 <div>
将水平延伸以填充其容器一样。然而,使用 justify-items
,我们可以调整这种行为。
This is useful because it allows us to break free from the rigid symmetry of columns. When we set justify-items
to something other than stretch
, the children will shrink down to their default width, as determined by their contents. As a result, items in the same column can be different widths.
这很有用,因为它使我们能够摆脱柱的严格对称性。当我们将 justify-items
设置为 stretch
之外的其他值时,子项将缩小到其默认宽度,具体取决于其内容。因此,同一列中的项目可以具有不同的宽度。
We can even control the alignment of a specific grid child using the justify-self
property:
我们甚至可以使用 justify-self
属性来控制特定子网格的对齐方式:
.parent {
display: grid;
grid-template-columns: 90px 90px;
justify-content: start;
}
.one {
justify-self: center;
}
Unlike justify-items
, which is set on the grid parent and controls the alignment of all grid children, justify-self
is set on the child. We can think of justify-items
as a way to set a default value for justify-self
on all grid children.
与 justify-items
在网格父级上设置并控制所有网格子级的对齐方式不同, justify-self
在子级上设置。我们可以将 justify-items
视为在所有网格子项上为 justify-self
设置默认值的一种方法。
Link to this headingAligning rows 对齐行
So far, we've been talking about how to align stuff in the horizontal direction. CSS Grid provides an additional set of properties to align stuff in the vertical direction:
到目前为止,我们一直在讨论如何在水平方向上对齐东西。 CSS Grid 提供了一组附加属性来在垂直方向上对齐内容:
align-content
is like justify-content
, but it affects rows instead of columns. Similarly, align-items
is like justify-items
, but it handles the vertical alignment of items inside their grid area, rather than horizontal.align-content
与 justify-content
类似,但它影响行而不是列。类似地, align-items
类似于 justify-items
,但它处理网格区域内项目的垂直对齐,而不是水平对齐。
To break things down even further:
进一步分解:
justify
— deals with columns.justify
— 处理列。align
— deals with rows.align
—— 处理行。content
— deals with the grid structure.content
—— 涉及网格结构。items
— deals with the DOM nodes within the grid structure.items
— 处理网格结构中的 DOM 节点。
Finally, in addition to justify-self
, we also have align-self
. This property controls the vertical position of a single grid item within its cell.
最后,除了 justify-self
之外,我们还有 align-self
。此属性控制单元格内单个网格项的垂直位置。
Link to this headingTwo-line centering trick 两线居中技巧
There's one last thing I want to show you. It's one of my favourite little tricks with CSS Grid.
我想向您展示最后一件事。这是我最喜欢的 CSS 网格小技巧之一。
Using only two CSS properties, we can center a child within a container, both horizontally and vertically:
仅使用两个 CSS 属性,我们就可以将子项在容器内水平和垂直居中:
.parent {
display: grid;
place-content: center;
}
The place-content
property is a shorthand. It's syntactic sugar for this:place-content
属性是一种简写。这是语法糖:
.parent {
justify-content: center;
align-content: center;
}
As we've learned, justify-content
controls the position of columns. align-content
controls the position of rows. In this situation, we have an implicit grid with a single child, and so we wind up with a 1×1 grid. place-content: center
pushes both the row and column to the center.
正如我们所知, justify-content
控制列的位置。 align-content
控制行的位置。在这种情况下,我们有一个带有单个子项的隐式网格,因此我们最终得到一个 1×1 网格。 place-content: center
将行和列都推到中心。
There are lots of ways to center a div in modern CSS, but this is the only way I know of that only requires two CSS declarations!
在现代 CSS 中,有很多方法可以使 div 居中,但这是我所知道的唯一只需要两个 CSS 声明的方法!
Link to this headingTip of the iceberg 冰山一角
In this tutorial, we've covered some of the most fundamental parts of the CSS Grid layout algorithm, but honestly, there's so much more stuff we haven't talked about!
在本教程中,我们介绍了 CSS 网格布局算法的一些最基本的部分,但说实话,我们还有很多东西没有讨论!
If you found this blog post helpful, you might be interested to know that I've created a comprehensive learning resource that goes way deeper. It's called CSS for JavaScript Developers(opens in new tab).
如果您发现这篇博文有帮助,您可能有兴趣知道我创建了一个更深入的 综合学习资源。它被称为 JavaScript 开发人员的 CSS (在新选项卡中打开) 。
The course uses the same technologies as my blog, and so it's chock full of interactive explanations. But there are also bite-sized videos, practice exercises, real-world-inspired projects, and even a few mini-games.
该课程使用与我的博客相同的技术,因此充满了交互式解释。但也有小型视频、练习、受现实世界启发的项目,甚至一些迷你游戏。
If you found this blog post helpful, you'll love the course. It follows a similar approach, but for the entire CSS language, and with hands-on practice to make sure you're actually developing new skills.
如果您发现这篇博文有帮助,您一定会喜欢这门课程。它遵循类似的方法,但针对整个 CSS 语言,并通过实践练习来确保您实际上正在开发新技能。
It's specifically built for folks who use a JS framework like React/Angular/Vue. 80% of the course focuses on CSS fundamentals, but we also see how to integrate those fundamentals into a modern JS application, how to structure our CSS, stuff like that.
它是专门为使用 React/Angular/Vue 等 JS 框架的人们而构建的。课程 80% 的内容侧重于 CSS 基础知识,但我们也了解如何将这些基础知识集成到现代 JS 应用程序中,如何构建我们的 CSS 等等。
If you struggle with CSS, I hope you'll check it out. Gaining confidence with CSS is game-changing, especially if you're already comfortable with HTML and JS. When you complete the holy trinity, it becomes so much easier to stay in flow, to truly enjoy developing web applications.
如果你对 CSS 有困难,我希望你能看看。获得对 CSS 的信心将会改变游戏规则,特别是如果您已经熟悉 HTML 和 JS。当您完成这神圣的三位一体后,保持流畅、真正享受开发 Web 应用程序就会变得更加容易。
You can learn more here:
您可以在这里了解更多信息:
I hope you found this tutorial useful. ❤️
我希望您觉得本教程有用。 ❤️
Last updated on 最后更新于
September 13th, 2024 2024 年 9 月 13 日