引言
昨日看牛客面经,看到一个面试题:实现一个圣杯布局,也正好是我刚看了阮老师Flex布局教程中有对圣杯布局的描述,我当时并没有实现,但看来还是要老老实实动手去实现一下,写的过程我也对 flex:1 进行了一些探索和得到一些新的认识。
圣杯布局
圣杯布局(Holy Grail Layout)指的是一种最常见的网站布局。页面从上到下,分成三个部分:头部(header),躯干(body),尾部(footer)。其中躯干又水平分成三栏,从左到右为:导航、主栏、副栏。
弹性盒模型实现
我是按照阮老师的示例,采用Flex布局实现,大体相同,有些细节部分不一样
HTML代码如下:
<body class="HolyGrail">
<header>#header</header>
<div class="HolyGrail-body">
<main class="HolyGrail-content">#center</main>
<nav class="HolyGrail-nav">#left</nav>
<aside class="HolyGrail-ads">#right</aside>
</div>
<footer>#footer</footer>
</body>
CSS代码如下:
* {
margin: 0;
}
.HolyGrail {
display: flex;
min-height: 100vh; /*撑满整个屏幕*/
flex-direction: column; /* 头、中部、脚纵向显示 */
}
header,
footer {
height: 60px; /*设置一个固定的高度*/
background: rgba(29, 27, 27, 0.726);
/* 用于字体居中,不是重点 */
line-height: 60px;
text-align: center;
color: white;
}
.HolyGrail-body {
display: flex;
flex: 1;
}
.HolyGrail-content {
flex: 1;
background: rgb(206, 201, 201);
}
.HolyGrail-nav,
.HolyGrail-ads {
/* 两个边栏的宽度设为12em,定宽 */
flex: 0 0 12em;
}
.HolyGrail-nav {
/* 导航放到最左边 */
order: -1;
background: rgba(95, 179, 235, 0.972);
}
.HolyGrail-ads {
background: rgb(231, 105, 2);
}
/*如果是小屏幕,躯干的三栏自动变为垂直叠加。*/
@media (max-width: 768px) {
.HolyGrail-body {
flex-direction: column;
flex: 1;
}
.HolyGrail-nav,
.HolyGrail-ads,
.HolyGrail-content {
flex: auto;
}
}
布局理解
①首先是HolyGrail ,给整个body设置flex布局方式,同时设置属性flex-direction: column使得头部(header),躯干(body),尾部(footer)从上到下纵向显示
②对于header和footer,给一个固定的高度
③对于HolyGrail-body(躯干部分),整体设置为flex布局方式
④对于主栏,可以伸缩
⑤对于导航栏和副栏,定宽
flex:1的奥秘
想必看了阮老师的教程都发现在圣杯布局的示例中他用了flex:1写法,但是在他的教程中并没有对其阐述,博主当时也是比较纳闷,所以便去查阅了很多资料,但是网上很多博文水平参差不齐,出入很大,最终还是回到了MDN去查官方的文档。
请看下面MDN官方文档:
由MDN文档可知,设置 flex:1相当于flex:1 1 0,浏览器会按照flex:1 1 0的写法来渲染样式。
flex属性的前两个参数分别是flex-grow属性和flex-shrink属性,均设置为1,即表示该项目可以放大和缩小即可以伸缩。
那么flex属性的第三个参数设置为0又表示什么呢?
flex属性的第三个参数是flex-basis属性
flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
auto 表示项目本身的大小, 如果设置为 auto, 那么盒子就会按照自己内容的多少来等比例的放大和缩小,
那我们如果设置为0, 那么他就不会按项目本身来计算, 所以它不关心内容, 只是把空间等比收缩和放大
上图是MDN的官方实例,注意Chrome浏览器会自动在0后面添加一个px像素单位,用其他浏览器打开可能会发现后面添加的是%,这些都是浏览器自动添加的后缀不会产生其他影响。
注:
①两个边栏的宽度设为12em,em是一个相对单位,是当前元素相对于父元素字体的大小而言的,在不设置字体大小的情况下,浏览器默认字体大小为16px,此时1em=16px,所以12em相当于192px
②CSS3新属性之min-height: 100vh;
vh: 相对于视窗的高度, 视窗被均分为100单位的vh;
vw: 相对于视窗的宽度, 视窗被均分为100单位的vw;
所以给body设置min-height: 100vh可以使所有盒子撑满整个屏幕。
写在最后
当网上的文章过于纷杂,乱花渐欲迷人眼的时候,去看一些权威的文档、源码才是正确的选择,这样才能保持一个清醒的头脑和清晰的认知。
MDN Web 文档