面试题 CSS

BFC - 块级格式化上下文

块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视化CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。
BFC 解决了什么问题?

清除浮动

在 flex 布局还没流行的时候,常常会用到浮动 float ,浮动元素脱离的文档流,带来直接的一个问题就是父级高度塌陷。
清除浮动常用的方法有, clear 属性,还有就是构建 BFC ,看个小例子

  1. .con{
  2. border: 1px solid;
  3. width: 300px;
  4. }
  5. .float{
  6. float: left;
  7. height: 100px;
  8. background-color: sandybrown;
  9. }
  10. <div class="con">
  11. <div class="float">xxxxxxxx</div>
  12. <p>dsfsdfwefesfhjkhjkhuhjk</p>
  13. </div>

黄色 div 是个浮动元素,定了 100px 高度,父级不定高,很明显父级高度没有被撑开。
image.png
给父级 con 加上 overflow: auto; 效果如下
image.png
这时候父级div就是一个 BFC

外边距折叠

在CSS中,两个或多个毗邻的普通流中的盒子(可能是父子元素,也可能是兄弟元素)在垂直方向上的外边距会发生叠加,这种形成的外边距称之为外边距叠加。
形成外边距折叠有几个关键要素:毗邻、两个及以上、垂直方向、正常流
毗邻:对于父子元素,他们自己是紧挨着的,子元素没有被父元素 border padding 给隔开,这样他们就是毗邻的;对于兄弟元素,他们的盒模型是挨着一起的就是毗邻的。
正常流:除去浮动定位、绝对定位,也就是正常的文档流。
这是个非常常见的问题。解决方案也挺多的,无外乎打破三要素中的一个即可,比如采用浮动、绝对定位、inline-block、添加空白的flex元素、还有就是接下来要说的构建 BFC

  1. .con {
  2. width: 300px;
  3. background-color: antiquewhite;
  4. }
  5. .one {
  6. height: 100px;
  7. margin-top: 10px;
  8. margin-bottom: 20px;
  9. background-color: seagreen;
  10. }
  11. .two {
  12. height: 100px;
  13. margin-top: 10px;
  14. background-color: slateblue;
  15. }
  16. <div class="con">
  17. <div class="one"></div>
  18. <div class="two"></div>
  19. </div>

image.png
div onemargin-top: 10px; 导致父级向下移动 10px,这是父子元素的外边距折叠,用构建 BFC 的方式解决。

  1. .con {
  2. width: 300px;
  3. background-color: antiquewhite;
  4. overflow: auto; /* 构建BFC */
  5. }

效果如下:
image.png
那么对于毗邻的兄弟节点,方法也是一样,把一个节点构建成 BFC 即可

  1. <div class="con">
  2. <div class="one"></div>
  3. <div style="overflow: auto;">
  4. <div class="two"></div>
  5. </div>
  6. </div>

image.png

BFC的创建方式

