CSS布局知识汇总:
CSS布局是前端开发的基础,以下是对布局知识的系统学习和汇总。
1. 正常文档流(Normal Flow)
在正常的文档流中,写作模式是水平方向,正常流会垂直地一个接一个排列页面的块级元素;若写作模式是垂直方向,正常流会将块级元素水平排列。
- 正常文档流的用处
在定义的CSS加载失败,或者是浏览器不支持新特性,在正常文档流的支撑下,页面会保持可阅读的状态下。
- 脱离正常文档流
脱离正常文档流,不按照正常文档流的结构显示。
2. 浮动
脱离文档流的例子,为元素设置float属性,值有left、right,默认值为none。
当设置了某个元素浮动,文字会环绕浮动元素。如果要设置浮动元素与环绕文字之间的距离,需要设置浮动元素的margin属性值。
body{
padding: 20px;
font: 1em Helvetica Neue,Helvetica,Arial,sans-serif;
}
p{
margin:0 0 1em 0;
}
.p1{
background-color: red
}
.container{
width:500px;
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
}
.item{
width: 100px;
height: 100px;
float:left;
margin: 20px 20px 20px 20px;
background-color: blue
}
</style>
</head>
<body>
<div class="container">
<div class="item"></div>
<p class="p1">Pea horseradish azuki bean lettuce avocado asparagus okra. Kohlrabi radish okra azuki bean corn fava bean mustard tigernut jícama green bean celtuce. </p>
<p>Grape silver beet collard greens avocado quandong fennel gumbo black-eyed pea watercress potato tigernut corn groundnut. Chickweed okra pea winter purslane coriander yarrow sweet pepper radish garlic brussels sprout groundnut summer purslane earthnut pea tomato spring onion azuki bean gourd. Gumbo kakadu plum komatsuna black-eyed pea green bean zucchini gourd winter purslane silver beet rock melon radish asparagus spinach.</p>
</div>
</body>
2.清除浮动
对元素使用了浮动,接下来的元素会环绕它,直到元素开始应用正常文档流。避免这种情况,则需要清除浮动,添加clear属性即可。
.container::after{
content: "",attr();
display: table;
clear:both;
}
2.2 块级格式化上下文(Block Formatting Context )
清除浮动的另一个方法是在容器内创建BFC。一个BFC完全包裹住了它的内部元素,包括内部的浮动元素,保证浮动元素不超过其底部。为元素设置visible(默认)之外的overflow属性。
.container{
Overflow:auto;
}
此种方法大部分情况下是有效的,但是会带来阴影或非预期的滚动条。使用display:flow-root,可以清除浮动,并且可以避免BFC的负面影响。
.container{
Display: flow-root;
}
2.3 float遗留作用:创建多栏布局
3. 定位(position)
处于正常文档流中,position的属性值为static。通过改变position的属性值,设置一些偏移量来是元素相对于参照点一定的距离。
3.1 相对定位(relative positioning)
元素具有属性position: relative, 偏移的参照为原先其正常文档流中的位置。可以使用top、bottom、left、right属性来设置相对于正常文档流位置进行移动。
.item{
position: relative;
Bottom: 50px;
}
页面上的元素不会因为该位置变化而受到影响,该元素处于正常文档流中的位置会被保留,因此需要手动处理元素内容覆盖的情况。
3.4 绝对定位(absolute positioning)
元素设置position: absolute属性可以将其在正常流中移除。该元素原本占据的空间也会被移除。元素的定位会相对于视口容器,除非某个祖先元素也是定位元素(position的值不为static)。
元素设置了position: absolute,元素会定位在视口的左上角,可以通过left、right、bottom、top偏移量属性将元素移动到想要的位置。
通常情况下,绝对定位不用来相对于视口的定位,而是相对于容器,则此时该为容器设置position属性值除static以外的值。
.container{
position: relative;
}
.item{
position: absolute;
}
3.5 固定定位(fixed positioning)
大多数情况下,position: fixed 会相对于视口定位,并且会从正常文档流中被删除,不保留它所占据的空间。页面滚动时,固定的元素会留在相对于视口的位置,而其他正常流中的内容正常滚动。
当想要一个固定导航栏一直停留在屏幕上时非常有效。会造成一些元素被遮挡,需要小心保证页面内容的可读而不被固定元素遮挡。
.container{
Position: relative;
}
.item{
position: fixed
top: 20px;
left: 20px;
}
如果不让固定元素不相对于视口进行定位,要为容器元素设置transform、perspective、filter三个属性之一(不为默认值none)。这样固定元素就会相对于该块级元素偏移,而非视口。
3.4 STICKY定位
设置position: sticky属性让元素在页面滚动时如同在正常流,但当其滚动到相对于视口的某个特定位置时就会固定在屏幕上,如同fixed一般。
用此可以实现导航栏随着页面滚动,而当导航栏滚动到页面顶部时则会固定在顶部位置。
.cocntainer{
Position: relative;
}
.item{
Position: sticky;
Top: 0
Width: 100%;
}
4. 弹性布局(Flex Layout)
弹性布局是为一种一维布局而设计的方法,内容按照行或者列来布局的。容器的直接子元素会变为弹性项,并按照行来排列。
在容器设置如下:
<style type="text/css">
body {
padding: 20px;
font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}
*{
box-sizing: border-box;
}
p {
margin: 0 0 1em 0;
}
.container {
width: 500px;
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
display: flex;
}
.item {
width: 100px;
height: 100px;
padding: 10px;
margin-left: 5px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
</style>
</head>
<body>
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">2</div>
</div>
</body>
4.1 弹性盒子的轴(axes)
弹性盒子中的弹性项默认排列轴是按行排列,即flex-direction: row是从左往右行排列,而flex-direction: row-reverse是从右往左行排列; 在弹性盒子中设置flex-direction: column是从上往下竖排列,flex-direction: column-reverse是从下往上竖排列。 弹性项则按照块级元素排列方向排列。
交叉轴,row的交叉轴是column; column的交叉轴是row.
具体操作只需要设置容器如下:
.container{
flex-direction: flex;
}
盒子里的弹性项就会按照块级元素排列。
也可以通过order属性来改变弹性项的顺序,但会影响通过键盘访问网站的用户带来麻烦,因为tab的顺序是页面内元素在源码中的顺序而非显示顺序。
弹性盒子容器的属性:
以上讲过的flex-direction.
flex-wrap: 决定的是如果一条轴线排不下,如何换行。
flex-wrap: nowrap|wrap|wrap-reverse. nowrap: 不换行; wrap: 换行,第一行在上方;wrap-reverse: 换行,第一行在下方。
flex-flow: 是flex-direction和flex-wrap的简写形式,默认值为 row nowrap
justify-content: 定义了项目在主轴上的对齐方式,有以下四个值:
flex-start(默认值):左对齐
flex-end: 右对齐
center: 居中
space-between: 两端对齐,项目之间的间隔相等。
space-around; 每个项目的两侧相等,项目之间的间隔比项目与边框的间隔大一倍。
align-items: 定义了在交叉轴上的对齐方式。
flex-start: 交叉轴的起点对齐
flex-end: 交叉轴的终点对齐
center: 交叉轴的中点对齐
baseline: 项目的第一行的文字基线对齐
stretch(默认值): 如果项目没设置高度或者auto,将占满整个容器的高度。
align-content: 属性定义了多根轴线的对齐方式,如果只有一个轴线,则属性不起作用。
flex-start: 与交叉轴的起点对齐
flex-end: 与交叉轴的终点对齐
center: 与交叉轴的中点对齐
space-between: 与交叉轴的两端对齐,轴线之间的间隔均匀分布
around-between: 每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。
Stretch(默认值): 轴线占满整个交叉轴。
项目的属性:
flex属性用来控制弹性项在主轴上空间大小的。属性有:flex-grow默认知为0、flex-shrink默认值为1、flex-basis默认值为0,这三个属性的简写方式是flex。例如flex: 1 1 200px
flex-basis会为弹性项设置未拉伸和压缩时的初始大小,以上弹性项的初始大小为200px;当空间不会正好分配给各个弹性项,会有空间不足或空间剩余,flex-grow在空间有多余的时候,允许弹性项均分多余空间,值是任意的正数;flex-shrink在空间不足的时候,允许溢出的弹性项等比例收缩适应容器的大小,值可以是任意正数。
具体设置如下:
.container{ display:flex;}
.item{ flex: 1 1 0;}
.container :first-child{ flex: 2 1 0;}
order: 定义项目的排列顺序,数值越小,排列越靠前,默认值为0.
align-self: 允许单个项目有与其他项目不一样的对齐方式,可覆盖容器的align-items属性。默认值为auto,表示继承容器的对齐方式,其他的值与align-items的属性值一样。
5.网格布局
网格布局需要设置display: grid,使用 grid-template-columns和grid-template-rows属性来控制网格中的列与行。
fr是一种弹性单位,它可以指定容器内的空间被如何划分,使得网格的列可以自适应。使用grid-gap来保证元素间的间距。
.container{
width: 500px;
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 20px;
}
.container>div{
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
</style>
<body>
<div class="container">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5 <br> has more content</div>
</div>
</body>
5.1 网格的术语
网格系统的轴:inline axis :页面中文字排列的方向;block axis页面中块级元素的排列方向。
display属性被设置为grid的元素就为网格容器,网格容器中会有网格线(grid line),是grid-template-columns和grid-template-rows划分形成的。网格中最小的单位为网格单元格(grid cell)。
5.2 网格的自动排列规则
一旦你创建了网格,那么网格容器的直接子元素就会开始将它们自己一个一个地放置在网格的单元格中。子元素的放置是依据网格的自动排列规则(auto-placement rule)。这些规则确保了网格内元素是被安排在各个空的单元格中,而不会彼此遮盖。
网格中任何没有被进行定位的直接子元素都会根据自动排列规则进行放置。
行列的基本定位法:
.item{
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 3;
}
这些属性可以缩写表示:grid-column和grid-row,第一个值代表起始值,第二个值代表结束值。
.item{
grid-column: 1/3;
grid-row: 1/3;
}
可以让网格项同时占据同一个单元格,完成内容间覆盖的设计。可以使用z-index来设置顺序。
.one{
grid-column: 1/4;
grid-row: 1;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
.two{
grid-column: 1/3;
grid-row: 2;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
.three{
grid-column: 2/4;
grid-row: 2/5;
background-color: rgba(193,225,237,.3);
border: 2px solid rgba(193,225,237,.5);
}
.four{
grid-column: 1;
grid-row: 4;
background-color: rgba(193,225,237,.3);
border: 2px solid rgba(193,225,237,.5);
}
.five{
grid-column: 3;
grid-row: 4/5;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
5.3 通过命名区域来定位元素
需要给每个元素一个名字,然后通过grid-template-areas属性的值来描述布局方式。使用grid-area来命名元素,gird-template-areas来应用命名好的元素,填充已经定格好的布局,如果填充不满,就使“.”代替。
.container{
width: 500px;
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-auto-rows: minmax(50px,auto);
grid-gap: 20px;
grid-template-areas: "a a a""b c c"". . d""e e d";
}
.container>div{
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
.one{
grid-area: a;
}
.two{
grid-area: b;
}
.three{
grid-area: c;
}
.four{
grid-area: d;
}
.five{
grid-area: e;
}
6. 盒子模型的生成
Display:none元素不展示,并且不会保留它占有的空间。
元素应用display:content,元素自身的盒子不生成但所有的子元素照常生成。如果你希望一个弹性布局或网格布局中的非直接子元素能应用这些布局,这就会非常有用。
.container{
width: 500px;
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
display: flex;
}
.item{
flex: 1 1 200px;
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
.subitem{
padding: 10px;
background-color: rgba(193,225,237,.3);
border: 2px solid rgba(193,225,237,.5);
}
.container .item:first-child{
display: contents;
}
</style>
<body>
<div class="container">
<div class="item">
<div class="subitem">A</div>
<div class="subitem">B</div>
</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
</body>
7. 对齐
网格和弹性中的对齐布局,align-items和justify-items是相对于align-self和justify-self的一种批量的形式。
align-content和justify-content属性会对网格中的行列进行对齐控制。
.container{
width: 500px;
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
display: grid;
grid-template-columns: 100px 100px 100px;
grid-auto-rows: minmax(100px,auto);
grid-gap: 20px;
align-content: space-between;
justify-content: end;
}
/* .special{
grid-column: 2/4;
align-self: end;
justify-self: end;
} */
.container > div{
padding: 10px;
background-color: rgb(111,41,97,.3);
border: 2px solid rgb(111,41,97,.5);
}
在弹性盒子中,align-items和align-self来解决交叉轴上的对齐问题,justify-content用来解决主轴上的空间分配。
7.1 行/列的间隔
一个多栏布局具有column-gap属性,网格布局具有grid-column-gap、grid-row-gap和grid-gap,这些属性都被从grid标准中删除添加到盒模型中,grid的前缀删除,就是盒模型的属性。
8 多栏布局(多列布局)
使用column-count属性来设置栏数,column-width来设置栏的宽度,容器的足够撑起这三个栏并且有空间剩余,额外空间会被分给这三栏。
无法为单个栏盒子来设置内边距和外边距,column-gap来设置间距,如果没有值,则默认值为1em来防止栏间碰撞。然而在其他布局中的column-gap的默认值为0。
使用column-rule可让你有能力向两栏间添加规则,是column-rule-width、column-rule-color、column-rule-style的简写形式。一个规则自身不会占用任何空间。它会占据在间距的顶部,从而增加或减少那些你设置column-gap的规则与内容间的空间。
.container{
width: 500px;
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
/* column-count: 3; */
column-width: 120px;
column-gap: 20px;
column-rule: 4px dotted #000;
}
使用column-span允许元素横跨多栏,类似通栏。Firefox不支持该属性。
9. 碎片化(Fragmentation)
多栏布局是碎片化(fragmentation)的一个例子,页面内容会被拆分成栏。这和打印时内容被分到不同页非常类似。这个过程是碎片化规范(Fragmentation specification)处理的。这个规范包括了一些帮助控制内容切分的属性。
有一组置于多栏中的卡片,并且你想确保卡片不会被截为两半分到不同的栏,你可以使用break-inside属性的avoid值。考虑浏览器兼容性的因素,你也可能会想使用遗留的page-break-inside属性。
.container {
width: 500px;
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
column-width: 120px;
column-gap: 20px;
column-rule: 4px dotted #000;
}
.container p {
page-break-inside: avoid;
break-inside: avoid;
}