Css布局的一些常见问题
em和rem的区别
1em,等于本元素的字体大小,所以在不同的元素里1em的绝对大小是不一样的。 而1rem,等于根元素的字体大小,在一个页面中,无论在哪个元素上1rem都是一样的。 em 适合于用在需要大小需要跟随字体变化的属性上,比如padding、margin、height、width等等,元素继承了不同的字体大小,这些属性最好也能跟着变化;
当使用 rem 单位,他们转化为像素大小取决于页根元素的字体大小,即 html 元素的字体大小。 根元素字体大小乘以你 rem值。
例如,根元素的字体大小 16px,10rem 将等同于 160px,即 10 x 16 = 160。
CSS设置padding为10rem
浏览器解析出来的值为160px
em 单位如何转换为像素值
当使用em单位时,像素值将是em值乘以使用em单位的元素的字体大小。
例如,如果一个 div 有 18px 字体大小,10em 将等同于 180px,即 10 × 18 = 180。
CSS设置padding为10em
<style>
div{
font-size: 18px;
}
.q{
font-size: 1em;
}
.w{
font-size: 1rem;
}
</style>
</head>
<body>
<div>
<!--浏览器默认的字体大小为16px-->
<p class="q">132</p><!--大小为1x18-->
<p class="w">132</p><!--大小为1x16-->
</div>
Css的多栏布局实现
- 利用浮动,将设置的盒子全部向一个方向浮动形成多栏布局
- 利用父相子绝定位布局的方式,最左边的设置absolute
圣杯布局和双飞翼布局
圣杯布局
圣杯布局就是左右两边固定宽度,中间自适应宽度的三栏式布局
header和footer固定高度,left和right固定高度,中间宽度自适应
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>css</title>
</head>
<style type="text/css">
body{
min-width: 550px;
}
*{
margin:0;
padding: 0;
}
.header , .footer{
background: gray;
width: 100%;
}
.footer{
clear: both;
}
.main{
height: 200px;
padding: 0 150px 0 200px;
background: greenyellow;
*zoom: 1;
}
.left , .center , .right{
float: left;
}
.center{
width: 100%;
height: 200px;
background: red;
}
.left {
width: 200px;
height: 200px;
background: yellow;
margin-left: -100%;
position: relative;
left: -200px;
}
.right{
width: 150px;
height: 200px;
background: gainsboro;
margin-left: -150px;
position: relative;
left: 150px;
}
</style>
<body>
<div class="header">
头部
</div>
<div class="main">
<div class="center">中间中间中间中间中间中间中间后</div>
<div class="left">左边</div>
<div class="right">右边</div>
</div>
<div class="footer">
底部
</div>
</body>
</html>
双飞翼布局
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>css</title>
</head>
<style type="text/css">
*{
margin:0;
padding: 0;
}
.main>div{
float: left;
}
.left {
width: 200px;
background: red;
margin-left: -100%;
}
.right{
width: 200px;
background: blue;
margin-left: -200px;
}
.middle{
width: 100%;
background: yellow;
}
.content{
margin-left: 200px;
margin-right: 200px;
}
</style>
<body>
<div class="main">
<div class="middle">
<div class="content">
中间
</div>
</div>
<div class="left">
左边
</div>
<div class="right">
右边
</div>
</div>
</body>
</html>
两者的区别在于,双飞翼是将中间三个部分的元素放在了一个div中,然后在中间div中设置marginleft和right
圣杯布局是在父元素上设置了padding-left和padding-right,在给左右两边的内容设置position为relative
link与import的区别
1,link是XHTML标签,除了可以加载css外还可以加载rss等一些其他事务,而这个@import属于css范畴,只能加载css。
2,link在页面加载的时候他就可以加载css文件,而@import必须等到页面加载完成后才可以加载css。
3,link是XHTML标签,没有任何兼容问题,而@import是在css2.1之后提出的,所以可能存在兼容问题。
4,link支持JavaScript操作dom方式去改变样式,而@import则不支持
重绘和回流
重绘是当节点需要更改外观而不会影响布局的,例如更改颜色
回流是布局或者几何属性改变时即对布局发生了改变,需要重新计算渲染的
例如:
1、页面渲染初始化;(无法避免)
2、添加或删除可见的DOM元素;
3、元素位置的改变,或者使用动画;
4、元素尺寸的改变——大小,外边距,边框;
5、浏览器窗口尺寸的变化(resize事件发生时);
6、填充内容的改变,比如文本的改变或图片大小改变而引起的计算值宽度和高度的改变;
7、读取某些元素属性:(offsetLeft/Top/Height/Width, clientTop/Left/Width/Height, scrollTop/Left/Width/Height, width/height, getComputedStyle(), currentStyle(IE) )
回流必定会重绘,重绘不一定会回流
减少重绘和回流的办法
- 使用
transform
替代top
- 使用
visibility
替换display: none
,因为前者只会引起重绘,后者会引发回流(改变了布局 - 避免使用
table
布局,可能很小的一个小改动会造成整个table
的重新布局。 - 尽可能在
DOM
树的最末端改变class
,回流是不可避免的,但可以减少其影响。尽可能在DOM树的最末端改变class,可以限制了回流的范围,使其影响尽可能少的节点。 - 避免设置多层内联样式,CSS 选择符从右往左匹配查找,避免节点层级过多。
- 将动画效果应用到
position
属性为absolute
或fixed
的元素上,避免影响其他元素的布局 - 避免使用
CSS
表达式,可能会引发回流。 - CSS3 硬件加速(GPU加速)
- 避免频繁操作样式,最好一次性重写
style
属性,或者将样式列表定义为class
并一次性更改class
属性。 - 避免频繁操作
DOM
,创建一个documentFragment
,在它上面应用所有DOM操作
,最后再把它添加到文档中。 - 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
margin重叠问题
margin重叠问题有两种
1.兄弟级垂直块
<style>
.o{
width: 200px;
height: 200px;
background-color: aqua;
margin: 20px;
}
.t{
width: 200px;
height: 200px;
background-color: rgb(95, 39, 128);
margin-top: 20px;
}
</style>
</head>
<body>
<div class="o"></div>
<div class="t"></div>
</body>
我们发现,两个div之间的间隔并没有按照我们想的那样叠加(也就是40),实际的间隔只有20px,这就2个元素的margin重叠了,当两个div重叠时,中间的间距会根据margin大的一方来选取
解决办法
给下面的元素添加display:inline-block或者浮动
2.父子级的块之间
<style>
.o{
width: 200px;
height: 200px;
background-color: aqua;
}
.t{
width: 100px;
height: 100px;
background-color: rgb(95, 39, 128);
margin-top: 30px;
}
</style>
</head>
<body>
<div class="o">
<div class="t"></div>
</div>
我们发现给子级元素添加的margin,并没有在它与父级之间产生间距,而是出现在父级元素的margin-top上
解决办法
父级加overflow:hidden或加padding或加border,子级加position:absolute