方法很多,可根据实际情况选择

  • 根元素(html)
  • 浮动元素(元素的 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 值为 flow-root 的元素
  • contain 值为 layout、content或 paint 的元素
  • 弹性元素(display为 flex 或 inline-flex元素的直接子元素)
  • 网格元素(display为 grid 或 inline-grid 元素的直接子元素)
  • 多列容器(元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1)
  • column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更,Chrome bug)。

    BFC解决了什么问题

    上面可看出 BFC 可以清除浮动,可以解决外边距折叠两问题。
    BFC 可通俗理解成是构建一个独立的区域,可包含区域内的所有元素,包括浮动元素,与外界互不打扰的一个空间。

    absolute 是相对哪个元素定位的

    position 属性取值有 relative, absolute, fixed 或 sticky,元素设置了其中之一的就是定位元素。(换句话说,除static以外的任何东西)。
    目前定位类型有四类:

  • 相对定位元素(relatively positioned element)是计算后位置属性为 relative 的元素。

  • 绝对定位元素(absolutely positioned element)是计算后位置属性为 absolute 或 fixed 的元素。
  • 粘性定位元素(stickily positioned element)是计算后位置属性为 sticky 的元素。用于滑动中固定某一元素,这个目前有些兼容性问题。

    相对定位

    position: relative; 元素按照文档流的布局放置元素,它的用处是可以在不改变布局方式的前提下调整元素位置,使用 top bottom left right

    绝对定位

    position: absolute; 绝对定位的元素脱离了文档流,不会占据文档流的空间,感觉就像在文档流的上一层。
    绝对定位的元素可以使用 top bottom left right 调整布局位置,在没有设置这几个值的时候,绝对定位元素显示还是保持在当前的位置。如果设置了值,那么这个元素就需要找到一个锚点,因为已经脱离文档流,所以需要找到一个参考点,这参考点就是 最近的非 static 祖先元素 ,可以是 relative, absolute, fixed,一直往上到 body 元素。
    所以常常会采用 relative + absolute 的组合布局方式,当然也可以利用绝对定位元素在当前位置显示的特性结合 margin 来使用。
    绝对定位还有个用处,就是避免触发回流,因为脱离正常的文档流,因此对于频繁回流的元素可以采用绝对定位。

    z-index

    z-index 表示创建一个新的显示层级,值大的在最上层。多个绝对定位元素会按照后一个覆盖前一个的显示方式,而且绝对定位元素会覆盖文档流中的元素,那么只有在元素位置不当便调整顺序的时候才只用,正常情况下不建议设置值,毕竟多使用一个元素,就容易出现诡异的问题。

    DPR

    先看看几个概念

    像素

    是图像显示的基本单位,类似于米是长度的一个单位一样。1像素是显示的最小区域。

    物理像素

    设备的物理像素,每个设备的物理像素都是厂家固定好的,

    css像素

    这个主要用于编码用的,约定好的在显示层上的单位,screen.width 可获取到逻辑编码中的窗口最大像素。

    DPR

    在 iphone 没有搞事之前,物理像素和逻辑像素是相等的,但如今高清屏已经快成标配,可显示的像素点越多越清晰,导致设备上每英寸可显示的像素点(PPI)越来越多,这样一来,屏幕的大小没变,css的逻辑像素没变,可物理像素却变多了,一个逻辑像素要对于多个物理像素,这两者的比例就是 DPR,DPR = 物理像素/css逻辑像素,可以通过 window.devicePixelRatio 获取设备的 DPR。

    1px 问题了解么?有什么解决方案?

    在高清屏中 DPR 可能会是 2 或者 3 ,那么原先 1px 像素的线在高清屏下就占了2个或者3个物理像素,导致线看着比较粗。
    解决:
  1. 使用伪类,设置 border 1px scale(0.5)
  2. 设置 meta initial-scale 根据DPR设置初始值
  3. 伪类 + transform: scaleY(0.5);

    1. /* 伪类 + transform: scaleY(0.5); */
    2. .px1 {
    3. position: relative;
    4. }
    5. .px1:before {
    6. content: " ";
    7. position: absolute;
    8. left: 0;
    9. top: 0;
    10. width: 200%;
    11. border: 1px solid black;
    12. color: black;
    13. height: 200%;
    14. transform-origin: left top;
    15. transform: scale(0.5);
    16. }

    link 和 @import 的区别

    @import 根据字面意思就知道是用于导入其他样式文件的,两者的区别如下:

  4. 从属关系区别
    link:是 html 提供的标签,不仅可以加载css样式表,还可以定义 RSS、rel 连接属性等。
    @import:是 css 提供的语法规则,用于导入样式表。

  5. 加载顺序区别
    link:文件是同时加载。
    @import 引入的 CSS 将在页面加载完毕后被加载。
  6. 兼容性问题
    link 不存在兼容性问题;@import 可能会有兼容性问题

    display:none与visibility:hidden的区别?

    效果都是隐藏元素
    display:none 在文档布局中不在分配空间(节点),值变化会导致回流和重绘
    visibility:hidden 保留渲染树中的节点,占用空间,会导致重绘

    inline-block block 的区别

    这两个分别是:行内块级元素和块级元素,顺带介绍下行内元素

    块级元素

    块级元素的特点:元素总是在新的一行开始,盒模型的属性均可以控制,div p ul ol ... 等元素默认就是块级元素,也可以通过 display: block; 设置为块级元素。

    行内元素

    行内元素的特点:和其他元素在同一行,元素不可以设置高度和宽度,取决于内容的宽高度,默认的行内元素有 span a lable input img ...,也可通过 display: inline; 设置为行内元素。

    行内块级元素

    名字看上去就是上面两者的结合,同时具备了两个的特性。通过 display: inline-block; 设置。
    但是两个相邻的 inline-block 元素中间有空格就会出现间隙,解决办法可以粗暴的移除空格和换行,还有设置字体大小为 0 , 因空格也是字符,所以可给父级设置 font-size:0、letter-spacing:-3px

    rem em vh vw 的区别

    这几个单位常用于自适应布局

    rem em

    rem : css3 新增,相对于根节点的字体大小的一个单位,eg: 1rem * font-size:20px = 20px
    在开发前先制定好一个基准,比如说以 375 宽的设计稿作为规范,设定这个宽度下的字体大小为 375/10 = 37.5 ,那设计稿下 60px 的宽对应的 rem 就是:60px = (60/37.5)rem
    若使用css预处理,可以写一个转换函数
    1. @function px2rem($px) {
    2. @return ($px/37.5) + rem;
    3. }
    em : 与rem类似,但是相对于父级元素的字体大小。

    vw vh

    相对于视口宽高的百分比值

    vw : 1vw 等于视口宽度的1% vh : 1vh 等于视口高度的1% vmin : 选取 vw 和 vh 中最小的那个 vmax : 选取 vw 和 vh 中最大的那个

  1. //iPhone 6尺寸作为设计稿基准
  2. $vm_base: 375;
  3. @function vw($px) {
  4. @return ($px / $vm_base) * 100vw;
  5. }

