authors are vetted experts in their fields 和 write on 前ics in which they have demonstrated experience. All of our 内容 is peer reviewed 和 validated by Toptal experts in the same field.< / div >< / div >
< / div >< / div >< / div >< / div >< / div >< / div >< / div >< / div >< / div >< / div >
< / div >
< / div >
< / div >< / div >分享< / div >< / div >< / div >
Mastering web layout without 掌握CSS is about as feasible as learning to swim on dry l和. 但不像游泳, 一旦掌握了, is a skill 那 remains with you 为 life – 掌握CSS is a process 那 never really ends since CSS itself is continually evolving.
的 challenge is aggravated by differences in CSS implementation 和 support across different browsers (和 even across different versions of the same browser), 以及采纳CSS建议的不同比率. 十多年了, web designers 和 developers have been grappling with sporadic 和 inconsistent bursts of 额外的 支持CSS3特性 在每个新的浏览器版本.
One of the best 道路s to learn a technology is to have a specific use case you’re attempting to support or a particular problem you’re trying to solve. Toward 那 end, we’ll focus on a use case with a specific set of requirements.
Header, footer, navigation menu, sub-navigation all remain 固定 on scroll
导航和子导航元素占据所有垂直自由空间
Content section uses all remaining free space on the page 和 has a scrollable area
动态行为
导航菜单默认只显示图标, but can be 扩大 to 显示 text as well (和 can then be collapsed to again show only icons)
布局的变化
有些页面在导航菜单旁边有子导航,有些则没有
使用经典CSS2技术的CSS教程
< / div >
For starters, here’s the HTML5 markup we’ll use with our sample implementation using classic CSS:
固定定位
在CSS2中,我们可以实现页面上的固定元素(页眉、页脚等).),使用使用固定定位的定位布局模型.
另外,我们将使用 z - index CSS 财产 to ensure 那 our 固定 元素 remain “on 前 of” the other 内容 on the page. 的 z - index 属性指定元素的堆栈顺序, where an 元素 with greater stack order is al道路s “on 前 of” an 元素 with a lower stack order. 请注意 z - index 属性仅适用于 定位 元素. 在我们的例子中,我们任意使用a z - index value of 20 (which is higher than the default) to ensure 那 our 固定 元素 remain visually at the 为efront.
同样,我们会设置 宽度 财产 to 100% which instructs the browser to use all available space horizontally 为 the 元素.
垂直扩展是通过设置两个 前 和 底 将元素的属性设置为固定值, so the 元素 will exp和 vertically to use the remaining vertical space accordingly. Basically what you’re doing is tying the 前 of the 元素 to a specific distance from the 前 of the page 和 the 底 of the 元素 to a specific distance from the 底 of the page, so the 元素 exp和s to fill the entire vertical space between those two points.
类似地,通过设置 左 和 正确的 将元素的属性设置为固定值, so the 元素 will exp和 horizontally to use the remaining horizontal space accordingly.
对于我们的用例,我们需要使用垂直扩展.
#导航, #子导航{
位置:固定;
前: 6em; /* leave 1em 保证金 below header */
底: 4em; /* leave 1em 保证金 above footer */
z - index: 20;
}
# nav {
左:0;
宽度:5 em;
}
#子导航{
左:6 em; /* leave 1em 保证金 to 正确的 of nav */
宽度:13 em;
}
默认(静态)定位
的 main scrollable 内容 area can simply rely on default (static) positioning, 元素按照它们在文档流中出现的顺序呈现. 因为页面上的其他东西都在固定位置, 该元素是文档流中唯一的元素. 因此,要正确定位它所需要做的就是指定它的 保证金 属性以避免与固定页眉、页脚和nav/子导航重叠:
#{主要
边距:60 - 40 - 20;
}
说到这里, 使用CSS2,我们已经满足了用例的基本布局需求, but we still need to satisfy the 额外的 requirements 为 dynamic 函数ality.
使用经典CSS2技术的动态行为
的 requirements stated 那 our Navigation menu would by default show only icons, but would be able to be 扩大 to 显示 text as well (和 could then be collapsed to again show only icons).
< / div >
让我们从简单的加法开始 5em 到导航菜单展开时的宽度. We’ll do this by creating an “扩大” CSS class 那 we can dynamically add or remove from the navigation menu 元素:
还不错,但也不完全是. Although the nav menu can now exp和 和 contract, it doesn’t play well with the rest of the page. 的 扩大 nav menu now overlaps the 子导航 which is definitely 不 the desired behavior.
This reveals one of the key limitations of CSS2; namely, there is 道路 太多需要用固定位置值硬编码的内容. 结果是, 为 the other 元素 on the page 那 need to be re定位 to accommodate the 扩大 nav menu, 我们需要定义 额外的 “扩展”CSS类 更多的 固定位置值.
#子导航{
左:6 em;
宽度:13 em;
&.扩大{
左: 11em; /* move it on over */
}
}
#{主要
页边距:6em 0 4em 20;
z - index: 10;
&.扩大{
保证金-左: 25 em; /* move it on over */
}
}
We then need to extend our JavaScript code to add dynamic adjustment of these other 元素 as well when the nav toggle is clicked by the user:
Now let’s address the requirement of having some pages 那 hide the sub nav menu. 具体地说, we want the sub nav menu to be hidden when the user clicks the “users” icon in the main nav area.
< / div >
因此,首先,我们将创建一个新类“hidden”来应用 显示:没有:
.隐藏的{
显示:没有;
}
And again, we’ll use JavaScript (jQuery) to apply the “hidden” CSS class to the #子导航 元素,当用户单击users图标时:
(Note: One disadvantage of using the 相邻兄弟选择器 is 那 it 为ces us to al道路s have #子导航 显示在DOM中,而不管它是否被显示.)
最后,如果 #子导航 是隐藏的 #导航 是展开的,我们设置左边距 #主要 at 11em:
#子导航.Hidden + #主要.扩大{
保证金-左: 11 em;
}
这使我们能够在没有任何繁重的JavaScript代码的情况下将东西连接在一起, but we can also see how complicated this code can become if we add more 元素 to the page. 我们再次看到,使用CSS2, 很多 of hardcoding of 位置值 is needed in order to get things to work properly.
利用CSS3
CSS3 offers significantly enhanced 函数ality 和 layout techniques 那 make it much easier to use 和 much less reliant on hardcoded values. CSS3天生就支持更多的动态行为, 从这个意义上说, “可编程”. 让我们来看看与我们的用例相关的一些新功能.
CSS3 钙() 函数
新 CSS3 钙() 函数 可以用来动态计算CSS属性值(不过请注意, 支持不同 跨浏览器). 的表达式 钙() 函数 can be any simple expression combining the basic arithmetic operators (+, -, *, /),使用标准操作符优先规则.
有了以上内容 高度 规范使用 钙() 函数,我们实现了与CSS2中相同的结果 上图:6 em 和 底部:4 em, but in a much more flexible 和 adaptive 道路, without needing to hardcode 前 和 底 位置值.
CSS3 Flexbox布局
Flexbox 是CSS3 (不同浏览器的支持不同). 的 flexbox layout makes it simpler to arrange 元素 on a page in a 道路 那 behaves predictably across different screen sizes, 决议, 和设备. 因此,它在下列情况下特别有用 响应式网页设计.
主要特点包括:
Positioning child 元素 is much easier 和 complex layouts can be achieved more simply 和 with cleaner code.
Child 元素 can be laid out in any direction 和 can have flexible dimensions to adapt to the 显示 space.
子元素自动扩展契约以适应可用的空闲空间.
Flexbox引入了自己独特的术语和概念. 其中一些包括:
Flex容器. 具有其 显示 属性设置为 flex or inline-flex 哪个作为伸缩项的容器元素.
Flex项目. 伸缩容器中的任何元素. (Note: Text directly contained in a flex container is wrapped in an anonymous flex item.)
虽然我们的主要布局是垂直的, 内容区域中的元素(nav, 子导航, 主)是水平布局的. 每个伸缩容器只能定义一个方向(i.e.,其布局必须是水平或垂直的). 因此, when the layout requires more than this (a common case being 为 an app layout), 我们可以将多个容器嵌套在一起, 每个都有不同的方向布局.
现在,为了定位我们的伸缩项,我们将使用属性 flex 这是一个简写 flex: ;. Those three flex properties are the ones 那 determine how our flex items distribute any free space remaining between them in the flow direction, 如下:
flex-grow: specifies how much an item can grow relative to the rest of the flexible items inside the same container
flex-shrink: specifies how an item can shrink relative to the rest of the flexible items inside the same container
设置 flex-grow 和 flex-shrink 两者都为零表示该项的大小为 固定 和 it will 不 grow or shrink to accommodate there being more or less free space available. 这就是我们对页眉和页脚所做的,因为它们有固定的大小:
#标题{
Flex: 0 0 5em;
}
#页脚{
Flex: 0 0 3em;
}
要让一个项目占用所有可用的空闲空间,请设置其 flex-grow 和 flex-shrink 值为1,并设置其 flex-basis 价值 汽车. This is what we do 为 the 内容 area since we want it to take up all available free space.
Note 那 this time we don’t need to let other items know about the 宽度 change, 因为flexbox布局为我们处理了所有这些.
唯一剩下的就是把潜艇导航藏起来了. 你猜怎么着? That “just works” too, without any 额外的 changes, using the same JavaScript code as be为e. Flexbox knows about free space 和 it 汽车matically makes our layout work with no extra code. 很酷.
Flexbox also provides some interesting 道路s of centering both vertical 和 horizontal 元素. We realize here how important it is 为 a presentational language to include the 不ion of free space 和 how scalable our code can become using these sorts of techniques. On the other h和, the concepts 和 不ation here can take a bit more to master than classic CSS.
CSS3网格布局
如果Flexbox布局是在CSS3的前沿, 那么网格布局可以说是在其流血的边缘. W3C规范仍处于草案状态 浏览器支持相当有限. (It’s enabled in Chrome through the “experimental 网络 Plat为m features” flag in chrome://flags).
相应的, 基于标记的网格已经使用了很长时间, 所以现在CSS网格布局实际上只是遵循相同的范式, offering all of its benefits 和 much more in the presentation layer with no markup requirements.
一般的想法是有一个预定义的, 固定, 或者灵活的网格布局,我们可以定位我们的元素. 比如flexbox, it also works on the free space principle 和 allows us to define both vertical 和 horizontal “directions” in the same 元素, 哪个在代码大小和灵活性上有优势.
Like flexbox, Grid layout introduces its own unique set of terms 和 concepts. 其中一些包括:
网格容器. 具有其 显示 属性设置为 “grid” or “inline-grid” into which the contained 元素 are laid out by positioning 和 aligning to a predefined grid (显式的 mode). 的 grid is an intersecting set of horizontal 和 vertical grid lines 那 divide the grid container’s space into grid cells. 的re are two sets of grid lines; one 为 defining the columns 和 one orthogonal to it 为 defining the rows.
网格单元. 两个相邻行和两个相邻列网格线之间的空间. It is the smallest unit of the grid 那 can be referenced when positioning grid items.
灵活的长度. 指定的维度 fr 单元,它表示网格容器中可用空间的一小部分.
< / div >
如果我们使用网格布局,这里是我们可以使用的替代标记:
注意,在这个布局中,我们这样做 不 内容区域需要一个额外的包装器,就像我们为flexbox所做的那样, since this type of layout allows us to define 元素 space designation in both directions in the same grid container.
我们定义 显示:网格; 在我们的集装箱上. 的 grid-template-columns 和 grid-template-rows 每个属性都被指定为网格轨道之间的空格列表. In other words, those values are 不 the position of the grid lines; rather, they represent the 空间量 两轨之间.
注意,测量单位可以指定为:
一个长度
网格容器大小的百分比
对所占列或行内容的测量
网格中自由空间的一小部分
所以, 网格模板列:汽车 0 汽车 1em 1fr; 我们将有:
1个轨道定义2列 汽车 宽度(#导航 空间)
0的边距 #子导航 is at the 元素 level, as it can be present or 不, this 道路 we avoid having double gutter)
1个轨道定义2列 汽车 宽度(#子导航 空间)
1沟槽 1em
1轨道使用 1fr 为 #主要 (将占用所有剩余空间)
这里我们大量使用 汽车 轨道的值, which allows us to have dynamic columns where the position 和 size of lines are defined by their maximum 内容. (因此,我们需要指定的尺寸 #导航 和 #子导航 元素,我们很快就会讲到.)
类似地,对于我们已知的行线 网格模板行:5em 1em 1em 3em; 这就是我们的 #头 和 #页脚 to be 固定 和 all 元素 between to use the remaining free space while using 1em 排水沟.
Now let’s see how we place the actual 元素 to be 定位 into our defined grid:
This specifies 那 we want our header to be between grid line 1 和 6 (full 宽度), 在网格线1和2之间. 页脚也一样,但在最后两行之间(而不是前两行). And the main area is set appropriately 为 the space it is supposed to occupy.
现在我们可以切换 #导航 还有隐藏/移除 #子导航 一切都很完美! 网格布局也允许我们为我们的线条使用别名, so eventually changing grids won’t break out code as it’s mapped to a name 和 不 a grid line. Definitely looking 为ward to this being more widely supported by more browsers.
结论
即使使用经典的CSS技术, there’s much more 那 can be accomplished than many web developers realize or take advantage of. 也就是说, much of this can be quite tedious 和 can involve hardcoding of values repeatedly throughout a style sheet.
CSS3 has begun to deliver much more sophisticated 和 flexible layout techniques 那 are 更容易编程 并且避免了以前的CSS规范的许多乏味之处.
Mastering these techniques 和 paradigms – both 为 CSS2 和 CSS3 – is essential to leveraging all 那 CSS has to offer in order to optimize both the user’s experience 和 the quality of your code. This article really just represents the tip of the iceberg of all there is to learn 和 all 那 can be accomplished with the power 和 flexibility of CSS. 试试吧!
Laureano is a web developer 和 designer with a variety of skills gained over the last 15 years, 与英特尔等客户合作.
< / div >< / div >< / div >
authors are vetted experts in their fields 和 write on 前ics in which they have demonstrated experience. All of our 内容 is peer reviewed 和 validated by Toptal experts in the same field.< / div >