一道面试题目引发的思考
起因
多列布局是前端一个经典的反复被提及的面试题目,最典型的即两列,左列定宽菜单栏,右列变宽为内容区域。
通常得到的答案无外乎左列浮动定宽,然后右列或浮动,或设置外边距,或绝对定位等等。偶尔会有面试者给出设置右列overflow属性的答案,心里就会有些惊喜,继而会继续追问,为什么这么设置就能实现效果,期待能有进一步惊喜,但基本大部分面试者都止步于这样设置,并不清楚原因。非常少的面试者会提到这样设置能够触发块级格式化上下文(Block Formatting Conext, BFC),如果继续追问触发BFC的原因,几乎没有一个面试者能给出比较满意的答案。
本文就是由这道面试题目引发的一些思考。针对设置overflow属性这一方法,做进一步的探讨。
overflow属性
overflow属性最常见的一个使用场景就是规定当内容溢出元素框时发生的事情。可能的值如下:
- visible 默认值。元素内容不会被裁剪,元素框之外的内容仍然会呈现。
- hidden 元素内容会被裁剪,并且元素 框之外的内容是不可见的。
- scroll 元素内容会被裁剪,但是浏览器会显示滚动条以便查看其余的内容。
- auto 浏览器自动处理元素内容的溢出,如果元素内容被裁剪,则浏览器会显示滚动条以便查看其余的内容。
- inherit 规定应该从父元素继承 overflow 属性的值。
除此之外,也会经常看到通过overflow属性实现的一些效果,比如清除浮动,以及上面提到的两栏布局的实现。这些效果的实现,可能跟overflow属性的本意相差甚远,就像两种不相关的事务被硬生生的牵扯到了一起。其实不然,CSS Spec规范文档中还明确记录着overflow属性的另外一个重要作用。
overflow属性跟布局的关系
The CSS2.1 spec mandates that overflow other than visible establish a new "block formatting context".
CSS2.1规范中已经明确提出,设置overflow属性(非visible)能触发块级格式化上下文(Block Formatting Conext, BFC)。
BFC是个很大的话题,此处不展开,这里给出一个简化不精确的解释,BFC概念的引入,一定程度是为了特殊情况下布局计算的方便,元素触发BFC之后,其作用就相当于一个根容器,其内部的子元素会跟外界完全隔离开,子元素布局以及尺寸相关的计算都会以该元素容器为基础。
为什么overflow非visible值会触发BFC?
首先,设置overflow属性为visible的话,是一种默认情况,就相当于正常默认的布局,所有超出元素框的内容仍然会正常显示,不会被裁剪,也不会出现滚动条。但对于其它几种值的话(hidden, scroll, auto),元素的内容可能会被裁剪,此时,对于某些情况下可能出现的特殊布局处理就会出现争议。
比如对于垂直方向紧贴着的两个元素A和B,其中元素A中浮动的子元素可能会遮住元素B的部分文字区域,此时如果元素B的overflow属性设置为visible,则内容会包裹在元素A浮动子元素的周围,这种情况比较容易理解,如下图。
图1 overflow属性设置为visible
但当元素B的overflow属性设置为非visible的值时,各版本规范的规定就会出现差异。
CSS2.0规范规定,设置非visible属性值后,元素B的内容仍然包裹浮动元素,如图2所示。
图2 overflow属性设置为novisible,CSS2.0规范中的处理
此后如果元素B内容发生滚动,每次滚动行为,元素B中发生折叠的内容(图3中元素B中文字内容滚动后发生变化)全部要重新计算重绘,实际上这将会带来很大的性能问题,对滚动体验也会造成比较大的影响。
图3 overflow属性设置为novisible,CSS2.0规范中发生滚动时的处理
但这里存在进一步的疑问,即使按此规范的约定,元素B内容滚动时存在性能以及体验问题,但是非visible属性中的hidden值,难以理解,元素内容已经被裁剪掉了,为什么跟其它值auto, scroll归为一类?这里面就存在一个误区,overflow设置为hidden值并不代表内容不可滚动,此时浏览器只不过没有提供可滚动的UI,被"裁剪"掉的内容可以通过JavaScript脚本来控制滚动,这也是脚本模拟滚动条的基础。比如,可以通过JavaScript脚本设置元素的scrollTop实现图4的效果,更友好的方式可以自定义一个滚动条。
图4 overflow属性设置为hidden,CSS2.0规范中发生滚动时的处理
事实上各大浏览器厂商也都没有遵照CSS2.0来实现这一部分规范。取而代之,实现的是CSS2.1中的规范内容,即当元素B的overflow属性设置为非visible值时会触发BFC,元素B会创建自己的块级格式化上下文,并会被整体推向右侧,如图5所示。
图5 overflow属性设置为nonvisible,CSS2.1规范中的处理
备注 上面各图均来自于参考文献3
收尾
事实上,一些常见的其它布局技巧也都是基于上述的原理点,比如overflow属性非visible值可以用于清除浮动。如果一个面试者,能够比较清楚地讲出上面的各点,相信每个面试官心里面都会比较惊喜,上面只是自己的一些想法,可能会有些许的钻牛角尖,但单从这种对细节的钻研把控程度,候选人就一定不会太差,对候选人来说必然会有很大程度的加分。
上面只是针对两列布局这道题目一种方案的单方面探讨,这种方案有哪些优缺点等等都未提及,如果对每种方案都进行类似程度的拓展,将会发现这其中会涵盖很多前端知识点,所以看似简单的题目其实并不简单。越发觉得前端领域的水很深,伙伴们一起来努力探索实践吧!
参考文献
- block formatting contexts
- The impact of 'overflow' values other than 'visible' on the block formatting context
- Re: CSS21 Why do overflow values other than 'visible' establish a new block formatting context?
- How does the CSS Block Formatting Context work?
Written by Hong
更多专业前端知识,请上 【猿2048】www.mk2048.com
一道面试题目引发的思考相关推荐
- 三只青蛙的故事:一道脑筋急转弯题目引发的思考
一道脑筋急转弯题目是这样的:有三只青蛙在河中的一片叶子上顺水漂流.其中一只想跳到河里.在叶子上还剩几只青蛙? 大多数人会回答还有两只.(我刚看到此题时认为一只也没有,因为一只青蛙跳了之后剩下的两只也会 ...
- 一道JS面试题目引发的思考
今看到一道有意思的题目,引发很多未知的东西,页面上有html代码如下: <body> <form id="form1" runat="server&qu ...
- 前置++与后置++之一道简单的题目引发的思考
引言 昨晚一时兴起,我脑子就问自己下面的代码会输出什么,也不知道我脑子为什么有这个代码模型,只是模糊的有些印象: #include <stdio.h> #include <stdli ...
- Google测试工师的一道面试题目
最近重读<Google软件测试之道>,其中有一道面向软件测试工程师的面试题非常考验测试人员的思维.拿来与你们分享,看看这样一道题,你能想到多少个测试点. 题目: 在一个Web测试页面上,有 ...
- mysql is fashion ctf_一道CTF题引发的思考-MySQL的几个特性(续)
0x00 背景 这两天处于转牛角尖的状态,非常不好.但是上一篇的中提到的问题总算是总结了些东西. 0x01 测试过程 (1)测试环境情况:创建了如下测试表test, mysql> select ...
- Mysql京东的一道面试题目 比较综合
查询sql :求取一个月之内每天分数和大于40的天数大于1的人 # 凭借印象记下来的 一个意思 # 计算出每人每天的分数和 然后每人每天分数和要求大于40 # 然后统计一个月之内每人每天分数大于40的 ...
- Java实现C语言select函数_一道面试题目,分别用sql 和java,c++, c语言实现,
引用来自"雨翔河"的评论 获取国家假日办的的信息,然后根据假日办提供的信息来搞定.日期的话,哈哈,找个提供日期查询的接口,借用一下来查日期,也搞定了.总之哪里有的抄就抄哪里的. 再 ...
- 一道概率题引发对考研数学复习的思考
一道概率题引发对考研数学复习的思考 知识回顾 如题,今天上午我兴致勃勃地拿出2006年数学一做了起来.做前面还算顺利,直到最后那道概率题,关于极大似然估计的题目,我的内心:艹了,这怎么跟之前做的不一样 ...
- 一道大厂Python面试题,4种解法,从青铜到王者引发的“思考”!
"菜鸟学Python",第"518"篇原创 金九银十应该是校招的黄金时间,大家都知道去大厂面试,算法是一个必须要过的关,无论是笔试还是面试的环节都需要.而算法这 ...
最新文章
- HDU - 5877 Weak Pair 2016 ACM/ICPC 大连网络赛 J题 dfs+树状数组+离散化
- 幼儿园课程体系结构图_全人教育、均衡发展课程体系介绍
- 计算机网络·详解TCP流量控制,拥塞控制,运输连接管理
- 【MM模块】Batch 批次管理 2
- BZOJ 3309 DZY Loves Math
- http协议与服务器通信,iPhone应用用HTTP协议和服务器通信
- CentOS安装Oracle12C
- 关于Element UI中页面样式小问题
- cassss服务未启动_不要再本地启动项目调试了,试SpringBoot远程调试你会发现新大陆!...
- 喇叭正反相位测试音频_音频功放失真的四大要点及改善方法
- 基于javaweb酒店信息管理系统、基于ssm/springboot的酒店预定系统
- linux中-f的含义,linux 下shell中if的“-e,-d,-f”的含义
- linux常用软件收集
- TutorialsPoint NumPy 教程
- lisp不是函授型语言_lisp语言的定义
- MySQL 触发器使用入门
- Boost串口通信 boost::asio::serial_port基本使用
- 数据库 之数据库设计浅知识 -- 设计概述、概念结构设计(E-R模型概述)、逻辑结构设计(函数依赖和范式)、物理结构设计
- 【Git】SSL certificate problem: unable to get local issuer certificate错误的解决办法
- New的返回值和New的(3种)用法详解
热门文章
- 新版ipados可以编辑C语言吗,iPadOS新增了五个有用的功能,看你需不需要
- mongodb mysql json数据_使用MongoDB与MySQL有很多JSON字段?
- 如何设置Linux操作系统shell命令的默认语言
- 实现多线程的方式之实现Callable接口
- vue element-ui 的奇怪组件el-switch
- C-Free 5.0编译失败问题解决办法
- MacOSX64位机器上gcc编译32位x264静态库
- DotNetOpenAuth实践之搭建验证服务器
- SP2010开发和VS2010专家食谱--第二章节--工作流
- 正在编写推箱子游戏的自动求解程序