单行、多行文本居中

单行:

  1. 设置 line-heightheight 相同
  2. flex 布局,设置交叉轴对齐方式

多行:

  1. flex 布局 display: flex;align-items: center;
  2. table 布局 ,外层使用 display: table; 内层使用 vertical-align: middle;display: table-cell; table-cell 可以将元素表现与单元格 td 类似,在对单元格设置居中,不过会破坏其他属性,比如浮动、margin 等

    1. .text{
    2. background-color: sandybrown;
    3. width: 200px;
    4. height: 300px;
    5. display: table;
    6. }
    7. .cell{
    8. vertical-align: middle;
    9. }
    10. <div class="text">
    11. <div class="cell">
    12. 今天天气很好,好想出去玩.今天天气很好,好想出去玩.今天天气很好,好想出去玩.今天天气很好,好想出去玩.今天天气很好,好想出去玩.
    13. </div>
    14. </div>
  3. 设置外层 line-height 等于外层高度,文本一行的高度就等于容器的高度,内层使用 display: inline-block;vertical-align: middle;line-height: 17px; 内层设定为行内块级元素,设置行内元素的对齐方式是 middle,在对元素重新设定行高

    1. .text {
    2. background-color: sandybrown;
    3. width: 200px;
    4. height: 300px;
    5. line-height: 300px;
    6. }
    7. .cell {
    8. display: inline-block;
    9. vertical-align: middle;
    10. line-height: 20px;
    11. }
    12. <div class="text">
    13. <div class="cell">
    14. 今天天气很好,好想出去玩.今天天气很好,好想出去玩.今天天气很好,好想出去玩.今天天气很好,好想出去玩.今天天气很好,好想出去玩.
    15. </div>
    16. </div>

    css 选择器和优先级

    id选择器(#myid)、类选择器(.myclassname)、标签选择器(div, h1, p)、相邻选择器(h1 + p)、子选择器(ul > li)、后代选择器(li a)、通配符选择器(*)、属性选择器(a[rel=”external”])、伪类选择器(a:hover, li:nth-child),简单介绍下面几个:

    a > b :子类选择器,只有直接的子类才生效 a + b:毗邻选择器,只有毗邻的下一个元素才生效 a ~ b :后续选择器,a元素之后的所有同级的b元素 [attribute] :属性选择器,含有这个属性的元素才生效 :first-of-type : 选择器匹配元素其父级是特定类型的第一个子元素

选择器权重

优先级排序:!important > 行内样式 > ID > 类、伪类、属性 > 标签名 > 通配符 > 继承
权重值如下,每个都是相差一个量级

  1. 元素和伪元素选择器:1
  2. class选择符:10
  3. id选择符:100
  4. 内联样式:1000

    英文换行

  • word-break: break-all 对字符起作用,断开单词,下个字母自动到下一行。主要解决了长串英文的问题。
  • word-wrap:break-word 只对英文起作用,以单词作为换行依据

    哪些属性可以继承

    元素外观相关的属性可以继承,比如字体相关的属性、文本系列的属性。布局相关的属性不可以继承,具体属性名就不列举了。

    flex 常见有属性

    容器上的属性

    flex-direction : 主轴方向 flex-wrap : 换行的方式 flex-flow :上面两个的简写 justify-content : 主轴的对其方式 align-items : 交叉轴的对齐方式 align-content : 多根主轴的对齐方式

元素上的属性

order : 排序值,数值越小越靠前 flex-grow : 项目放大的比例,默认为 0 不放大 flex-shrink : 项目缩小的比例,默认 1 flex-basis : 属性定义了在分配多余空间之前,项目占据的主轴空间,如果元素定义了宽,那么宽度将无效默认 auto flex :以上三个的简称