一、基本概念

1、定位(position)

定义一个元素相对于其他正常元素的位置,它应该出现在哪里,这里的其他元素可以是父元素,也可以是浏览器窗口本身。

  1. static:元素框正常生成。块级元素生成一个矩形框,作为文档流的一部分;行内元素则会创建一个或多个行框,置于其父元素中。

  2. relative: 元素框相对于之前正常文档流中的位置发生偏移,并且原先的位置仍然被占据。发生偏移的时候,可能会覆盖其他元素。

  3. absolute:元素框不再占有文档流位置,并且相对于包含块进行偏移(所谓的包含块就是最近一级外层元素position不为static的元素)

  4. fixed:元素框不再占有文档流位置,并且相对于视窗进行定位

  5. sticky:相当于relative和fixed混合。最初会被当作是relative,相对于原来的位置进行偏移;一旦超过一定阀值之后,会被当成fixed定位,相对于视口进行定位。

定位时的偏移量:top | right | bottom | left

  1. static: 偏移量不会对static元素起到作用

  2. relative: 它的偏移是相对于原先在文档流中的位置

  3. absolute: 它的偏移是相对于最近一级position不是static的祖先元素的

  4. fixed: 它的偏移量是相对于视口的

在做自适应布局设计时,往往希望这些偏移量的单位能够使用百分比,或者相对的单位例如rem等。

2、尺寸

当网页中的字体没有给出实际的px或pt的定义时,任意浏览器会给定一个默认值:1em=12pt=16px,对应浏览器中“字体大小”中的“中等”,以这个为标准,变大或缩小。

  • 百分比: 百分比的参照物是父元素,50%相当于父元素width的50%;

  • rem: 这个对于复杂的设计图相当有用,它是相对于 html 的 font-size 的大小,集相对大小和绝对大小的优点于一身,既可以做到只修改根元素就成比例的调整所有字体大小,又可以避免字体大小逐层复合的连锁反应。

    • 需要考虑兼容性,对于IE8-,所有浏览器均已支持rem

    • 对于不支持的浏览器,就是多写一个绝对单位的声明,浏览器会忽略用rem设定的字体大小。如p{font-size:14px;font-size:0.875rem}

  • em: 即%,它虽然也是一个相对的单位,相对于父元素的font-size,结合css继承关系使用

    • 10px = 0.625em,通常为了简化font-size的换算,会在css中设置body的font-size=62.5%,使得16px * 62.5% = 10px 为 1em,也就说只需要将你原来的px数值除以10,然后换上em作为单位即可。

    • 重新计算那些被放大的字体的em数值,避免字体大小的重复声明

      • 避免出现1.2 * 1.2 = 1.44 的现象。比如父元素声明了字体大小为1.2em,那么子元素在声明字体大小时就只能是1em,而不是1.2em,因为此em非彼em,它因为继承了父元素的字体高而使得1em = 12px
  • px: 像素,是屏幕上显示数据的最基本的点,用于网页设计,直观方便。

  • pt: 专用的印刷单位“榜”,大小为1/72英寸,是自然界标准的长度单位,也称为“绝对长度”

3、盒子模型

可以通过box-sizing设置不同的模型。两种盒子模型,主要是width的不同
布局 - 图1

  • 标准:width = content的宽度

  • border-box: width = border + padding + content

  1. width的默认值是auto,这个属性值会使得内部元素的长度自动填充满父元素的width。

  2. height的默认值也是auto,auto表示的是浏览器自动计算。这种自动计算,需要一个基准,一般浏览器都是允许高度滚动的,所以,会导致一个问题——浏览器找不到垂直方向上的基准。

同样地道理也会被应用在margin属性上。相信如果考察居中时,水平居中你可能闭着眼睛都能写出来,但是垂直居中却绕着脑袋想。这是因为如果是块级元素水平居中只要将水平方向上的margin设置成auto就可以了。但是,垂直方向上却没有这么简单,因为你设置成auto时,margin为0。这个问题,还是需要仔细思考一下的。

二、浮动(类似于PS中的图层)

