CSS&HTML面经专题——(三)CSS定位/盒模型/经典布局/浮动布局与BFC
CSS&HTML面经专题
一、position定位
position:static | relative | absolute | fixed | center | page | sticky
默认值:static,
center、page、sticky是CSS3中新增加的值。
- static 可以认为静态的,默认元素都是静态的定位,对象遵循常规流。此时4个定位偏移属性不会被应用,也就是使用left,right,bottom,top将不会生效。
- relative 相对定位,对象遵循常规流,并且参照自身在常规流中的位置通过top,right,bottom,left这4个定位偏移属性进行偏移时不会影响常规流中的任何元素。
- absolute a、绝对定位,对象脱离常规流,此时偏移属性参照的是离自身最近的定位祖先元素,如果没有定位的祖先元素,则一直回溯到body元素。盒子的偏移位置不影响常规流中的任何元素,其margin不与其他任何margin折叠。 b、元素定位参考的是离自身最近的定位祖先元素,要满足两个条件,第一个是自己的祖先元素,可以是父元素也可以是父元素的父元素,一直找,如果没有则选择body为对照对象。第二个条件是要求祖先元素必须定位,通俗说就是position的属性值为非static都行。
- fixed 固定定位,与absolute一致,但偏移定位是以窗口为参考。当出现滚动条时,对象不会随着滚动。
- center 与absolute一致,但偏移定位是以定位祖先元素的中心点为参考。盒子在其包含 容器 垂直水平居中。(CSS3) 与absolute一致。元素在分页媒体或者区域块内,元素的包含块始终是初始包含块,否则取决于每个absolute模式。(CSS3)
- sticky 对象在常态时遵循常规流。它就像是relative和fixed的合体,当在屏幕中时按常规流排版,当卷动到屏幕外时则表现如fixed。该属性的表现是现实中你见到的吸附效果。(CSS3)
二、盒子模型
1、标准盒模型
box-sizing: content-box /*默认值*/
复制代码
2、怪异盒模型(IE盒模型)
box-sizing: border-box /*默认值*/
复制代码
问题:两者哪个效率更高?
- 编码效率后者更高
- 渲染效率前者更高
- 因为后者的话它那个content部分要通过width和height去减padding和border
3、flex弹性盒模型
给一个盒子设置
display:flex
这个盒子就会变成弹性盒子,有两个轴,一个主轴一个交叉轴,常用属性:
flex-direction属性决定主轴的方向(即项目的排列方向)
flex-wrap属性定义,如果一条轴线排不下,如何换行。
flex-flow
justify-content属性定义了项目在主轴上的对齐方式
align-items属性定义项目在交叉轴上如何对齐
align-content
flexbox中的align-self
align-items
在伸缩容器上使用它,伸缩容器内部所有的元素都一致地受制于
align-items
的值。
但是有些时候,我们希望伸缩容器内部某个元素在侧轴上的排列方式有所差异。此时就不能使用
align-items
,因为
align-items
作用于整体。
我们希望作用于部分。这就是align-self的发挥场地。 可取值:
align-self: auto|stretch|center|flex-start|flex-end|baseline|initial|inherit;
4、columns盒模型(不常考,略)
三、盒子水平垂直居中方案
(回答问题的小技巧,比如这个盒子水平垂直居中的问题,可以从项目说起,说我在项目中就经常会遇到需要元素居中的问题,一开始我总用...后来学习了好用的弹性布局...再后来逛博客比如掘金啊什么的,看到了什么什么方法,觉得也挺好用好实现的...)
基本代码:
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html,body{
height: 100%;
overflow: hidden;
.box{
box-sizing: border-box;
width: 100px;
height: 50px;
border: 1px solid #000;
background: brown;
</style>
</head>
<div class="box"></div>
</body>
</html>
复制代码
方案一:(定位的三种实现)
/* 定位1 */
/* 缺点,必须知道具体的宽高, 但很多时候都不是具体的宽高 */
body{
position: relative;
.box{
position: absolute;
top: 50%;
left: 50%;
margin-top: -25px;
margin-left: -50px;
复制代码
/* 定位2 */
/* 缺点,盒子必须有宽高,不需要考虑具体宽高 */
body{
position: relative;
.box{
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
复制代码
/* 定位3 CSS3里的translate神器 */
/* 缺点,浏览器兼容性不好 */
body{
position: relative;
.box{
position: absolute;
top: 50%;
left: 50%;
transform:translate(-50%, -50%);
复制代码
方案二(flex)
/*移动端常用
缺点:浏览器兼容性不好*/
body{
display: flex;
/* 主轴居中 */
justify-content: center;
/* 交叉轴居中 */
align-items: center;
复制代码
方案三(JS)
获取当前屏幕的宽高,获取盒子的宽和高,(屏幕宽高-盒子宽高)/2
<style>
body{
position: relative;
.box{
position: absolute;
</style>
<script>
let HTML = document.documentElement,
winW = HTML.clientWidth,
winH = HTML.clientHeight,
boxW = box.offsetWidth,
boxH = box.offsetHeight;
box.style.position = "absoluteH";
box.style.left = (winW-boxW) / 2 + 'px';
box.style.top = (winH-boxH) / 2 + 'px';
</script>
复制代码
方案四(盒子 变inline-block 转为文档属性使用)
/* 缺点,要求父级有固定宽高, 不能是百分比 */
body{
display: table-cell;
vertical-align: middle;
text-align: center;
/* 固定宽高 */
width: 500px;
height: 500px;
border: 1px solid #000;
.box{
display: inline-block;
复制代码
水平居中
-
对于
行内元素
: text-align: center; 复制代码 - 对于 确定宽度width的块级元素 :
- width和margin实现。 margin: 0 auto; 复制代码
-
子元素绝对定位和
margin-left: -width/2
, 前提是 父元素position: relative
- 对于 宽度未知的块级元素
- table标签配合margin左右auto实现水平居中。使用table标签(或直接将块级元素设值为display:table),再通过给该标签添加左右margin为auto。
-
inline-block实现水平居中方法。
display:inline-block
和text-align:center
实现水平居中。 -
绝对定位 +
transform
,translateX
可以移动本身元素的50%
。 - flex布局使用 justify-content:center 复制代码
垂直居中
-
通过设置父容器
相对定位
,子级设置绝对定位
,标签通过margin实现自适应居中 -
弹性布局
flex
:父级设置display: flex; 子级设置margin为auto实现自适应居中 -
父级设置相对定位,子级设置绝对定位,并且通过位移
transform
实现 -
table
布局,父级通过转换成表格形式,然后子级设置vertical-align
实现。(需要注意的是:vertical-align: middle使用的前提条件是内联元素以及display值为table-cell的元素)。 - flex方案: align-items: center; 复制代码
子Q:文字大小根据屏幕大小自适应
结合响应式rem那些
四、经典布局
1、两列布局——左边固定,右边自适应
flex属性
flex属性 :是 flex-grow、flex-shrink、flex-basis三个属性的缩写。
(1)flex-grow:定义项目的的放大比例
- 默认为0, 即使存在剩余空间,也不会放大 ;
- 所有项目的flex-grow为1:等分剩余空间(自动放大占位);
- flex-grow为n的项目,占据的空间(放大的比例)是flex-grow为1的n倍。
(2)flex-shrink:定义项目的缩小比例
- 默认为1, 如果空间不足,该项目将缩小
- 所有项目的flex-shrink为1:当空间不足时,缩小的比例相同;
- flex-shrink为0:空间不足时,该项目不会缩小;
- flex-shrink为n的项目,空间不足时缩小的比例是flex-shrink为1的n倍。
(3)flex-basis: 定义在分配多余空间之前,项目占据的主轴空间(main size),浏览器根据此属性计算主轴是否有多余空间
- 默认值为auto,即项目原本大小;
- 设置后项目将占据固定空间。
flex: 1
相当于:
-
flex-grow:1
自动放大占位 -
flex-shrink:1
如果空间不足,项目缩小 -
flex-basis:0%
<style>
#flex-container {
display: flex; /* 采用 flex 布局 */
flex-direction: row; /* 按行排列 */
.box-left {
background: orange;
width: 500px;
.box-right {
background: blue;
flex: 1;
</style>
</head>
<div id="flex-container">
<div class="box-left">left</div>
<div class="box-right">right</div>
</body>
复制代码
2、圣杯布局
(1) 浮动和负margin
<head>
<style>
html,body {
height: 100%;
/* 超出一屏隐藏 */
overflow: hidden;
.container{
height: 100%;
/*左右两边要设置200的宽度,所以这边padding左右留出200*/
padding: 0 200px;
.left,.right {
width: 200px;
min-height: 200px;
background: lightblue;
.center{
/* center其实是占满了container 留出padding之后的全部 */
width: 100%;
min-height: 400px;
background: lightsalmon;
.left,.right, .center {
/* 如果不加这个浮动,那么center,left,right这三个就会依次一行一行排下去 */
/* 加了浮动之后,由于center已经占满了第一行,所以left和right会在第二行依次排开 */
float: left;
.left{
margin-left: -100%;
position: relative;
left: -200px;
.right{
margin-right: -200px;
</style>
</head>
<!-- 圣杯布局 -->
<div class="container clearfix">
<div class="center"></div>
<div class="left"></div>
<div class="right"></div>
</body>
</html>
复制代码
(2) 使用CALC
(不推荐使用,兼容到IE9,一般来说禁止在css里使用表达式去算,因为渲染的很慢,影响性能,所以css里这种运算表达式尽量少写)
.center {
width: calc(100%-400px);
min-height: 400px;
background: #ffa07a;
复制代码
(3) Flex布局
<head>
<style>
html, body {
overflow: hidden;
.container {
display: flex;
justify-content: space-between;
height: 100%;
.left, .right {
/* flex是个组合写法
第一个:放大的比例
第二个:缩小的比例
第三个: 在整个容器里占空间的大小 */
flex: 0 0 200px ;
height: 200px;
background: lightblue;
.center {
/* 这里写1的意思是把剩余空间全部占满 */
flex : 1;
min-height: 400px;
background: lightsalmon;
</style>
</head>
<div class="container">
<div class="left"></div>
<div class="center"></div>
<div class="right"></div>
</body>
</html>
复制代码
(4) 定位
<head>
<style>
html, body {
height: 100%;
overflow: hidden;
.container {
position: relative;
height: 100%;
.left, .right {
position: absolute;
top: 0;
width: 200px;
min-height: 200px;
background: lightskyblue;
.left{
left: 0;
.right{
right: 0;
.center {
margin: 0 200px;
min-height: 400px;
background: lightsalmon;
</style>
</head>
<div class="container">
<div class="center"></div>
<div class="left"></div>
<div class="right"></div>
</body>
</html>
复制代码
3、双飞翼布局
(1) 浮动和负margin
<head>
<style>
html,body{
height: 100%;
overflow: hidden;
.container, .left, .right {
/* 浮动,使container,left,right都并排排列 */
/* 但由于container占了百分之百了,所以只有container在第一行 */
/* left和right在第二行 */
float: left;
.container {
width: 100%;
.container .center {
margin: 0 200px;
min-height: 400px;
background: lightsalmon;
.left, .right {
width: 200px;
min-height: 200px;
background: lightblue;
.left {
margin-left: -100%;
.right {
margin-left: -200px;
</style>
</head>
<!--container2里面只包含中间部分,两边翅膀脱离container-->
<div class="container">
<div class="center"></div>
<div class="left"></div>
<div class="right"></div>
</body>
</html>
复制代码
4、品字布局
<!doctype html>
<meta charset="utf-8">
<title>品字布局</title>
<style>
margin: 0;
padding: 0;
body {
overflow: hidden;
div {
margin: auto 0;
width: 100px;
height: 100px;
background: red;
font-size: 40px;
line-height: 100px;
color: #fff;
text-align: center;
.div1 {
margin: 100px auto 0;
.div2 {
margin-left: 50%;
background: green;
float: left;
transform: translateX(-100%);
.div3 {
background: blue;
float: left;
transform: translateX(-100%);
</style>
</head>
<div class="div1">1</div>
<div class="div2">2</div>
<div class="div3">3</div>
</body>
</html>
复制代码
<!doctype html>
<meta charset="utf-8">
<title>品字布局</title>
<style>
margin: 0;
padding: 0;
div {
width: 100%;
height: 100px;
background: red;
font-size: 40px;
line-height: 100px;
color: #fff;
text-align: center;
.div1 {
margin: 0 auto 0;
.div2 {
background: green;
float: left;
width: 50%;
.div3 {
background: blue;
float: left;
width: 50%;
</style>
</head>
<div class="div1">1</div>
<div class="div2">2</div>
<div class="div3">3</div>
</body>
</html>
复制代码
5、布局题:div垂直居中,左右10px,高度始终为宽度一半
子题目:(较简单)纯CSS实现一个长宽比始终为2:1的长方形。
问题描述: 实现一个div垂直居中, 其距离屏幕左右两边各10px, 其高度始终是宽度的50%。同时div中有一个文字A,文字需要水平垂直居中。
思路一:利用height:0; padding-bottom: 50%;
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
margin: 0;
padding: 0;
html, body {
height: 100%;
width: 100%;
.outer_wrapper {
margin: 0 10px;
height: 100%;
/* flex布局让块垂直居中 */
display: flex;
align-items: center;
.inner_wrapper{
background: red;
position: relative;
width: 100%;
height: 0;
padding-bottom: 50%;
.box{
position: absolute;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
</style>
</head>
<div class="outer_wrapper">
<div class="inner_wrapper">
<div class="box">A</div>
</body>
</html>
复制代码
强调两点:
-
padding-bottom究竟是相对于谁的?
答案是相对于
父元素的width值
。 那么对于这个out_wrapper的用意就很好理解了。 CSS呈流式布局,div默认宽度填满,即100%大小,给out_wrapper设置margin: 0 10px;相当于让左右分别减少了10px。 - 父元素相对定位,那绝对定位下的子元素宽高若设为百分比,是相对谁而言的? 相对于父元素的(content + padding)值, 注意不含border 延伸:如果子元素不是绝对定位,那宽高设为百分比是相对于父元素的宽高,标准盒模型下是content, IE盒模型是content+padding+border。
思路二: 利用calc和vw
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
padding: 0;
margin: 0;
html,
body {
width: 100%;
height: 100%;
.wrapper {
position: relative;
width: 100%;
height: 100%;
.box {
margin-left: 10px;
/* vw是视口的宽度, 1vw代表1%的视口宽度 */
width: calc(100vw - 20px);
/* 宽度的一半 */
height: calc(50vw - 10px);
position: absolute;
background: red;
/* 下面两行让块垂直居中 */
top: 50%;
transform: translateY(-50%);
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
</style>
</head>
<div class="wrapper">
<div class="box">A</div>
</body>
</html>
复制代码
五、浮动布局,清除浮动
浮动布局简介:
当元素浮动以后可以向左或向右移动,直到它的外边缘碰到包含它的框或者另外一个浮动元素的边框为止。
元素浮动以后会脱离正常的文档流,所以文档的普通流中的框就变的好像不存在一样。
优点
- 只会影响它这个元素后面的元素
- 内容默认提升半层
- 默认宽由其中的内容决定,会换行排列
- 这样做的优点就是在图文混排的时候可以==很好的使文字环绕在图片周围==。
- 另外当元素浮动了起来之后,它有着块级元素的一些性质:例如可以设置宽高等。 但它与inline-block还是有一些区别的,第一个就是关于横向排序的时候,float可以设置方向而inline-block方向是固定的;还有一个就是inline-block在使用时,有时会有空白间隙的问题。
缺点
最明显的缺点就是浮动元素一旦脱离了文档流,就 无法撑起父元素,会造成父级元素的高度塌陷。
清除浮动
-
额外添加一个标签
- 注:clear可选值:left right both
<div class="parent"> //添加额外标签并且添加clear属性 <div style="clear:both"></div> //也可以加一个br标签 </div> 复制代码
- 父级添加overflow属性,或者设置高度 缺点:如果有子元素想溢出,那么会受到影响。 <div class="parent" style="overflow:hidden"> //将父元素的overflow设置为hidden <div class="f"></div> </div> 复制代码
- after伪类 : 推荐,是空标签的加强版,目前各大公司的做法。 <style> #box1{ width:200px; border:1px black solid; } #box2{ width:100px; height:200px; background:red; float:left; } .clear:after{ /* 设置添加子元素的内容是空 */ content:''; /* 设置添加的子元素的高度0 */ height: 0; /* 设置添加子元素看不见 */ visibility: hidden; /* 设置添加子元素为块级元素 */ display: block; clear:both; } </style> <body> <div id="box1" class="clear"> <div id="box2"></div> </div> aaaaaaa </body> 复制代码
六、BFC
BFC定义
W3C对BFC的定义如下:浮动元素和绝对定位元素,非块级盒子的块级容器(例如inline-blocks, table-cells, 和table-captions),以及overflow值不为“visiable”的块级盒子,都会为他们的内容创建新的BFC(Block Fromatting Context, 即块级格式上下文)
触发条件
一个HTML元素要创建BFC,则满足下列的任意一个或多个条件即可:
下列方式会创建块格式化上下文:
- 根元素()
- 浮动元素(元素的float不是none)
- 绝对定位元素(元素的position为absolute或fixed)
- 行内块元素(元素的display为inline-block)
- 表格单元格(元素的display为table-cell, HTML表格单元格默认为该值)
- 表格标题(元素的display为table-caption,HTML表格标题默认为该值)
- 匿名表格单元格元素(元素的display为table、table-row、table-row-group、table-header-group、table-footer-group(分别是HTML table、row、tbody、thead、tfoot的默认属性)或inline-table)
- overflow 值 不为 visible 的块元素 - 弹性元素 (display为flex 或 inline-flex元素的直接子元素)
- 网络元素(display 为 grid 或 inline-grid 元素的直接子元素)
BFC渲染规则
- BFC垂直方向边距重叠
- BFC的区域不会与浮动元素的box重叠
- BFC是一个独立的容器,外面的元素不会影响里面的元素
- 计算BFC高度的时候浮动元素也会参与计算
应用场景
(1) 避免外边距折叠
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.container {
background-color: green;
overflow: hidden;
.inner {
background-color: lightblue;
margin: 10px 0;
</style>
</head>
<div class="container">
<div class="inner">1</div>
<div class="bfc">
<div class="inner">2</div>
<div class="inner">3</div>
</body>
</html>
复制代码
这时边距是叠在一起的,只会取到10px
/*style 添加*/
.bfc{
overflow: hidden;
<div class="container">
<div class="inner">1</div>
<div class="bfc">
<div class="inner">2</div>
<div class="inner">3</div>
复制代码
这时可以看到,边距不会叠在一起了,是正常的20px。
(2) 防止浮动导致父元素高度塌陷
现有如下页面代码:
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.container {
border: 10px solid red;
.inner {
background: #08BDEB;
height: 100px;
width: 100px;
</style>
</head>
<div class="container">
<div class="inner"></div>
</body>
</html>
复制代码
接下来将inner元素设为浮动:
.inner {
float: left;
background: #08BDEB;
height: 100px;
width: 100px;