圣杯布局——针对前端小白篇

css3

浏览数:456

2019-4-15

什么是圣杯布局

三栏的布局结构,左栏和右栏的宽度固定不变,中间栏的宽度自动填充,会跟着父级元素的宽度变化而变化。

如图所示

  • header和footer的宽度填充满整个屏幕
  • 缩小或者拉大屏幕,左栏和右栏的宽度保持不变,中间的宽度随着变小或变大

下面,让我们来实现这个效果

Dom结构

<header id="header">header</header>
    <div id="container">
        <div id="center" class="column">center</div>
        <div id="left" class="column">left</div>
        <div id="right" class="column">right</div>
    </div>
<footer id="footer">footer</footer>

解析:

  • 使用了header和footer这两个HTML5语义化标签,语义化标签有利于seo
  • center块放在left块前面是为了让center块更快加载出来(DOM加载是按顺序加载的)
  • center、left和right使用了相同的class名,是因为它们有一些公共的css样式

CSS样式

第一步

设置好header和footer的宽度是100%,左栏宽度200px,右栏宽度300px,中间栏宽度100%(因为要跟着浏览器的宽度变化)

body {
    width: 100%;
    margin: 0;  //去掉浏览器默认的margin宽度
}

#header,
#footer {
    width: 100%;
    background-color: #ccc;
}

#container {
    width: 100%;
    background-color: yellow;
}

#container .column {
    height: 200px;
}

#left {
    width: 200px;
    background-color: green;
}

#center {
    width: 100%;
    background-color: blue;
}

#right {
    width: 300px;
    background-color: red;
}

实现如下图

第二步

现在要让left块、right块和center块水平排列,处于统一水平线,因此要让它们浮动起来。加上css样式
#container .column { float: left; }


因为center块的宽度是100%,占据了全部的位置,left块和right块只能下移,但是可以看到footer的居然上移了,这是因为container块的三个子元素都浮动(浮动会脱离文档流)了,即使我们给了三个子元素的height为200px,container的height为0,footer就会上移。

这里清除浮动的办法有三,

1、设置contaniner的高度;

2、footer的样式加上clear:both,可以清除其他元素浮动对它的影响;

3、利用伪元素清除浮动

#container:after {
    display: block;
    content: '';
    width: 100%;
    height:0;
    clear: both;
}

实现如图

第三步

设置container的padding-left等于left块的宽度,padding-right为right块的宽度
加上样式

#container {
    padding-left: 200px;
    padding-right: 300px;
    box-sizing: border-box;
}

解析:
盒子模型有两种,w3c标准的盒子模式和IE怪异盒子,区别在于padding(内边距)和border(边框)是否算在盒子的width和height里。浏览器默认的盒子模型是content-box,即padding和border不算在width里,因为我们的container的width是100%,如果是content-box,则container表现出来的width要大于整个浏览器的宽度,会看到浏览器下方有滚动条,因此我们设置 box-sizing: border-box ,让padding算在width里。

实现如图

第四步

要让left块挪到center块的左边,right块挪到center块的右边
原本center块、left块和right块应该是同一水平线排列,因为container的宽度不够(center块的宽度等于container的宽度)在水平线容纳三块,才把left块和right块挤下来

因此我们加上left块的样式 margin-left: -100%;

盒子的margin的距离是以盒子对应的方向来计算,负值表示按反方向移动。比如marin-left以盒子的左边来算,margin-right以盒子的右边来算

margin的值如果是按百分比计算,那计算的基础是上一层父级的宽度,在这里即是container的width,又因为center块的width和container块一样,这时候left块和center块重叠了,而且left块在center块上面(如果没有设置层级z-index,当然z-index还要配合position使用,统一层级的元素,当有重叠时,后面的元素会盖住前面的元素)

这时候left块还要再向左移动它自身宽度的位置,也就是200px;

#left {
    position: relative;
    right: 200px;
}

解析:
relative对象遵循正常文档流,可以根据top,right,bottom,left等属性在正常文档流中偏移位置。right的距离是根据left块的左边位置来计算。

接下来给right块加上样式 #right { margin-right: -300px;}
表示right块往左移动300px(刚好覆盖在container的padding-right位置)

整个css代码如下:

body {
    width: 100%;
    margin: 0;
}

#header,
#footer {
    width: 100%;
    background-color: #ccc;
}

#container {
    width: 100%;
    padding-left: 200px;
    padding-right: 300px;
    box-sizing: border-box;
    background-color: yellow;
}

#container:after {
    display: block;
    content: '';
    width: 100%;
    height:0;
    clear: both;
}

#container .column {
    height: 200px;
    float: left;
}

#left {
    width: 200px;
    background-color: green;
    margin-left: -100%;
    position: relative;
    right: 200px;
}

#center {
    width: 100%;
    background-color: blue;
}

#right {
    width: 300px;
    background-color: red;
    margin-right: -300px;
}

注意:如果你将浏览器的宽度缩小到一定程度,会发现页面的布局出现错乱,这是因为左栏和右栏的宽度和margin值、container的padding值都是写死的,当浏览器的宽度不足以容纳它们时,就会出现错乱。因为我们在写页面的时候应该响应式布局,即不管浏览器的宽度如何变化,我们展示出来的页面依然是完美的(哈哈有点夸张),当然,这肯定会有一个最小宽度要求(pc端看具体需求,移动端一般是按iphone5的宽度320px)

ps:这是我一次写文档,如有错误的地方麻烦各位大佬指正,感谢!!!