布局
盒模型宽度计算
盒模型宽度计算
offsetWidth = (内容宽度+内边距+边框),无外边距;
margin 纵向重叠问题
margin 纵向重叠问题
相邻元素的 margin-top 和 margin-bottom 会发生重叠,已最大值优先;
空白内容的<p></p>
也会重叠;
margin 负值问题
margin 负值问题
margin-top 和 margin-left 负值,元素向上、向左移动;
margin-right 负值,右侧元素左移,自身不受影响;
margin-bottom 负值,下方元素上移,自身不受影响;
BFC理解与应用
BFC理解与应用
理解
Block format context,块级格式化上下文;
一块独立渲染区域,内部元素的渲染不会影响边界以外的元素;
应用
清除浮动;
重排和重绘
重排和重绘
重排(Reflow)
当涉及到DOM节点的布局属性发生变化时,就会重新计算该属性,浏览器会重新描绘相应的元素,
此过程叫 回流(Reflow)。
重绘(Repaint)
当影响DOM元素可见性的属性发生变化 (如 color) 时, 浏览器会重新描绘相应的元素,
此过程称为 重绘(Repaint)。因此重排必然会引起重绘。
引起Repaint和Reflow的一些操作
1. 调整窗口大小
2. 字体大小
3. 样式表变动
4. 元素内容变化,尤其是输入控件
5. CSS伪类激活,在用户交互过程中发生
6. DOM操作,DOM元素增删、修改
7. width, clientWidth, scrollTop等布局宽高的计算
这些引起回流的操作中,6和7是和JavaScript相关的,所以开发人员应该注意2点:
避免大量的DOM操作
避免过多DOM布局属性的计算
注:display:none 会触发 reflow,而 visibility:hidden 只会触发 repaint,因为没有发生位置变化。
如何避免过多的Repaint和Reflow?
var s = document.body.style;
s.padding = "2px"; // 回流+重绘
s.border = "1px solid red"; // 再一次 回流+重绘
s.color = "blue"; // 再一次重绘
s.backgroundColor = "#ccc"; // 再一次 重绘
s.fontSize = "14px"; // 再一次 回流+重绘
// 添加node,再一次 回流+重绘
document.body.appendChild(document.createTextNode('abc!'));
Repaint和Reflow是不可避免的,只能说对性能的影响减到最小,给出下面几条建议:
1. 避免逐条更改样式。建议集中修改样式,例如操作className。
2. 避免频繁操作DOM。创建一个documentFragment或div,在它上面应用所有DOM操作,最后添加到文档里。设置display:none的元素上操作,最后显示出来。
3. 避免频繁读取元素几何属性(例如scrollTop)。
4. 绝对定位具有复杂动画的元素。绝对定位使它脱离文档流,避免引起父元素及后续元素大量的回流
示例
如何实现圣杯布局和双飞翼布局
目的:
三栏布局,中间一栏最先加载和渲染(内容最重要);
两侧内容固定,中间内容随着宽度自适应;
一般用于PC网页;
技术总结:
使用float布局;
两侧使用margin负值,以便和中间内容横向重叠;
防止中间内容被两侧覆盖,一个用padding一个用margin;
手写clearfix
.clearfix:after {
content: '';
display: table;
clear: both;
}
.clearfix {
*zoom: 1; /* 兼容 IE 低版本 */
}
flex 实现一个三点的色子
/* flex 画三个点的骰子 */
.box {
display: flex;
justify-content: space-between;
}
.item {
/* 背景色,大小,边框 */
}
.item:nth-child(2) {
align-self: center; /* 第二项居中对齐 */
}
.item:nth-child(3) {
align-self: flex-end; /* 第三项尾对齐 */
}
实现水平垂直居中
- absolute元素: top, left, bottom, right = 0 + margin: auto;
.child1 {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}
- absolute元素: top, left = 50% + translate(-50%, -50%);
.child2 {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
- flex父元素: justify-content: center; + align-items: center;
.box3 {
display: flex;
justify-content: center;
align-items: center;
}