浮动的元素会在浮动层上面进行排布,而在原先文档流中的元素位置,会被以某种方式进行删除,但是还是会影响布局。
浮动元素,其实对于布局来说,是特别危险的。因为你可能这一块做过浮动,但未做清除,那么造成高度塌陷的问题。

  • overflow: 将父元素的overflow,设置成hidden。

  • after伪类:对子元素的after伪类进行设置。

三、flexbox(一维)

flex 布局的限制:http://t.cn/EGMB2Uh
flex 布局讲解: http://www.lulustyle.net/Flex/02flex%E5%B8%83%E5%B1%80.html
http://www.lulustyle.net/Flex/demo.html

四、css grid(二维)

grid-template-columns

按百分比显示,左边 70%,右边 30%。

  1. .wrapper {
  2. display: grid;
  3. grid-template-columns: 70% 30%;
  4. }

不仅是可以左右按比例,可以任意,比如

  1. .wrapper {
  2. display: grid;
  3. grid-template-columns: 40% 30% 30%;
  4. }

除了按百分比,也可以按固定的大小(px)。

  1. .wrapper {
  2. display: grid;
  3. grid-template-columns: 300px 200px 200px;

fr 单位

  1. .wrapper {
  2. display: grid;
  3. grid-template-columns: 1fr 2fr 1fr;
  4. }

repeat()

  1. .wrapper {
  2. display: grid;
  3. grid-template-columns: repeat(4, 1fr);
  4. }

repeat,顾名思义,重复的意思,1fr 重复四次,那就是 1fr 1fr 1fr 1fr。

  1. .wrapper {
  2. display: grid;
  3. grid-template-columns: repeat(4, 1fr 2fr);
  4. }

左边 1 个格子,右边 2 个格子,这样重复 4 次,相当于 1fr 2fr 1fr 2fr 1fr 2fr 1fr 2fr。如果你的标签元素不够,那自然就留为空白了。

网格间距

grid-column-gap:列间距

  1. .wrapper {
  2. display: grid;
  3. grid-template-columns: 1fr 2fr 2fr;
  4. grid-column-gap: 1em;
  5. }

grid-row-gap: 行间距

  1. .wrapper {
  2. display: grid;
  3. grid-template-columns: 1fr 2fr 1fr;
  4. grid-column-gap: 1em;
  5. grid-row-gap: 1em;
  6. }

简写

  1. grid-column-gap: 1em;
  2. grid-row-gap: 1em;
  3. // 等同于
  4. grid-gap: 1em
  5. // 等同于
  6. grid-gap: 1em 2em; //第一个参数是行间距,第二个参数是列间距。

grid-auto-rows(网格高度)

  1. .wrapper {
  2. display: grid;
  3. grid-template-columns: 1fr 2fr 1fr;
  4. grid-gap: 1em;
  5. grid-auto-rows: 100px;
  6. }

要解决上面的问题,可以使用 minmax() 设置最小的高度。

  1. .wrapper {
  2. display: grid;
  3. grid-template-columns: 1fr 2fr 1fr;
  4. grid-gap: 1em;
  5. grid-auto-rows: minmax(100px, auto);
  6. }

网格排列

justify-items(水平排列)

  1. .wrapper {
  2. display: grid;
  3. grid-template-columns: 1fr 2fr 1fr;
  4. grid-gap: 1em;
  5. grid-auto-rows: minmax(100px, auto);
  6. justify-items: start;
  7. }
  • start:最左边排列。
  • center:中间排列。
  • end:最右边排列。
  • stretch:默认情况。

align-items(垂直排列)

  1. .wrapper {
  2. display: grid;
  3. grid-template-columns: 1fr 2fr 1fr;
  4. grid-gap: 1em;
  5. grid-auto-rows: minmax(100px, auto);
  6. justify-items: stretch;
  7. align-items: start;
  8. }

针对某个特定的网格进行排列

使用 justify-self 和 align-self

  1. .wrapper {
  2. display: grid;
  3. grid-template-columns: 1fr 2fr 1fr;
  4. grid-gap: 1em;
  5. grid-auto-rows: minmax(100px, auto);
  6. justify-items: stretch;
  7. align-items: stretch;
  8. }
  9. .box1 {
  10. align-self: start;
  11. }
  12. .box2 {
  13. justify-self: start;
  14. }

网格空间大小和位置

grid-template-columns 是控制了所有的网格盒子的分布比率,如果要控制单个网格盒子的网格水平水向和垂直方向的大小,分别要使用 grid-column 和 grid-row。

这两个指令要用起来,主要是靠自己的理解和对它慢慢地调节,不断地总结经验。

  1. .box1 {
  2. grid-column: 1/3;
  3. }
  4. .box2 {
  5. }

这个 1/3 表示的是 1 到 3,第一到第三个网格,我们还是来看下效果。

五、布局实现方案

单列布局

布局 - 图2
常见的单列布局有两种:

  • 一种是header、content、footer宽度都相同,其一般不会占满浏览器的最宽宽度,但当浏览器宽度缩小低于其最大宽度时,宽度会自适应。
  1. <div class="layout">
  2. <div id="header">头部</div>
  3. <div id="content">内容</div>
  4. <div id="footer">尾部</div>
  5. </div>
  1. .layout{
  2. /* width: 960px; *//*设置width当浏览器窗口宽度小于960px时,单列布局不会自适应。*/
  3. max-width: 960px;
  4. margin: 0 auto;
  5. }
  • 一种是header、footer宽度为浏览器宽度,但content以及header和footer里的内容却不会占满浏览器宽度。
  1. <div id="header">
  2. <div class="layout">头部</div>
  3. </div>
  4. <div id="content" class="layout">内容</div>
  5. <div id="footer">
  6. <div class="layout">尾部</div>
  7. </div>
  1. .layout{
  2. /* width: 960px; *//*设置width当浏览器窗口宽度小于960px时,单列布局不会自适应。*/
  3. max-width: 960px;
  4. margin: 0 auto;
  5. }

两栏布局

一栏定宽,一栏自适应。这样子做的好处是定宽的那一栏可以做广告,自适应的可以作为内容主体。

实现方式:
1、float + margin

  1. <body>
  2. <div class="left">定宽</div>
  3. <div class="right">自适应</div>
  4. </body>
  1. .left{
  2. width: 200px;
  3. height: 600px;
  4. background: red;
  5. float: left;
  6. display: table;
  7. text-align: center;
  8. line-height: 600px;
  9. color: #fff;
  10. }
  11. .right{
  12. margin-left: 210px;
  13. height: 600px;
  14. background: yellow;
  15. text-align: center;
  16. line-height: 600px;
  17. }

2、position+margin:参考三栏布局第二种方法

三栏布局

两边定宽,然后中间的width是auto的,可以自适应内容,再加上margin边距,来进行设定。

1.float+margin:使用左右两栏使用float属性,中间栏使用margin属性进行撑开,注意的是html的结果
缺点是:(1)当宽度小于左右两边宽度之和时,右侧栏会被挤下去;(2)html的结构不正确

  1. <div class="left">左栏</div>
  2. <div class="right">右栏</div>
  3. <div class="middle">中间栏</div>
  1. .left{
  2. width: 200px;
  3. height: 300px;
  4. background: yellow;
  5. float: left;
  6. }
  7. .right{
  8. width: 150px;
  9. height: 300px;
  10. background: green;
  11. float: right;
  12. }
  13. .middle{
  14. height: 300px;
  15. background: red;
  16. margin-left: 220px;
  17. margin-right: 160px;
  18. }

2.position+margin:使用position定位实现,即左右两栏使用position进行定位,中间栏使用margin进行定位

好处是:html结构正常。
缺点时:当父元素有内外边距时,会导致中间栏的位置出现偏差

  1. <div class="left">左栏</div>
  2. <div class="middle">中间栏</div>
  3. <div class="right">右栏</div>
  1. .left{
  2. background: yellow;
  3. width: 200px;
  4. height: 300px;
  5. position: absolute;
  6. top: 0;
  7. left: 0;
  8. }
  9. .middle{
  10. height: 300px;
  11. margin: 0 220px;
  12. background: red;
  13. }
  14. .right{
  15. height: 300px;
  16. width: 200px;
  17. position: absolute;
  18. top: 0;
  19. right: 0;
  20. background: green;
  21. }

3、使用float和BFC配合圣杯布局(float + 负margin + padding + position)

将middle的宽度设置为100%,然后将其float设置为left,其中的main块设置margin属性,然后左边栏设置float为left,之后设置margin为-100%,右栏也设置为float:left,之后margin-left为自身大小。
缺点是:1. 结构不正确 2. 多了一层标签

  1. <div class="wrapper">
  2. <div class="middle">
  3. <div class="main">中间</div>
  4. </div>
  5. <div class="left">
  6. 左栏
  7. </div>
  8. <div class="right">
  9. 右栏
  10. </div>
  11. </div>
  1. .wrapper{
  2. overflow: hidden; // 清除浮动
  3. }
  4. .middle{
  5. width: 100%;
  6. float: left;
  7. }
  8. .middle .main{
  9. margin: 0 220px;
  10. background: red;
  11. }
  12. .left{
  13. width: 200px;
  14. height: 300px;
  15. float: left;
  16. background: green;
  17. margin-left: -100%;
  18. }
  19. .right{
  20. width: 200px;
  21. height: 300px;
  22. float: left;
  23. background: yellow;
  24. margin-left: -200px;
  25. }

4、flex布局

除了兼容性,一般没有太大的缺陷

  1. <div class="wrapper">
  2. <div class="left">左栏</div>
  3. <div class="middle">中间</div>
  4. <div class="right">右栏</div>
  5. </div>
  1. .wrapper{
  2. display: flex;
  3. }
  4. .left{
  5. width: 200px;
  6. height: 300px;
  7. background: green;
  8. }
  9. .middle{
  10. width: 100%;
  11. background: red;
  12. marign: 0 20px;
  13. }
  14. .right{
  15. width: 200px;
  16. height: 3000px;
  17. background: yellow;
  18. }

移动端

媒体查询

媒体查询的主要原理:给整个 css 样式设置了断点,通过给定的条件去判断,在不同的条件下,显示不同的样式。

@media:

  • all, 所有媒体
  • braille 盲文触觉设备
  • embossed 盲文打印机
  • print 手持设备
  • projection 打印预览
  • screen 彩屏设备
  • speech ‘听觉’类似的媒体类型
  • tty 不适用像素的设备
  • tv 电视

例如:手机端的尺寸在750px,而PC端则是大于750px的

  1. @media screen and (min-width: 750px){
  2. .media{
  3. height: 100px;
  4. background: red;
  5. }
  6. }
  7. @media (max-width: 750px){
  8. .media{
  9. height: 200px;
  10. background: green;
  11. }
  12. }
  1. @media screen {
  2. p.test {font-family:verdana,sans-serif;font-size:14px;}
  3. }
  4. @media print {
  5. p.test {font-family:times,serif;font-size:10px;}
  6. }
  7. @media screen,print {
  8. p.test {font-weight:bold;}
  9. }
  10. /*移动端样式*/
  11. @media only screen and (min-device-width : 320px) and (max-device-width : 480px) {
  12. /* Styles */
  13. }

flex 弹性盒子

移动端会经常使用到flex布局,因为在简单的页面适配方面,flex可以起到很好的拉伸的效果。往往你并不需要去反复的使用媒体查询的。整整的响应式布局是使界面能够自动的根据屏幕进行变化,做到完美的弹性布局,在必要的时候,去使用媒体查询,对页面进行调整。

(1)容器:设定 display:flex 的地方
布局 - 图3
(2)项目:容器内部的直接子项就是flex item
布局 - 图4
(3)轴线(axis):如坐标系,具备着x轴与y轴,flex在整个布局当中,也可分为水平方向和垂直方向,简称为主轴和交叉轴

  • main start: 项目到容器的开始位置

  • main end: 项目到容器结束的位置

  • cross start: 交叉轴上面的开始位置

  • cross end: 交叉轴上面的结束位置

  • main size:项目的水平距离

  • cross size:项目的垂直距离

布局 - 图5

(4)容器的基本属性

  • (a) display:表示容器展示的布局类型,可设定为flex和inline-flex。两者的设定也就是inline和block的区别。当然了,在webkit内核的浏览器(safari)中使用时,需要在其前面加上前缀(-webkit-flex)
  1. .container{
  2. display: -webkit-flex;
  3. display: flex; /* or inline-flex*/
  4. }
  • (b) flex-direction: 表示容器内部子项目的展示方向。row | row-reverse | column | column-reverse
  1. .container{
  2. flex-direction: row /* 默认 行正序*/ || row-reverse /*行倒序*/ || column /* 列正序*/ || column-reverse /*列倒序*/
  3. }

布局 - 图6

  • (c) flex-wrap: 表示当容器内部内容超出容器时,容器是否分行展示

    • nowrap(浏览器默认,不分行)

    • wrap(超出的部分分行处理)

    • wrap-reverse(分行逆序)

  1. .container{
  2. flex-wrap: nowrap || wrap || wrap-reverse;
  3. }

布局 - 图7

  • (d) flex-flow: 这个属性就是可以将上面两个属性合起来写的属性,
  1. .container {
  2. flex-flow: row wrap;
  3. }
  • (e) justify-content: 表示容器内部的子项目的水平对齐方式。而水平的对齐方式主要有六种:

    • flex-start: 对应的对齐方式是水平向左对齐。(浏览器默认)

    • flex-end: 对应的对齐方式是水平向右对齐。

    • center: 对应的对齐方式是居中对齐。

    • space-between: 对应的是,每个元素之间中间流出间隙是一样的,两边无间隙。

    • space-around: 对应的是,每个元素周围的间隙是一样的,而不是元素之间的,因此,可以从图中看出两边的间隙会比中间小一半。

    • space-evenly:对应的是,每个元素之间的间隙大小一致。

布局 - 图8

  1. justify-content: flex-start || flex-end || center || space-between || space-around || space-evenly
  • (f) align-items:表示容器内部的子项目的垂直对齐方式。而垂直的对齐方式主要有五种:

    • flex-start: 对应的对齐方式是垂直向上对齐。

    • flex-end: 对应的对齐方式是垂直向下对齐。

    • center:对应的对齐方式是垂直居中对齐。

    • stretch:对应的对齐方式是将整个子项目的长度拉伸到最大块的高度(浏览器默认)

    • baseline: 对应的对齐方式是子项目内部的文字基线对齐。

  1. .container{
  2. align-items: flex-start || flex-end || center || stretch || baseline;
  3. }

布局 - 图9

  • (g) align-content: 表示在对行的情况下,每行所对应的垂直方向上的对齐方式。主要有六种对齐方式:
  • flex-start:对应的是每一行在垂直方向上向上对齐的方式

  • flex-end:对应的是每一行在垂直方向上向下对齐的方式

  • center:对应的是每一行在垂直方向上居中对齐的方式

  • stretch:对应的是每一行延展到铺满整个垂直方向。

  • space-between:对应的就是每行之间留有空隙,而两边没有空隙

  • space-around:对应的就是每行周围的空隙均相等

布局 - 图10
(5) 项目的属性

  • (a)order:子项目的排列顺序。通常,默认情况下,子项目都是按照默认顺序进行排序的。但是,有时候你或许需要将后面的元素拿上来,那你就可以使用order这个属性,正如图中展示的:
  1. order: <integer> //如1

布局 - 图11

  • (b) flex-grow: 表示的是元素的所占空间的比例.在设置每个元素flex-grow为1时,一行内的子元素都是均分的,即1:1:1。但是,如果你给第一个元素设置flex-grow为2时,它们的比例就会变成2:1:1。如图:
  1. flex-grow: <integer> /默认为0/

布局 - 图12

  • (c) flex-shrink: 表示子项目的伸缩
  1. flex-shrink: number /*default to 1*/
  • (d) flex-basis: 表示子项目的长度,默认为auto。当设置flex-grow时,长度就为flex-grow的value,如果没有,就是块本身内容的大小。
  1. flex-basis:<length> | auto /*default auto*/
  • (e) flex: flex-grow、flex-shrink和flex-basis的集合写法,默认为0,1,auto
  1. flex: <flex-grow> <flex-shrink> <flex-basis>
  • (f) align-self: 表示子项目在垂直轴线上的放置方式。
  1. align-self: auto | flex-start | flex-end | center | stretch | baseline

rem适配

rem 可以说是移动端适配的一个神器。
这种界面有个特点就是页面元素的复杂度比较高,而使用 flex 进行布局会导致页面被拉伸,但是上下的高度却没有变化等问题。
从网易与淘宝的font-size思考前端设计稿与工作流