HTML5andCSS3面试题大全
- 一.HTML5
- 1.html5有哪些新特性、移除了那些元素?
- 2.有⼏种前端储存的⽅式?这些⽅式的区别是什么?(追问)✨✨✨✨
- 3.你对HTML语义化的理解?✨
- 4.html文档解析
- 5.用websocket搭建实验聊天室
- 6.doctype的作用是什么?✨
- 7.HTML、XHTML、XML有什么区别
- 8.什么是data-属性?
- 9. HTML5与HTML4的不同之处
- 10. 有哪些常⽤的meta标签?
- 11.src和href的区别?
- 12.script标签中defer和async的区别?✨✨✨
- 13.(Drag)和放(Drop)
- 14.24个强大的HTML属性与实用小技巧
- 二.CSS
- 核心基础知识
- 语法
- @规则
- 继承性
- 视觉格式化模型
- 1.块元素和行内元素、行内块元素的区别
- 2.CSS选择器
- (1) CSS选择器种类
- (2)CSS选择器的优先级
- (3)类选择的命名规范
- 3.CSS伪类和伪元素
- (1)伪类和伪元素种类
- (2)特殊选择器的妙用
- 1.CSS引入
- (1)有哪些引入方式?通过link和@import引入有什么区别?(* )
- (2)Style 标签写在 body 后和 body 前有什么区别?
- (3)什么是 FOUC(Flash of Unstyled Content)?如何来避免 FOUC
- 4.CSS盒模型✨
- 7.display 布局(行内元素和块级元素)
- 9.overflow溢出
- 10.格式化上下文
- (一)BFC块级格式上下文
- (二)IFC行内格式上下文
- 12.z-index层叠上下文
- 13.CSS浏览器兼容性
- 15.em\px\rem区别?
- 18.学习布局
- (一)布局方式
- 1.流式布局
- 2.浮动布局
- 3.定位布局
- 4.表格布局
- 5.弹性布局
- 6.栅格布局
- 7.响应式布局
- (二)布局实践
- 1.水平垂直居中
- 2.常用布局
- 布局一:两栏布局(边栏定宽主栏自适应)
- 布局二:三栏布局(两侧栏定宽主栏自适应)
- 布局三:多列等高布局
- 布局四:三行布局(头尾定高主栏自适应)
- 3.自适应的优秀布局方案实践
- 19.CSS 动画有哪些?
- 21.为什么要初始化 CSS 样式
- 22.手写题:实现一个两栏布局。三列的布局,并且要求三列等高,且以内容最多的一列的高度为准。
- 1.两栏布局的方式
- 2.实现三列布局的方式
- 23.CSS实现自适应正方形、等宽高比矩形
- 24.CSS sprites 的理解及其好处
- 26.WEB标准以及W3C
- 27.css实现瀑布流布局
- 28.TailwindCSS v3.0 一大波新特性来袭!
- 29.CSS预编译
- 1.scss是什么及其几大特性?
- 2.安装和使用Sass的步骤是什么?
- 3.Sass和Less有什么区别?
- 4.什么是CSS预处理器/后处理器?
- 5.UI组件库中三大预编译的样式穿透
- 6.当Sass和新CSS功能发生冲突时的解决方案
- 7.SCSS的应用
- 30.进阶:玩转 CSS 变量
- 31.CSS代码整洁之道
- 32.CSS性能优化
- 33.提高用户体验技巧
- 34.12种增强CSS技能并加快开发速度的资源
- 二.常见需求
- 1.自定义属性
- 2. 移动端兼容常见问题汇总
- (1)1px 边框解决方案
- (2) 响应式设计
- 3.PC端兼容性问题汇总
- (1)消除浏览器默认样式
- 5.长文本省略处理
- 6.水平垂直居中
- 单行的文本、inline 或 inline-block 元素
- 固定宽高的块级盒子
- 不固定宽高的块级盒子
- 8.CSS 实现优惠券的技巧
- 10.常见面试题
- (1)面试官:让Chrome支持小于12px 的文字方式有哪些?区别?
- (2)面试官:flex:7 1 100px中这三个参数你知道什么意思吗?
- (3)有哪些方式(CSS)可以隐藏页面元素?[visibility \display\opacity的差别]
- 三.CSS奇巧淫技
- 1.有意思!奇妙的 CSS shapes(CSS图形)
- 2.5个你可能不知道的很棒CSS功能
- 3.Github -- iCSS
- 4.不可思议的纯 CSS 滚动进度条效果
- 6.N个常见的CSS3动效技巧大全
- 7.CSS @property,让不可能变可能
- 8.N款非常实用的CSS3工具
- 参考链接
一.HTML5
1.html5有哪些新特性、移除了那些元素?
新增功能:HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加
- 本地存储 localStorage 和 sessionStorage
- 语意化标签 article、footer、header、nav、section
- 新增选择器 document.querySelector、document.querySelectorAll
- 绘画 canvas\svg
- 历史管理 history
- 拖拽释放(Drag and drop) API
- 媒体播放的 video 和 audio
- 离线应用 manifest
- 桌面通知 Notifications
- 增强表单控件 calendar、date、time、email、url、search
- 地理位置 Geolocation
- 多任务 webworker
- 全双工通信协议 websocket
- 跨域资源共享(CORS) Access-Control-Allow-Origin
- 页面可见性改变事件 visibilitychange
- 跨窗口通信 PostMessage
- Form Data 对象
移除的元素:
纯表现的元素:basefont、big、center、font、 s、strike、tt、u
对可用性产生负面影响的元素:frame、frameset、noframes
viewport
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<!--
width 设置viewport宽度,为一个正整数,或字符串‘device-width’
device-width 设备宽度
height 设置viewport高度,一般设置了宽度,会自动解析出高度,可以不用设置
initial-scale 默认缩放比例(初始缩放比例),为一个数字,可以带小数
minimum-scale 允许用户最小缩放比例,为一个数字,可以带小数
maximum-scale 允许用户最大缩放比例,为一个数字,可以带小数
user-scalable 是否允许手动缩放
-->
延伸提问:怎样处理 移动端 1px 被 渲染成 2px问题?
局部处理
- meta标签中的 viewport属性 ,initial-scale 设置为 1
- rem按照设计稿标准走,外加利用transfrome 的scale(0.5) 缩小一倍即可;
全局处理
- meta标签中的 viewport属性 ,initial-scale 设置为 0.5
- rem 按照设计稿标准走即可
2.有⼏种前端储存的⽅式?这些⽅式的区别是什么?(追问)✨✨✨✨
cookies、localstorage、sessionstorage、Web SQL、IndexedDB?
- cookies: 在HTML5标准前本地储存的主要⽅式,优点是兼容性好,请求头⾃带cookie⽅便,缺点是⼤⼩只有4k,
⾃动请求头加⼊cookie浪费流量,每个domain限制20个cookie,使⽤起来麻烦需要⾃⾏封装,联系XSS攻击和单点登录 - localStorage:HTML5加⼊的以键值对(Key-Value)为标准的⽅式,优点是操作⽅便,永久性储存(除⾮⼿动删
除),⼤⼩为5M,兼容IE8+ 联系单点登录和Vuex持久化插件(vuex-persistedstate)(解决一刷Vuex数据就没有了的问题) - sessionStorage:与localStorage基本类似,区别是sessionStorage当⻚⾯关闭后会被清理,⽽且与cookie、localStorage不同,他不能在所有同源窗⼝中共享,是会话级别的储存⽅式
- Web SQL:2010年被W3C废弃的本地数据库数据存储⽅案,但是主流浏览器(⽕狐除外)都已经有了相关的实
现,web sql类似于SQLite,是真正意义上的关系型数据库,⽤sql进⾏操作,当我们⽤JavaScript时要进⾏转换,较为繁琐。 - IndexedDB:是被正式纳⼊HTML5标准的数据库储存⽅案,它是NoSQL数据库,⽤键值对进⾏储存,可以进⾏快速读取操作,⾮常适合web场景,同时⽤JavaScript进⾏操作会⾮常⽅便。
3.你对HTML语义化的理解?✨
HTML5–语义化标签 语义化是指使⽤恰当语义的html标签,让⻚⾯具有良好的结构与含义,⽐如 <p>
标签就代表段落, <article>
代表正⽂内容等等。
语义化的好处主要有两点:
- 开发者友好:使⽤语义类标签增强了可读性,开发者也能够清晰地看出⽹⻚的结构,也更为便于团队的开发和维护
- 机器友好:带有语义的⽂字表现⼒丰富,更适合搜索引擎的爬⾍爬取有效信息,语义类还可以⽀持读屏软件,根据⽂章可以⾃动⽣成⽬录。
这对于简书、知乎这种富⽂本类的应⽤很重要,语义化对于其⽹站的内容传播有很⼤的帮助,但是对于功能性的web软件重要性⼤打折扣,⽐如⼀个按钮、Skeleton这种组件根本没有对应的语义,也不需要什么SEO。
4.html文档解析
5.用websocket搭建实验聊天室
6.doctype的作用是什么?✨
DOCTYPE是html5标准⽹⻚声明,且必须声明在HTML⽂档的第⼀⾏。来告知浏览器的解析器⽤什么⽂档标准解析这个
⽂档,不同的渲染模式会影响到浏览器对于 CSS 代码甚⾄ JavaScript 脚本的解析
⽂档解析类型有:
- BackCompat:怪异模式,浏览器使⽤⾃⼰的怪异模式解析渲染⻚⾯。(如果没有声明DOCTYPE,默认就是这个模式)
- CSS1Compat:标准模式,浏览器使⽤W3C的标准解析渲染⻚⾯。
IE8还有⼀种介乎于上述两者之间的近乎标准的模式,但是基本淘汰了。
这三种模式的区别是什么?
标准模式(standards mode):⻚⾯按照 HTML 与 CSS 的定义渲染
怪异模式(quirks mode)模式: 会模拟更旧的浏览器的⾏为
近乎标准(almost standards)模式: 会实施了⼀种表单元格尺⼨的怪异⾏为(与IE7之前的单元格布局⽅式⼀致),
除此之外符合标准定义
7.HTML、XHTML、XML有什么区别
- HTML(超⽂本标记语⾔): 在html4.0之前HTML先有实现再有标准,导致HTML⾮常混乱和松散
- XML(可扩展标记语⾔): 主要⽤于存储数据和结构,可扩展,⼤家熟悉的JSON也是相似的作⽤,但是更加轻量⾼效,所以XML现在市场越来越⼩了
- XHTML(可扩展超⽂本标记语⾔): 基于上⾯两者⽽来,W3C为了解决HTML混乱问题⽽⽣,并基于此诞⽣了
HTML5,开头加⼊ 的做法因此⽽来,如果不加就是兼容混乱的HTML,加了就是标准模式。
8.什么是data-属性?
HTML的数据属性,⽤于将数据储存于标准的HTML元素中作为额外信息,我们可以通过js访问并操作它,来达到操作数
据的⽬的。
<article
id="electriccars"
data-columns="3"
data-index-number="12314"
data-parent="cars">
...
</article>
前端框架出现之后,这种⽅法已经不流⾏了
9. HTML5与HTML4的不同之处
- ⽂件类型声明(<!DOCTYPE>)仅有⼀型:。
- 新的解析顺序:不再基于SGML。
- 新的元素:section, video, progress, nav, meter, time, aside, canvas,
command, datalist, details, embed, figcaption, figure, footer,
header, hgroup, keygen, mark, output, rp, rt, ruby, source, summary,
wbr。 - input元素的新类型:date, email, url等等。
- 新的属性:ping(⽤于a与area), charset(⽤于meta), async(⽤于script)。
- 全域属性:id, tabindex, repeat。
- 新的全域属性:contenteditable, contextmenu, draggable, dropzone, hidden,
spellcheck。 - 移除元素:acronym, applet, basefont, big, center, dir, font, frame,
frameset, isindex, noframes, strike, tt
10. 有哪些常⽤的meta标签?
meta标签由name和content两个属性来定义,来描述⼀个HTML⽹⻚⽂档的属性,例如作者、⽇期和时间、⽹⻚描述、关键词、⻚⾯刷新等,除了⼀些http标准规定了⼀些name作为⼤家使⽤的共识,开发者也可以⾃定义name。
- charset,⽤于描述HTML⽂档的编码形式
<meta charset="UTF-8" >
- http-equiv,顾名思义,相当于http的⽂件头作⽤,⽐如下⾯的代码就可以设置http的缓存过期⽇期
<meta http-equiv="expires" content="Wed, 20 Jun 2019 22:33:00 GMT">
- viewport,移动前端最熟悉不过,Web开发⼈员可以控制视⼝的⼤⼩和⽐例
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
- apple-mobile-web-app-status-bar-style,开发过PWA应⽤的开发者应该很熟悉,为了⾃定义评估⼯具栏的颜⾊。
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
11.src和href的区别?
- src是指向外部资源的位置,指向的内容会嵌⼊到⽂档中当前标签所在的位置,在请求src资源时会将其指向的资源下载并应⽤到⽂档内,如js脚本,img图⽚和frame等元素。当浏览器解析到该元素时,会暂停其他资源的下载和处理,知道将该资源加载、编译、执⾏完毕,所以⼀般js脚本会放在底部⽽不是头部。
- href是指向⽹络资源所在位置(的超链接),⽤来建⽴和当前元素或⽂档之间的连接,当浏览器识别到它他指向的⽂件时,就会并⾏下载资源,不会停⽌对当前⽂档的处理。
知道img的srcset的作⽤是什么?(追问)
可以设计响应式图⽚,我们可以使⽤两个新的属性srcset 和 sizes来提供更多额外的资源图像和提示,帮助浏览器选择正确的⼀个资源。
srcset 定义了我们允许浏览器选择的图像集,以及每个图像的⼤⼩。
sizes 定义了⼀组媒体条件(例如屏幕宽度)并且指明当某些媒体条件为真时,什么样的图⽚尺⼨是最佳选择。
所以,有了这些属性,浏览器会:
- 查看设备宽度
- 检查 sizes 列表中哪个媒体条件是第⼀个为真
- 查看给予该媒体查询的槽⼤⼩
- 加载 srcset 列表中引⽤的最接近所选的槽⼤⼩的图像
srcset提供了根据屏幕条件选取图⽚的能⼒
<img src="clock-demo-thumb-200.png"
alt="Clock"
srcset="clock-demo-thumb-200.png 200w,
clock-demo-thumb-400.png 400w"
sizes="(min-width: 600px) 200px, 50vw">
还有哪⼀个标签能起到跟srcset相似作⽤?(追问)
<picture>
元素通过包含零或多个 <source>
元素和⼀个<img>
元素来为不同的显示/设备场景提供图像版本。浏览器会选择最匹配的⼦ <source>
元素如果没有匹配的,就选择 <img>
元素的 src 属性中的URL。然后,所选图像呈现在 <img>
元素占据的空间中
picture同样可以通过不同设备来匹配不同的图像资源
<picture>
<source srcset="/media/examples/surfer-240-200.jpg"
media="(min-width: 800px)">
<img src="/media/examples/painted-hand-298-332.jpg" />
</picture>
12.script标签中defer和async的区别?✨✨✨
- script :会阻碍 HTML 解析,只有下载好并执行完脚本才会继续解析 HTML。
- async:与defer同样是异步加载脚本,区别是脚本加载完毕后⽴即执⾏,这导致async属性下的脚本是乱序的,对于script有先后依赖关系的情况,并不适⽤。
- defer:浏览器指示脚本在⽂档被解析后执⾏,script被异步加载后并不会⽴刻执⾏,⽽是等待⽂档被解析完毕后执⾏。
13.(Drag)和放(Drop)
14.24个强大的HTML属性与实用小技巧
二.CSS
核心基础知识
语法
CSS 的核心功能是将 CSS 属性设定为特定的值。一个属性与值的键值对被称为声明(declaration)。
color: red;
而如果将一个或者多个声明用 {} 包裹起来后,那就组成了一个声明块(declaration block)。
{
color: red;
text-align: center;
}
声明块如果需要作用到对应的 HTML 元素,那还需要加上选择器。选择器和声明块组成了CSS 规则集(CSS ruleset),常简称为 CSS 规则。
span {
color: red;
text-align: center;
}
规则集中最后一条声明可以省略分号,但是并不建议这么做,因为容易出错。
CSS 中的注释:
/* 单行注释 */
/*
多行
注释
*/
在 CSS 文件中,除了注释、CSS 规则集以及 @规则 外,定义的一些别的东西都将被浏览器忽略。
@规则
CSS 规则是样式表的主体,通常样式表会包括大量的规则列表。但有时候也需要在样式表中包括其他的一些信息,比如字符集,导入其它的外部样式表,字体等,这些需要专门的语句表示。
而 @规则 就是这样的语句。CSS 里包含了以下 @规则:
- @namespace 告诉 CSS 引擎必须考虑XML命名空间。
- @media 如果满足媒体查询的条件则条件规则组里的规则生效。
- @page描述打印文档时布局的变化.
- @font-face 描述将下载的外部的字体。
- @keyframes 描述 CSS 动画的关键帧。
- @document 如果文档样式表满足给定条件则条件规则组里的规则生效。 (推延至 CSS Level 4 规范)
除了以上这几个之外,下面还将对几个比较生涩的 @规则 进行介绍。
@charset
@charset[1] 用于定义样式表使用的字符集。它必须是样式表中的第一个元素。如果有多个 @charset 被声明,只有第一个会被使用,而且不能在HTML元素或HTML页面的
注意:值必须是双引号包裹,且和
@charset "UTF-8";
平时写样式文件都没写 @charset 规则,那这个 CSS 文件到底是用的什么字符编码的呢?
某个样式表文件到底用的是什么字符编码,浏览器有一套识别顺序(优先级由高到低):
- 文件开头的 Byte order mark[2] 字符值,不过一般编辑器并不能看到文件头里的 BOM 值;
- HTTP 响应头里的 content-type 字段包含的 charset 所指定的值,比如:
Content-Type: text/css; charset=utf-8
- CSS 文件头里定义的 @charset 规则里指定的字符编码;
- 标签里的 charset 属性,该条已在 HTML5 中废除;
- 默认是 UTF-8。
@import
@import[3] 用于告诉 CSS 引擎引入一个外部样式表。
link 和 @import 都能导入一个样式文件,它们有什么区别嘛?
- link 是 HTML 标签,除了能导入 CSS 外,还能导入别的资源,比如图片、脚本和字体等;而 @import 是 CSS 的语法,只能用来导入 CSS;
- link 导入的样式会在页面加载时同时加载,@import 导入的样式需等页面加载完成后再加载;
- link 没有兼容性问题,@import 不兼容 ie5 以下;
- link 可以通过 JS 操作 DOM 动态引入样式表改变样式,而@import不可以。
@supports
@supports[4] 用于查询特定的 CSS 是否生效,可以结合 not、and 和 or 操作符进行后续的操作。
/* 如果支持自定义属性,则把 body 颜色设置为变量 varName 指定的颜色 */
@supports (--foo: green) {
body {
color: var(--varName);
}
}
@property
CSS @property,让不可能变可能
继承性
在 CSS 中有一个很重要的特性就是子元素会继承父元素对应属性计算后的值。比如页面根元素 html 的文本颜色默认是黑色的,页面中的所有其他元素都将继承这个颜色,当申明了如下样式后,H1 文本将变成橙色。
body {
color: orange;
}
h1 {
color: inherit;
}
设想一下,如果 CSS 中不存在继承性,那么我们就需要为不同文本的标签都设置一下 color,这样一来的后果就是 CSS 的文件大小就会无限增大。
CSS 属性很多,但并不是所有的属性默认都是能继承父元素对应属性的,那哪些属性存在默认继承的行为呢?一定是那些不会影响到页面布局的属性,可以分为如下几类:
- 字体系列属性:font-family[字体系列]、font-style[字体风格]、font-size[字体大小]、font-weight[字体粗细] 等;
- 文本系列属性:text-align、text-indent、text-decoration、text-shadow、letter-spacing、word-spacing、white-space、line-height、color 等;
- 列表布局属性:list-style[列表风格]、list-style-image、list-style-type、list-style-position 等;
- 其他属性:visibility、cursor 等;
对于其他默认不继承的属性也可以通过以下几个属性值来控制继承行为: - inherit:继承父元素对应属性的计算值;
- initial:应用该属性的默认值,比如 color 的默认值是 #000;
- unset:如果属性是默认可以继承的,则取 inherit 的效果,否则同 initial
- revert:效果等同于 unset,兼容性差。
视觉格式化模型
视觉格式化模型(Visual formatting model)是用来处理和在视觉媒体上显示文档时使用的计算规则。CSS 中一切皆盒子,而视觉格式化模型简单来理解就是规定这些盒子应该怎么样放置到页面中去,这个模型在计算的时候会依赖到很多的因素,比如:盒子尺寸、盒子类型、定位方案(是浮动还是定位)、兄弟元素或者子元素以及一些别的因素。
从上图中可以看到视觉格式化模型涉及到的内容很多,有兴趣深入研究的可以结合上图看这个 W3C 的文档 Visual formatting model[6]。所以这里就简单介绍下盒子类型。
盒子类型由 display 决定,同时给一个元素设置 display 后,将会决定这个盒子的 2 个显示类型(display type):
- outer display type(对外显示):决定了该元素本身是如何布局的,即参与何种格式化上下文;
- inner display type(对内显示):其实就相当于把该元素当成了容器,规定了其内部子元素是如何布局的,参与何种格式化上下文;
outer display type
对外显示方面,盒子类型可以分成 2 类:block-level box(块级盒子) 和 inline-level box(行内级盒子)。
依据上图可以列出都有哪些块级和行内级盒子:
- 块级盒子:display 为 block、list-item、table、flex、grid、flow-root 等;
- 行内级盒子:display 为 inline、inline-block、inline-table 等;
所有块级盒子都会参与 BFC,呈现垂直排列;而所有行内级盒子都参会 IFC,呈现水平排列。
除此之外,block、inline 和 inline-block 还有什么更具体的区别呢?
block
- 占满一行,默认继承父元素的宽度;多个块元素将从上到下进行排列;
- 设置 width/height 将会生效;
- 设置 padding 和 margin 将会生效;
inline
- 不会占满一行,宽度随着内容而变化;多个 inline 元素将按照从左到右的顺序在一行里排列显示,如果一行显示不下,则自动换行;
- 设置 width/height 将不会生效;
- 设置竖直方向上的 padding 和 margin 将不会生效;
inline-block
- 是行内块元素,不单独占满一行,可以看成是能够在一行里进行左右排列的块元素;
- 设置 width/height 将会生效;
- 设置 padding 和 margin 将会生效;
inner display type
对内方面,其实就是把元素当成了容器,里面包裹着文本或者其他子元素。container box 的类型依据 display 的值不同,分为 4 种:
- block container:建立 BFC 或者 IFC;
- flex container:建立 FFC;
- grid container:建立 GFC;
- ruby container:接触不多,不做介绍。
值得一提的是如果把 img 这种替换元素(replaced element)申明为 block 是不会产生 container box 的,因为替换元素比如 img 设计的初衷就仅仅是通过 src 把内容替换成图片,完全没考虑过会把它当成容器。
1.块元素和行内元素、行内块元素的区别
(一).块级元素
(1)常见的块元素有哪些?
常见的块元素有<h1>~<h6>
、<p>
、<div>
、<ul>
、<ol>
、<li>
等,其中 <div>
标签是最典型的块元素。
(2)块级元素有什么特点?
- 自己独占一行
- 高度,宽度、外边距以及内边距都可以控制。
- 宽度默认是容器(父级宽度)的 100%
- 是一个容器及盒子,里面可以放行内或者块级元素
(3)注意问题:
- 只有文字才能组成段落,因此 p 标签里面不能放块级元素,特别是 p 标签不能放 div。同理还有这些标签
- h1,h2,h3,h4,h5,h6,dt ,他们都是文字类块级标签,里面不能放其他块级元素。
(二)行内元素
(1)常见行内元素有哪些?
常见的行内元素有 <a>
、<strong>
、<b>
、<em>
、<i>
、<del>
、<s>
、<ins>
、<u>
、<span>
等,其中 标签最典型的行内元素,也称内联元素。
(2)行内元素有哪些特点?
- 相邻行内元素在一行上,一行可以显示多个
- 高、宽直接设置是无效的
- 只可以设置水平方向的内外边距
- 默认宽度就是它本身内容的宽度
- 行内元素只能容纳文本或则其他行内元素
(3)注意问题:
- 链接里面不能再放链接。
- 特殊情况 a 里面可以放块级元素,但是给 a 转换一下块级模式最安全。
(三)行内块元素
(1) 常见行内块儿元素有哪些?
在行内元素中有几个特殊的标签 <img />
、<input />
、<td>
,可以对它们设置宽高和对齐属性,有些资料可能会称它们为行内块元素。
(2)行内块元素有什么特点?
- 和相邻行内元素(行内块)在一行上,但是之间会有空白缝隙,一行可以显示多个。
- 默认宽度就是它本身内容的宽度。
- 高度,行高、外边距以及内边距都可以控制。
(四). 块级元素、行内元素和行内块元素的区别
(五) 块级元素、行内元素和行内块元素互转
- 块转行内:display:inline;
- 行内转块:display:block;
- 块、行内元素转换为行内块:display: inline-block;
2.CSS选择器
CSS选择器的解析是从上到下,从右向左解析,为了避免对所有元素进行解析
- 可继承的样式:font-size, font-family, color,ul,li,dl,dt,dd;
- 不可继承的样式:border, padding, margin, width, height👉
(1) CSS选择器种类
① id选择器
根据提供的唯一id号快速获取标签对象
用于充当label标签for属性的值:用户名:,表示单击此label标签时,id为userid的标签获得焦点
② 类选择器 (class )
③ 标签选择器 (h1)
④ 相邻选择器 /子选择器(ul>li)/ 后代选择器(li a)
相邻选择器分为直接相邻元素选择器 (h1+p)和普通相邻元素选择器 (h2 ~ h2)
层次选择器(父子、后代、兄弟、相邻)
⑤通配符选择器(*)
⑥属性选择器(a[rel = “XXX”])
⑦伪类选择器( :hover :first-child ···)
⑧伪元素选择器( :before :after ···)
⑨分组选择器
(2)CSS选择器的优先级
优先级由高到低 !important > 内联style > ID选择器 > 类选择器 > 标签选择器 > 通配符选择器>继承
优先级算法(权重)
- 元素标签(派生选择器):1
- class选择符:10
- id选择符:100
- 内联样式最大:1000
- 元素选择符的权值
- 继承得到的样式的优先级最低
- 比较多个权重相同的CSS选择器优先级,定义的位置决定一切。从位置上由高到低分为六级:
1.位于<head/>标签里的<style/>中所定义的CSS拥有最高级的优先权。
2. 位于 <style/>标签中的 @import 引入样式表所定义。
3. 由<link/>标签所引入的样式表定义。
4. 由<link/>标签所引入的样式表内的 @import 导入样式表定义。
5. 用户设定。
6. 浏览器默认。
- 同位置情况下样式定义最近者为准(优先级相同,选择最后出现的样式)👉
参考链接:你必须懂的css样式权重和优先级
(3)类选择的命名规范
传统起名法
• 布局类:header, footer, container, main, content, aside, page, section
• 交互类:tips, alert, modal, pop, panel, tabs, accordion, slide, overlay
• 状态类:active, current, checked, hover, fail, success, warn, error, on, off
• 包裹类:wrapper, inner, box, block
• ⼤⼩类:s, m, l, xl, large, small
• 主次类:primary, secondary, sub, minor
• 样式类:text-large, color-primary, m-0, mt-10
• 结构类:hd, bd, ft, top, bottom, left, right, middle, col, row, grid, span
• 列表类:list, item, field
• 导航类:nav, prev, next, breadcrumb, forward, back, indicator, paging, first, last
BEM 命名
[block]__[element]–[modifier]
• Block 我的容器是谁
• Elemnt 我是谁
• Modifier 我是什么形态
范例1:
• .nav__logo,.photo__img, .photo__img--framed
• .btn--secondary
• .hero__text--small, .hero__text--big
范例2:
<figure class="photo">
<img class="photo__img photo__img--framed" src="me.jpg">
<figcaption class="photo__caption photo__caption--large">Look at me!</figcaption>
</figure>
<style>
.photo__img{
/* photo⾥图⽚的默认样式*/
}
.photo__img--framed {
/* 在默认基础上新增的样式 */
}
.photo__caption--large {
/* 在默认基础上新增的样式 */
}
</style
3.CSS伪类和伪元素
(1)伪类和伪元素种类
CSS伪元素包含以下
- ::selection 选择被用户选取的元素部分
- :first-line 选择元素中的第一行
- :first-letter 选择元素中的第一个字符
- :after 在元素在该元素之后添加内容
- :before 在元素在该元素之前添加内容
CSS伪类
- :root 选择文档的根元素,等同于html元素
- :empty 选择没有子元素的元素
- :target 选取当前活动的目标元素
- :not(selector) 选择除 selector 元素意外的元素
- :enabled 选择可用的表单元素
- :disabled 选择禁用的表单元素
- :checked 选择被选中的表单元素
- :first-child 选取当前选择器下第一个元素。
- :last-child 和 first-child 相反,选取当前选择器下最后一个元素。
- :only-child 选取唯一子元素。如果一个元素的父元素只有它一个子元素,这个伪类就会生效。如果一个元素还有兄弟元素,这个伪类就不会对它生效。
- :only-of-type 选取唯一的某个类型的元素。如果一个元素的父元素里只有它一个当前类型的元素,这个伪类就会生效。这个伪类允许父元素里有其他元素,只要不和自己一样就可以。
条件伪类
- :lang():基于元素语言来匹配页面元素;
- :dir():匹配特定文字书写方向的元素;
- :has():匹配包含指定元素的元素;
- :is():匹配指定选择器列表里的元素;
- :not():用来匹配不符合一组选择器的元素;
- :where 深入了解 CSS 中的 :where() 和 :is() 函数
行为伪类
- :active:鼠标激活的元素;
- :hover: 鼠标悬浮的元素;
- ::selection:鼠标选中的元素;
状态伪类
- :target:当前锚点的元素;
- :link:未访问的链接元素;
- :visited:已访问的链接元素;
- :focus:输入聚焦的表单元素;
- :required:输入必填的表单元素;
- :valid:输入合法的表单元素;
- :invalid:输入非法的表单元素;
- :in-range:输入范围以内的表单元素;
- :out-of-range:输入范围以外的表单元素;
- :checked:选项选中的表单元素;
- :optional:选项可选的表单元素;
- :enabled:事件启用的表单元素;
- :disabled:事件禁用的表单元素;
- :read-only:只读的表单元素;
- :read-write:可读可写的表单元素;
- :blank:输入为空的表单元素;
- :current():浏览中的元素;
- :past():已浏览的元素;
- :future():未浏览的元素;
结构伪类
- :root:文档的根元素;
- :empty:无子元素的元素;
- :first-letter:元素的首字母;
- :first-line:元素的首行;
- :nth-child(n):元素中指定顺序索引的元素;
- :nth-last-child(n):元素中指定逆序索引的元素;;
- :first-child :元素中为首的元素;
- :last-child :元素中为尾的元素;
- :only-child:父元素仅有该元素的元素;
- :nth-of-type(n) :标签中指定顺序索引的标签;
- :nth-last-of-type(n):标签中指定逆序索引的标签;
- :first-of-type :标签中为首的标签;
- :last-of-type:标签中为尾标签;
- :only-of-type:父元素仅有该标签的标签;
静态伪类(只用于a标签)
- :link 指示这个“超链接”(即 a 元素里有一个 href 属性)未被访问
- :visited 指示这个“超链接”已被访问👉
动态伪类(使用时鼓励“LVHT”顺序)
- :focus 指示这个元素拥有输入“焦点”——即可以接受键盘输入,或通过某种方式可以激活
- :hover 指示当鼠标停留在这个元素上时,外观可以作相应改变
- :active 指示这个元素可以被用户输入“激活”,如,用户停留在一个超链接上,当点击鼠标时,这个链接就会“激活”👉
- 被点击访问过的超链接样式不再具有hover和active了, 解决方法是改变CSS属性的排列顺序: L-V-H-A(link,visited,hover,active)
伪类和伪元素的根本区别
- 单冒号(:)用于CSS3伪类,双冒号(::)用于CSS3伪元素。(伪元素由双冒号和伪元素名称组成)。伪类用一个冒号表示 :first-child,伪元素则使用两个冒号表示 ::first-line,为了向下兼容,现在的浏览器中伪元素选择器用单冒号和双冒号都可以,而新的在CSS3中引入的伪元素则不允许再支持旧的单冒号的写法。👉
- 它们是否创造了新的元素(抽象)。从我们模仿其意义的角度来看,如果需要添加新元素加以标识的,就是伪元素,反之,如果只需要在既有元素上添加类别的,就是伪类。
- 伪元素在一个选择器里只能出现一次,并且只能出现在末尾。
- 伪类则是像真正的类一样发挥着类的作用,没有数量上的限制,只要不是相互排斥的伪类,也可以同时使用在相同的元素上。
- 想让插入的内容出现在其它内容前,使用::before,否者,使用::after;
- 在代码顺序上,::after生成的内容也比::before生成的内容靠后。
- 如果按堆栈视角,::after生成的内容会在::before生成的内容之上。
面试回答作用
- 在css3中使用单冒号来表示伪类,用双冒号来表示伪元素。但是为了兼容已有的伪元素的写法,在一些浏览器中也可以使用单冒号来表示伪元素。
- 伪类一般匹配的是元素的一些特殊状态,如hover、link等,而伪元素一般匹配的特殊的位置,比如after、before等。
(2)特殊选择器的妙用
①巧用not选择器
有些情况下所有的元素都需要某些样式,唯独最后一个不需要,这时候使用not选择器将会特别方便
如下图:最后一个元素没有下边框
//html
<ul>
<li>
<span>单元格</span>
<span>内容</span>
</li>
<li>
<span>单元格</span>
<span>内容</span>
</li>
<li>
<span>单元格</span>
<span>内容</span>
</li>
<li>
<span>单元格</span>
<span>内容</span>
</li>
</ul>
//css
li:not(:last-child){
border-bottom: 1px solid #ebedf0;
}
2. 用where简化代码
当对多个元素应用相同的样式时,CSS 可能如下:
.parent div,
.parent .title,
.parent #article {
color: red;
}
这样代码看起来可读性不是很好,:where() 伪类这时就派上用场了。:where() 伪类函数接受选择器列表作为它的参数,将会选择所有能被该选择器列表中任何一条规则选中的元素。
上面的代码使用:where()就可以这么写:
.parent :where(div, .title, #article) {
color: red;
}
代码是不是看起来简洁了很多?
3. :empty 选择器
平时开发的时候数据都是通过请求接口获取的,也会存在接口没有数据的情况。这个时候正常的做法是给用户一个提示,让用户知道当前不是出 bug 了,而是确实没有数据。
一般的做法是我们人为的判断当前数据返回列表的长度是否为 0,如果为 0 则显示一个 “暂无数据” 给用户,反之则隐藏该提示。写过 Vue 的小伙伴是不是经常这么做:
<div>
<template v-if="datas.length">
<div v-for="data in datas"></div>
</template>
<template v-else>
<div>暂无数据</div>
</template>
</div>
但是有了 :empty 这个选择器后,你大可以把这个活交给 CSS 来干。
.container {
height: 400px;
width: 600px;
background-color: antiquewhite;
display: flex;
justify-content: center;
align-items: center;
}
.container:empty::after {
content: "暂无数据";
}
通过 :empty 选中内容为空的容器,然后通过伪元素为空容器添加提示。是不是方便很多呢?
1.CSS引入
(1)有哪些引入方式?通过link和@import引入有什么区别?(* )
- CSS引入方式有4种内联、内嵌、外链、导入
- 外链 link
①属于XHTML标签;
②除了可以加载css之外,还可以定义rss、rel等属性;
③没有兼容性问题;
④支持使用javascript改变样式(使用dom控制样式时的差别);
⑤页面被加载时,link会同时被加载。
⑥link方式的样式权重高于@import的权重。 - 导入@import
①是css提供的;
②@import只在IE 5以上才能识别;
③ 不支持通过javascript修改样式(使用dom控制样式时的差别);
④通过@import引用的CSS会等到页面被加载完再加载并且只能用于加载css,可能出现无样式网页。
(2)Style 标签写在 body 后和 body 前有什么区别?
- 一般情况下,页面加载时自上而下的。将style标签至于body之前,为的是先加载样式。
- 若是写在body标签之后,由于浏览器以逐行方式对html文档进行解析,当解析到写在写在文档尾部的样式表时,会导致浏览器停止之前的渲染,等待加载且解析样式表完成之后会重新渲染,在windows的IE下可能会出现FOUC现象(页面闪烁)。
(3)什么是 FOUC(Flash of Unstyled Content)?如何来避免 FOUC
- 当使用@import导入CSS时,会导致某些页面在IE出现奇怪的现象:没有样式的页面内容显示瞬间闪烁,这种现象被称为“文档样式暂时失效”,简称FOUC。
- 产生原因: 当样式表晚于结构性html加载时,加载到此样式表时,页面将会停止之前的渲染。等待此样式表被下载和解析后,再重新渲染页面,期间导致短暂的花屏现象。
- 解决办法: 只要在之间加入一个或者元素即可。👉
4.CSS盒模型✨
盒模型分类
- W3C盒模型(标准盒模型)
width = content
在标准模式下,一个块的总宽度= width + margin(左右) + padding(左右) + border(左右) - IE盒模型(怪异盒模型)
width = border + padding + content
一个块的总宽度 = width + margin - 转换盒模型
Css中默认的盒模型是W3C盒模型,两者间的转换可以通过设置属性box-sizing来转换
box-sizing: content-box; // W3C盒模型标准
box-sizing: border-box; // IE盒模型标准
盒子一些相关宽度
clientWidth = width+左右padding
offsetWidth = width + 左右padding + 左右boder
scrollWidth:获取指定标签内容层的真实宽度(可视区域宽度+被隐藏区域宽度)👉
边界塌陷
CSS 中存在一个 margin collapse,即边界塌陷或者说边界重叠。
只有普通文档流中块框的垂直外边距才会发生外边距合并。行内框、浮动框或绝对定位之间的外边距不会合并。👉
①并排 DIV 边界塌陷(兄弟)
对于上下两个并排的 DIV 块而言,上面 DIV 的 margin-bottom 和下面 DIV 的 margin-top 会塌陷,会取上下两者 margin 里最大值作为显示值,只设置单个margin。👉
②包含元素盒子塌陷(父子)
父级div中没有border,padding,inlinecontent,子级div的margin会一直向上找,直到找到某个标签包括border,padding,inline content(文本)中的其中一个,然后按此div 进行margin。👉
解决方法
为父盒子设置border,为外层添加border后父子盒子就不是真正意义上的贴合 (可以设置成透明:border: 1px solid transparent)
为父盒子添加overflow: hidden;
为父盒子设定padding值;
为父盒子添加position:fixed;👉
负值作用
负 marign实现元素的水平垂直居中
负 marign隐藏列表 li 首尾多余的边框
负 text-indent 实现文字的隐藏
负的 z-index 参与层叠上下文排序
定位中的left、right、top、bottom👉
7.display 布局(行内元素和块级元素)
值 | 描述 |
none | 元素会被隐藏,不显示 |
inline | 元素会被设置为内联元素,内部按行从左向右排列(元素前后没有换行符) |
block | 元素会被设置为块级元素,内部按列从上到下排列(元素前后带有换行符) |
inline-block | 元素会被设置为行内块级元素,不会独占一行的块级元素 |
list-item | 元素会作为列表显示 |
table | 元素会作为块级表格来显示(类似table),表格前后带有换行符 |
flex | 元素会进入flex布局模式 |
2.inline、block、inline-block三者区别 | |
block块级特点: |
- 每个块级元素都从新的一行开始,并且其后的元素也另起一行。(一个块级元素独占一行)
- 元素的高度、宽度、行高以及顶和底边距都可设置。
- 元素宽度在不设置的情况下,是它本身父容器的100%(和父元素的宽度一致),除非设定一个宽度。
inline内联特点:
- 和其他元素都在一行上;
- 元素的高度、宽度及顶部和底部边距不可设置;
- 元素的宽度就是它包含的文字或图片的宽度,不可改变。
inline-block 特点:
- inline-block内联块状元素同时具备内联元素、块状元素的特点。
- 和其他元素都在一行上;
- 元素的高度、宽度、行高以及顶和底边距都可设置。
3.使用 display:inline-block 会产生什么问题?又如何解决?(*)
两个inline-block元素放到一起会产生一段空白。
产生空白的原因
元素被当成行内元素放置的时候,元素之间的空白符(空格,回车换行等)都会被浏览器处理,根据CSS中空白属性的处理方式(否则是正常,合并多余空白),原来HTML代码中的回车换行被转成一个空白符,在字体不为0的情况下,空白符较长一定长度,所以inline-block的元素之间就出现了空隙。
解决办法
- 将子元素标签的结束符和下一个标签的开始符写在同一行或把所有子标签写在同一行
- 父元素中设置字体大小:0,在子元素上重置正确的字体大小
- 为子元素设置float:left
该布局提供了一种更高效的方法对容器中的项目进行布局、对齐和分配空间,他没有方向上的限制,可以由开发人员自由操作(子元素的 vertical-align、float、clear 属性会失效)。
9.overflow溢出
- scroll:必定出现滚动条
- auto:子元素内容大于父元素时出现滚动条
- visible:溢出的内容出现在父元素之外
- hidden:溢出时隐藏👉
如何实现:单行文本溢出加 …(*)
white-space: nowrap; /* 首先,强制文本不换行;*/
overflow: hidden; /*其次,隐藏溢出;*/
text-overflow: ellipsis; /*最后,对溢出的文本用 ellipsis 省略号代替。*/
全屏滚动的原理?需要哪些css属性?
原理
类似于轮播图,整体元素一直排列下去,假设有5个需要展示的全屏页面,那么高度将会是500%,但我们只能展示100%,剩下的内容可以通过transform进行Y轴定位,也可以通过margin-top实现
涉及css属性
overflow:hidden | transition:all 1000ms ease
10.格式化上下文
格式化上下文(Formatting Context)是 CSS2.1 规范中的一个概念,大概说的是页面中的一块渲染区域,规定了渲染区域内部的子元素是如何排版以及相互作用的。
不同类型的盒子有不同格式化上下文,大概有这 4 类:
- BFC (Block Formatting Context) 块级格式化上下文;
- IFC (Inline Formatting Context) 行内格式化上下文;
- FFC (Flex Formatting Context) 弹性格式化上下文;
- GFC (Grid Formatting Context) 格栅格式化上下文;
其中 BFC 和 IFC 在 CSS 中扮演着非常重要的角色,因为它们直接影响了网页布局,所以需要深入理解其原理。
(一)BFC块级格式上下文
(1)什么是BFC?
BFC(Block formatting context)直译为"块级格式化上下文"。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。
在解释什么是BFC之前,我们需要先知道Box、Formatting Context的概念。
Box:css布局的基本单位
Box 是 CSS 布局的对象和基本单位, 直观点来说,就是一个页面是由很多个 Box 组成的。元素的类型和 display 属性,决定了这个 Box 的类型。 不同类型的 Box, 会参与不同的 Formatting Context(一个决定如何渲染文档的容器),因此Box内的元素会以不同的方式渲染。让我们看看有哪些盒子:
- block-level box:display 属性为 block, list-item, table 的元素,会生成 block-level box。并且参与 block fomatting context;
- inline-level box:display 属性为 inline, inline-block, inline-table 的元素,会生成 inline-level box。并且参与 inline formatting context;
- run-in box: css3 中才有, 这儿先不讲了。
Formatting Context
Formatting context 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。最常见的 Formatting context 有 Block fomatting context (简称BFC)和 Inline formatting context (简称IFC)。
BFC是一个独立的布局环境,其中的元素布局是不受外界的影响,并且在一个BFC中,块盒与行盒(行盒由一行中所有的内联元素所组成)都会垂直的沿着其父元素的边框排列。
(2)BFC的布局规则
- 内部的Box会在垂直方向,一个接一个地放置。
- Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠。
- 每个盒子(块盒与行盒)的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
- BFC的区域不会与float box重叠。
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
- 计算BFC的高度时,浮动元素也参与计算。
(3)如何创建BFC
- 根元素 → 根元素(html)就是最大的BFC
- 定位元素, position:fixed/absolute
- 浮动元素, float 除 none 以外的值
- display 为以下其中之一的值inline-block、table-cell、table-caption
- overflow不为visible (hidden,auto,scroll)
(4)BFC的作用及原理
①利用BFC避免margin重叠。
<!DOCTYPE html>
<html lang="en">
<head>
<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>防止margin重叠</title>
</head>
<style>
*{
margin: 0;
padding: 0;
}
p {
color: #f55;
background: yellow;
width: 200px;
line-height: 100px;
text-align:center;
margin: 30px;
}
</style>
<body>
<p>看看我的 margin是多少</p>
<p>看看我的 margin是多少</p>
</body>
</html>
页面生成的效果就是这样的:
根据第二条,属于同一个BFC的两个相邻的Box会发生margin重叠,所以我们可以设置,两个不同的BFC,也就是我们可以让把第二个p用div包起来,然后激活它使其成为一个BFC。
<!DOCTYPE html>
<html lang="en">
<head>
<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>防止margin重叠</title>
</head>
<style>
*{
margin: 0;
padding: 0;
}
p {
color: #f55;
background: yellow;
width: 200px;
line-height: 100px;
text-align:center;
margin: 30px;
}
div{
overflow: hidden;
}
</style>
<body>
<p>看看我的 margin是多少</p>
<div>
<p>看看我的 margin是多少</p>
</div>
</body>
</html>
问:两个div上下排列,都设margin,有什么现象?
- 都正取大
- 一正一负相加
问:为什么会有这种现象?你能解释一下吗?
是由块级格式上下文决定的,BFC,元素在 BFC 中会进行上下排列,然后垂直距离由 margin 决定,并且会发生重叠,具体表现为同正取最大的,同负取绝对值最大的,一正一负,相加。
BFC 是页面中一个独立的隔离容器,内部的子元素不会影响到外部的元素。
②自适应两栏布局
根据:
- 每个盒子的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
- 应用原理:BFC 的区域不会和浮动区域重叠,所以就可以把侧边栏固定宽度且左浮动,而对右侧内容触发 BFC,使得它的宽度自适应该行剩余宽度。
<!DOCTYPE html>
<html lang="en">
<head>
<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>
</head>
<style>
*{
margin: 0;
padding: 0;
}
body {
width: 100%;
position: relative;
}
.left {
width: 100px;
height: 150px;
float: left;
background: rgb(139, 214, 78);
text-align: center;
line-height: 150px;
font-size: 20px;
}
.right {
height: 300px;
background: rgb(170, 54, 236);
text-align: center;
line-height: 300px;
font-size: 40px;
}
</style>
<body>
<div class="left">LEFT</div>
<div class="right">RIGHT</div>
</body>
</html>
又因为:
BFC的区域不会与float box重叠。
所以我们让right单独成为一个BFC
<!DOCTYPE html>
<html lang="en">
<head>
<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>
</head>
<style>
*{
margin: 0;
padding: 0;
}
body {
width: 100%;
position: relative;
}
.left {
width: 100px;
height: 150px;
float: left;
background: rgb(139, 214, 78);
text-align: center;
line-height: 150px;
font-size: 20px;
}
.right {
overflow: hidden;
height: 300px;
background: rgb(170, 54, 236);
text-align: center;
line-height: 300px;
font-size: 40px;
}
</style>
<body>
<div class="left">LEFT</div>
<div class="right">RIGHT</div>
</body>
</html>
(3)清除浮动
当我们不给父节点设置高度,子节点设置浮动的时候,会发生高度塌陷,这个时候我们就要清除浮动。
<!DOCTYPE html>
<html lang="en">
<head>
<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>清除浮动</title>
</head>
<style>
.par {
border: 5px solid rgb(91, 243, 30);
width: 300px;
}
.child {
border: 5px solid rgb(233, 250, 84);
width:100px;
height: 100px;
float: left;
}
</style>
<body>
<div class="par">
<div class="child"></div>
<div class="child"></div>
</div>
</body>
</html>
这个时候我们根据最后一条:
- 计算BFC的高度时,浮动元素也参与计算。
给父节点激活BFC
<!DOCTYPE html>
<html lang="en">
<head>
<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>清除浮动</title>
</head>
<style>
.par {
border: 5px solid rgb(91, 243, 30);
width: 300px;
overflow: hidden;
}
.child {
border: 5px solid rgb(233, 250, 84);
width:100px;
height: 100px;
float: left;
}
</style>
<body>
<div class="par">
<div class="child"></div>
<div class="child"></div>
</div>
</body>
</html>
页面
总结:BFC内部的元素和外部的元素绝对不会互相影响,因此, 当BFC外部存在浮动时,它不应该影响BFC内部Box的布局,BFC会通过变窄,而不与浮动有重叠。同样的,当BFC内部有浮动时,为了不影响外部元素的布局,BFC计算高度时会包括浮动的高度。避免margin重叠也是这样的一个道理。👉
(二)IFC行内格式上下文
IFC 的形成条件非常简单,块级元素中仅包含内联级别元素,需要注意的是当IFC中有块级元素插入时,会产生两个匿名块将父元素分割开来,产生两个 IFC。
- 内部的盒子一个接着一个地排列,起点是包含块的顶点。
- 如果一行放不下内容,那么会被“拆”开放到下一行。
- 只有水平方向上的 Margin 会在盒子中保留。
- Padding 和 Border 不会撑开行高。
IFC 渲染规则 - 子元素在水平方向上一个接一个排列,在垂直方向上将以容器顶部开始向下排列;
- 节点无法声明宽高,其中 margin 和 padding 在水平方向有效在垂直方向无效;
节点在垂直方向上以不同形式对齐; - 能把在一行上的框都完全包含进去的一个矩形区域,被称为该行的线盒(line box)。线盒的宽度是由包含块(containing box)和与其中的浮动来决定;
- IFC 中的 line box 一般左右边贴紧其包含块,但 float 元素会优先排列。
- IFC 中的 line box 高度由 line-height 计算规则来确定,同个 IFC 下的多个 line box 高度可能会不同;
- 当内联级盒子的总宽度少于包含它们的 line box 时,其水平渲染规则由 text-align 属性值来决定;
- 当一个内联盒子超过父元素的宽度时,它会被分割成多盒子,这些盒子分布在多个 line box 中。如果子元素未设置强制换行的情况下,inline box 将不可被分割,将会溢出父元素。
针对如上的 IFC 渲染规则,你是不是可以分析下下面这段代码的 IFC 环境是怎么样的呢?
<p>It can get <strong>very complicated</storng> once you start looking into it.</p>
对应上面这样一串 HTML 分析如下:
- p 标签是一个 block container,对内将产生一个 IFC;
- 由于一行没办法显示完全,所以产生了 2 个线盒(line box);线盒的宽度就继承了 p 的宽度;高度是由里面的内联盒子的 line-height 决定;
- It can get:匿名的内联盒子;
- very complicated:strong 标签产生的内联盒子;
- once you start:匿名的内联盒子;
- looking into it.:匿名的内联盒子。
IFC 应用场景
- 水平居中:当一个块要在环境中水平居中时,设置其为 inline-block 则会在外层产生 IFC,通过 text-align 则可以使其水平居中。
- 垂直居中:创建一个 IFC,用其中一个元素撑开父元素的高度,然后设置其 vertical-align: middle,其他行内元素则可以在此父元素下垂直居中。
偷个懒,demo 和图我就不做了。
12.z-index层叠上下文
(1)z-index层叠的介绍
- z-index 可以解决元素之间覆盖顺序的问题,设置它的层叠顺序。
- 如果元素是没有定位的,对其设置的 z-index 会是无效的。
(2)元素层叠时,覆盖关系准则(*)
① 同父同级元素
- 当具有明显的层叠水平标示时,如识别的z-index值
- z-index大的覆盖小的,数值越大,越靠近视觉点。
- z-index相同时,在DOM流中处于后面会覆盖前面。
- 都没有设置 z-index时,使用默认值,一个定位一个没有定位,那么定位覆盖未定位元素。
- 都没有定位且发生位置重合现象时,在DOM流中处于后面会覆盖前面。
②父子层级元素
- 不同父元素,只要父元素越大,那么整体就越靠近视觉点,而不管其子元素大小情况。
- 如果父元素 z-index 有效,那么子元素无论是否设置 z-index 都和父元素一致,会在父元素上方;
- 如果父元素 z-index 失效(未定位或者使用默认值),那么定位子元素的 z-index 设置生效。
(3)层叠上下文的创建
① 根层叠上下文
指的是页面根元素,也就是滚动条的默认的始作俑者元素。这就是为什么,绝对定位元素在left/top等值定位的时候,如果没有其他定位元素限制,会相对浏览器窗口定位的原因。👉
②定位元素与传统层叠上下文
对于包含有position:relative/position:absolute/position:fixed的定位元素,当其z-index值不是auto的时候,会创建层叠上下文。👉
③CSS3与新时代的层叠上下文
CSS3的出现除了带来了新属性,同时还对过去的很多规则发出了挑战。例如,👉CSS3 transform对overflow隐藏对position:fixed定位的影响等。而这里,层叠上下文这一块的影响要更加广泛与显著。
如下:
- z-index值不为auto的flex项(父元素display:flex|inline-flex).
- 元素的opacity值不是1。
- 元素的transform值不是none。
- 元素mix-blend-mode值不是normal。
- 元素的filter值不是none。
- 元素的isolation值是isolate。
- will-change指定的属性值为上面任意一个。
- 元素的-webkit-overflow-scrolling设为touch。
13.CSS浏览器兼容性
浏览器CSS样式初始化
由于每个浏览器的css默认样式不尽相同,所以最简单有效的方式就是对其进行初始化,在所有CSS开始前,先把marin和padding都设为0,以防不同浏览器的显示效果不一样(推荐初始化库Normalize.css)。
浏览器私有属性
- 我们经常会在某个CSS的属性前添加一些前缀,比如-webkit-,-moz- ,-ms-,这些就是浏览器的私有属性,出现私有属性的原因是制定HTML和CSS标准的组织W3C动作是很慢的。
- 通常,有W3C组织成员提出一个新属性,比如说圆角border-radius,大家都觉得好,但W3C制定标准,要走很复杂的程序,审查等。而浏览器商市场推广时间紧,如果一个属性已经够成熟了,就会在浏览器中加入支持。
为避免日后W3C公布标准时有所变更,会加入一个私有前缀,比如-webkit-border-radius,通过这种方式来提前支持新属性。等到日后W3C公布了标准,border-radius的标准写法确立之后,再让新版的浏览器支持border-radius这种写法。常用的前缀有:
- -moz代表firefox浏览器私有属性
- -ms代表IE浏览器私有属性
- -webkit代表chrome、safari私有属性
- -o代表opera私有属性
对于私有属性的顺序要注意,把标准写法放到最后,兼容性写法放到前面
-webkit-transform:rotate(-3deg); /*为Chrome/Safari*/
-moz-transform:rotate(-3deg); /*为Firefox*/
-ms-transform:rotate(-3deg); /*为IE*/
-o-transform:rotate(-3deg); /*为Opera*/
transform:rotate(-3deg);
CSS hack
有时我们需要针对不同的浏览器或不同版本写特定的CSS样式,这种针对不同的浏览器/不同版本写相应的CSS code的过程,叫做CSS hack,写法大致归纳为3种:条件hack、属性级hack、选择符级hack。👉
自动化插件
- Autoprefixer是一款自动管理浏览器前缀的插件,它可以解析CSS文件并且添加浏览器前缀到CSS内容里,使用Can I Use(caniuse网站)的数据来决定哪些前缀是需要的。
- 把Autoprefixer添加到资源构建工具(例如Grunt)后,可以完全忘记有关CSS前缀的东西,只需按照最新的W3C规范来正常书写CSS即可。如果项目需要支持旧版浏览器,可修改browsers参数设置 。
- 目前webpack、gulp、grunt都有相应的插件,别再让CSS兼容性浪费你的时间。👉
常见的CSS兼容性问题有哪些
- 不同浏览器的标签默认的padding/margin不同,通过初始化css样式可以解决 *{ margin:0;padding:0px; }
- IE6双边距BUG
- 设置较小高度标签(一般小于10px)在IE6,IE7中高度超出自己设置的高度 ,通过设置overflow:hidden;或者设置行高line-height小于你设置的高度
- IE下,可以使用获取常规属性的方法来获取自定义属性,也可以使用getAttribute()获取自定义属性
- Chrome中文界面下默认会将小于12px的文本强制为12px 通过加入css属性 -webkit-text-size-adjust:none;可以解决,或者使用transform中的缩放属性
- 超链接访问过后hover样式就不出现,因为被点击访问过的超链接样式不再具有hover和active了 ,解决方法是改变css属性的排列属性:L-V-H-A a:link{} → a:visited{} → a:hover{} → a:active{}
- IE下,event对象有x,y属性,但是没有pageX,pageY属性,但没有x,y属性 解决方式:通过条件- png24位的图片在IE6浏览器上出现背景,解决方案是做出PNG8👉
15.em\px\rem区别?
- px:绝对单位,页面按精确像素展示。
- em:相对单位,基准点为父节点字体的大小,如果⾃身定义了font-size按⾃身来计算(浏览器默认字体是16px),整个页面内1em不是⼀个固定的值
- rem:相对单位,可理解为”root em”, 相对根节点html的字体大小来计算,CSS3新加属性,chrome/firefox/IE9+支持
口语表达
rem和em单位一样,都是一个相对单位,不同的是em是相对于元素的父元素的font-size进行计算,rem是相对于 根元素html的font-size进行计算。
1em相当于当前元素父元素的font-size
<style>
.box {
font-size: 18px;
}
.box .children {
width: 2rem; // 相当于2 * 18 = 36px
}
</style>
<div class="box">
<span class="children">里面</span>
</div>
参考阅读:px、rpx、em、rem 、vw/vh、百分比的区别?
18.学习布局
(一)布局方式
1.流式布局
在 CSS 的世界中,会把内容按照从左到右、从上到下的顺序进行排列显示。正常情况下会把页面分割成一行一行的显示,而每行又可能由多列组成,所以从视觉上看起来就是从上到下从左到右,而这就是 CSS 中的流式布局,又叫文档流。文档流就像水一样,能够自适应所在的容器,一般它有如下几个特性:
- 块级元素默认会占满整行,所以多个块级盒子之间是从上到下排列的;
- 内联元素默认会在一行里一列一列的排布,当一行放不下的时候,会自动切换到下一行继续按照列排布;
如何脱离文档流呢?
脱流文档流指节点脱流正常文档流后,在正常文档流中的其他节点将忽略该节点并填补其原先空间。文档一旦脱流,计算其父节点高度时不会将其高度纳入,脱流节点不占据空间。有两种方式可以让元素脱离文档流:浮动和定位。
- 使用浮动(float)会将元素脱离文档流,移动到容器左/右侧边界或者是另一个浮动元素旁边,该浮动元素之前占用的空间将被别的元素填补,另外浮动之后所占用的区域不会和别的元素之间发生重叠;
- 使用绝对定位(position: absolute;)或者固定定位(position: fixed;)也会使得元素脱离文档流,且空出来的位置将自动被后续节点填补。
2.浮动布局
- 有两个取值:left(左浮动)和right(右浮动)。
- 浮动的框可以向左或向右移动,直到它的外边缘碰到包含框或另一个浮动框的边框为止。
- 由于浮动框不在文档的普通流中,所以文档的普通流中的块框表现得就像浮动框不存在一样。👉
优点
最初的优点就是在图文混排的时候可以很好的使文字周围在图片周围。另外当元素浮动了起来之后,它具有块级元素的一些性质例如可以设置宽高等,但它与inline- block还是有一些区别的,第一个就是关于横向排序的时候,float可以设置方向而inline-block方向是固定的;还有一个就是inline-block在使用时有时会有空白间隙的问题。👉
缺点
最明显的缺点就是浮动元素一旦脱离了文档流,就无法撑起父元素,会造成父级元素高度塌陷为0(盒子塌陷)。
▲ 注意:设置元素浮动后,该元素的display值会变为block👉
清除浮动(*)
- 盒子大小写死,给每个盒子设定固定的width和height,直到合适为止,非自适应
- 给浮动元素父级设置高度
- 父级元素触发BFC(Float,Overflow: Hidden | Visible,Display: Flex | Grid)
(1)【Float父级同时浮动(需要给父级同级元素添加浮动)】
(2)【父级设置成inline-block,其margin: 0 auto居中方式失效】
<div class="parent" style="overflow:hidden">
<div class="f"></div>
</div>
- 添加额外标签:clear清除浮动(添加空div法)在浮动元素下方添加空div,并给该元素写css样式:{clear:both;height:0;overflow:hidden;}
<div class="parent"> //添加额外标签并且添加clear属性
<div class="f"></div>
</div>
<div style="clear:both"></div>
- 万能清除法 after伪类 清浮动(现在主流方法,推荐使用)
//添加:after伪元素
.parent:after{
content: ''; /* 设置添加子元素的内容是空 */
display: block; /* 设置添加子元素为块级元素 */
height: 0; /* 设置添加的子元素的高度0 */
visibility: hidden; /* 设置添加子元素看不见 */
clear: both; /* 设置clear:both */
}
<div class="parent">
<div class="f"></div>
</div>
3.定位布局
static(普通流定位)
默认定位👉
relative(相对定位)
相对本元素的左上角进行定位(相对于自身位置进行定位),本元素需要设置position为relative,top、left、bottom、right都可以有值。
虽然经过定位后,位置可能会移动,但是本元素并没有脱离文档流,还占有原来的页面空间。👉
absolute(绝对定位)
相对于祖代中有relative(相对定位)并且离本元素层级关系上是最近的元素的左上角进行定位,如果在祖代元素中没有有relative定位的,就默认相对于body进行定位。
元素定位后生成一个块级框,而不论原来它在正常流中生成何种类型的框。
绝对定位是脱离文档流的,与浮动定位是一样的效果,会压在非定位元素的上方。👉
fixed(固定定位)
类似于absolute定位,但是是相对于浏览器窗口进行定位👉
inherit
继承父级元素position属性值👉
sticky (额外补充)
粘性的-集合了flex和relative,参考👉杀了个回马枪,还是说说position:sticky吧
4.表格布局
5.弹性布局
(1).flex布局属性简介
容器属性(6个)
flex-direction 决定主轴方向(容器排列方向)
flex-direction: row | row-reverse | column | column-reverse;
flex-wrap 如果一条轴线排不下,定义换行规则
flex-wrap: nowrap | wrap | wrap-reverse;
flex-flow flex-direction和flex-wrap的简写形式
flex-flow: flex-direction||flex-wrap;
justify-content 定义容器在主轴上的对齐方式
justify-content: flex-start | flex-end | center | space-between | space-around;
align-items 定义容器在交叉轴上的对齐方式
align-items: flex-start | flex-end | center | baseline | stretch;
align-content 定义多根轴线的对齐方式,如果容器只有一根轴线,该属性不起作用
align-content: flex-start | flex-end | center | space-between | space-around |;👉
弹性盒布局,CSS3 的新属性,用于方便布局,比如垂直居中
flex属性是 flex-grow、flex-shrink 和 flex-basis 的简写
项目属性(6个)
- order 定义项目的排列顺序,数值越小,排列越靠前,默认为0
- flex-grow 定义项目的放大比例,默认为0(即如果存在剩余空间,也不放大)
- flex-shrink 定义项目的缩小比例,默认为1(即如果空间不足,该项目将缩小)
- flex-basis 定义了在分配多余空间之前,项目占据的主轴空间。默认值为auto(项目本来大小)
- align-self允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性,默认值为auto(表示继承父元素align-items属性,如果没有父元素,等同于stretch)
align-self: auto | flex-start | flex-end | center | baseline | stretch - flex 是flex-grow、flex-shrink和flex-basis的简写,默认值为 0 1 auto
flex: none | [ ‘flex-grow’ ‘flex-shrink’? || ‘flex-basis’]
该属性有两个快捷值: auto(1 1 auto) 和 none(0 0 auto)建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值👉
(2)使用实现特殊需求
①使用flex布局实现智能固定底部
内容不够时,规则说明要处于底部,内容足够多时,规则说明随着内容往下沉,大家一定也遇到过类似的需求,使用flex巧妙实现布局。
//html
<div class="container">
<div class="main">我是内容区域</div>
<div class="footer">规则说明</div>
</div>
//
.container{
height: 100vh;
/* 关键css处 */
display: flex;
flex-direction: column;
justify-content: space-between;
}
.main{
/* 关键css处 */
flex: 1;
background-image: linear-gradient(45deg, #ff9a9e 0%, #fad0c4 99%, #fad0c4 100%);
display: flex;
align-items: center;
justify-content: center;
color: #fff;
}
.footer{
padding: 15px 0;
text-align: center;
color: #ff9a9e;
font-size: 14px;
}
6.栅格布局
面试官:介绍一下CSS中的Grid网格布局?
7.响应式布局
参考阅读:
关于媒体查询
- 是什么
媒体查询是指针对不同的设备、特定的设备特征或者参数进行定制化的修改网站的样式。
媒体查询由一个可选的媒体类型和零个或多个使用媒体功能的限制样式表范围的表达式组成,例如宽度、高度和颜色。媒体查询在 CSS3 中出现,允许内容的呈现针对一个特定范围的输出设备而进行裁剪,而不必改变内容本身,非常适合 web 网页应对不同型号的设备做出对应的响应适配。 - 怎么使用?
你可以通过给 加上 media 属性来指定该样式文件只能对什么设备生效,不指定的话默认是 all,即对所有设备都生效:
<link rel="stylesheet" src="styles.css" media="screen" />
<link rel="stylesheet" src="styles.css" media="print" />
都支持哪些设备类型?
- all:适用于所有设备;
- print:适用于在打印预览模式下在屏幕上查看的分页材料和文档;
- screen:主要用于屏幕;
- speech:主要用于语音合成器。
需要注意的是:通过 media 指定的 资源尽管不匹配它的设备类型,但是浏览器依然会加载它。
除了通过 让指定设备生效外,还可以通过 @media 让 CSS 规则在特定的条件下才能生效。响应式页面就是使用了 @media 才让一个页面能够同时适配 PC、Pad 和手机端。
媒体查询支持逻辑操作符:
- and:查询条件都满足的时候才生效;
- not:查询条件取反;
- only:整个查询匹配的时候才生效,常用语兼容旧浏览器,使用时候必须指定媒体类型;
- 逗号或者 or:查询条件满足一项即可匹配;
媒体查询还支持众多的媒体特性,使得它可以写出很复杂的查询条件:
/* 用户设备的最小高度为680px或为纵向模式的屏幕设备 */
@media (min-height: 680px), screen and (orientation: portrait) {}
总之,媒体查询包含一个可选的媒体类型和,满足 CSS3 规范的条件下,包含零个或多个表达式,这些表达式描述了媒体特征,最终会被解析为 true 或 false。如果媒体查询中指定的媒体类型匹配展示文档所使用的设备类型,并且所有表达式的值都是 true,那么该媒体查询的结果为 true,那么媒体查询内的样式会生效。
<!-- link 元素中的 CSS 媒体查询 -->
<link rel="stylesheet" media="(max-width: 800px)" href="example.css">
<!-- 样式表中的 CSS 媒体查询 -->
<style>
@media (max-width: 600px) {
.facet_sidebar {
display: none;
}
}
</style>
【通用媒体查询】
/* Smartphones (portrait and landscape) ----------- */
@media only screen
and (min-device-width : 320px) and (max-device-width : 480px) {
/* Styles */
}
/* Smartphones (landscape) ----------- */
@media only screen and (min-width : 321px) {
/* Styles */
}
/* Smartphones (portrait) ----------- */
@media only screen and (max-width : 320px) {
/* Styles */
}
/* iPads (portrait and landscape) ----------- */
@media only screen and (min-device-width : 768px) and (max-device-width : 1024px) {
/* Styles */
}
/* iPads (landscape) ----------- */
@media only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : landscape) {
/* Styles */
}
/* iPads (portrait) ----------- */
@media only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : portrait) {
/* Styles */
}
/* Desktops and laptops ----------- */
@media only screen and (min-width : 1224px) {
/* Styles */
}
/* Large screens ----------- */
@media only screen and (min-width : 1824px) {
/* Styles */
}
/* iPhone 4 ----------- */
@media only screen and (-webkit-min-device-pixel-ratio:1.5), only screen and (min-device-pixel-ratio:1.5) {
/* Styles */
}
MDN:众多的媒体特性
(二)布局实践
1.水平垂直居中
1.CSS 实现元素水平垂直居中的 N 种方式 2.CSS 垂直居中的正确打开方式 3.做了几年前端,今天居然发现垂直居中都做错了!
CSS2
水平居中
- div + margin: auto;
- span + text-align
垂直居中
- 使用 position 然后 left/top 和 margin 的方式垂直居中(已知宽高和未知宽高)
- 使用 position + margin
- 使用 display: table-cell;
(1).已知宽高,进行水平垂直居中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.outer {
position: relative;
width: 400px;
height: 600px;
background: blue;
}
.inner {
position: absolute;
width: 200px;
height: 300px;
background: red;
left: 50%;
top: 50%;
margin: -150px 0 0 -100px;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner"></div>
</div>
</body>
</html>
(2).宽高未知,比如 内联元素,进行水平垂直居中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.outer {
width: 400px;
height: 600px;
/* background: blue; */
border: 1px solid red;
background-color: transparent;
position: relative;
}
.inner {
position: absolute;
background: red;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
<div class="outer">
<span class="inner">我想居中显示</span>
</div>
</body>
</html>
(3).绝对定位的 div 水平垂直居中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.outer {
width: 400px;
height: 600px;
/* background: blue; */
border: 1px solid red;
background-color: transparent;
position: relative;
}
.inner {
position: absolute;
background: red;
left: 0;
right: 0;
bottom: 0;
top: 0;
width: 200px;
height: 300px;
margin: auto;
border: 1px solid blue;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner">我想居中显示</div>
</div>
</body>
</html>
(4).图片和其他元素使用 display: table-cell; 进行垂直居中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.outer {
width: 400px;
height: 600px;
/* background: blue; */
border: 1px solid red;
background-color: transparent;
display: table-cell;
vertical-align: middle;
}
.inner {
background: red;
width: 200px;
height: 300px;
border: 1px solid blue;
margin: 0 auto;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner">我想居中显示</div>
</div>
</body>
</html>
CSS3
垂直、水平居中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.outer {
width: 400px;
height: 600px;
display: flex;
/* 垂直居中 */
align-items: center;
/* 水平居中 */
justify-content: center;
border: 1px solid red;
background-color: transparent;
}
.inner {
background: red;
width: 200px;
height: 300px;
border: 1px solid blue;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner">我想居中显示</div>
</div>
</body>
</html>
2.常用布局
布局一:两栏布局(边栏定宽主栏自适应)
方法一:float + overflow(BFC 原理)
方法二:float + margin
方法三:flex
方法四:grid
布局二:三栏布局(两侧栏定宽主栏自适应)
方法一:圣杯布局
方法二:双飞翼布局
方法三:float + overflow(BFC 原理)
方法四:flex
方法五:grid
布局三:多列等高布局
方法一:padding + 负margin
方法二:设置父级背景图片
布局四:三行布局(头尾定高主栏自适应)
列了 4 种方法,都是基于如下的 HTML 和 CSS 的,结合示例阅读效果更佳:codepen demo
<div class="layout">
<header></header>
<main>
<div class="inner"></div>
</main>
<footer></footer>
</div>
html,
body,
.layout {
height: 100%;
}
body {
margin: 0;
}
header,
footer {
height: 50px;
}
main {
overflow-y: auto;
}
方法一:calc
方法二:absolute
方法三:flex
方法四:grid
3.自适应的优秀布局方案实践
19.CSS 动画有哪些?
animation、transition、transform、translate 这几个属性要搞清楚:
- animation:用于设置动画属性,他是一个简写的属性,包含6个属性
- transition:用于设置元素的样式过度,和animation有着类似的效果,但细节上有很大的不同
- transform:用于元素进行旋转、缩放、移动或倾斜,和设置样式的动画并没有什么关系
- translate:translate只是transform的一个属性值,即移动,除此之外还有 scale 等
为什么有时会用 translate 来改变位置,而不是定位
translate() 是 transform 的一个值。改变 transform 或 opacity 不会触发浏览器重新布局(reflow)或重绘(repaint),只会触发复合(compositions)。而改变绝对定位会触发重新布局,进而触发重绘和复合。transform 使浏览器为元素创建一个 GPU 图层,但改变绝对定位会使用到 CPU。因此 translate() 更高效,可以缩短平滑动画的绘制时间。translate 改变位置时,元素依然会占据原始空间,绝对定位不会发生这种情况。
参考资料
21.为什么要初始化 CSS 样式
- 因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面显示差异
- 初始化样式会对SEO有一定的影响,但鱼和熊掌不可兼得,但力求影响最小的情况下初始化
推荐
body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, form, fieldset, legend, button, input, textarea, th, td { margin:0; padding:0; }
body, button, input, select, textarea { font:12px/1.5tahoma, arial, \5b8b\4f53; }
h1, h2, h3, h4, h5, h6{ font-size:100%; }
address, cite, dfn, em, var { font-style:normal; }
code, kbd, pre, samp { font-family:couriernew, courier, monospace; }
small{ font-size:12px; }
ul, ol { list-style:none; }
a { text-decoration:none; }
a:hover { text-decoration:underline; }
sup { vertical-align:text-top; }
sub{ vertical-align:text-bottom; }
legend { color:#000; }
fieldset, img { border:0; }
button, input, select, textarea { font-size:100%; }
table { border-collapse:collapse; border-spacing:0; }
22.手写题:实现一个两栏布局。三列的布局,并且要求三列等高,且以内容最多的一列的高度为准。
1.两栏布局的方式
(1)左 float,然后右 margin-left(右边自适应)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
div {
height: 500px;
}
.aside {
width: 300px;
float: left;
background: yellow;
}
.main {
background: aqua;
margin-left: 300px;
}
</style>
</head>
<body>
<div class="aside"></div>
<div class="main"></div>
</body>
</html>
(2)右 float,margin-right
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
div {
height: 500px;
}
.aside {
width: 300px;
float: right;
background: yellow;
}
.main {
background: aqua;
margin-right: 300px;
}
</style>
</head>
<body>
<div class="aside"></div>
<div class="main"></div>
</body>
</html>
(3)BFC + float
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
div {
height: 500px;
}
.aside {
width: 300px;
float: left;
background: yellow;
}
.main {
overflow: hidden;
background: aqua;
}
</style>
</head>
<body>
<div class="aside"></div>
<div class="main"></div>
</body>
</html>
(4)float + 负 margin
<head>
<style>
.left {
width: 100%;
float: left;
background: #f00;
margin-right: -200px;
}
.right {
float: left;
width: 200px;
background: #0f0;
}
</style>
</head>
<div class="left"><p>hello</p></div>
<div class="right"><p>world</p></div>
(5)圣杯布局实现两栏布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
/* div {
height: 500px;
} */
/* .box {
overflow: hidden;
} */
/* .container {
padding: 0 300px 0 200px;
border: 1px solid black;
} */
html,
body {
height: 100%;
}
div {
height: 100%;
}
.container {
display: flex;
}
.content {
flex: 1 1;
order: 2;
background: #f00;
}
.left {
float: left;
width: 100%;
background: #0f0;
}
.right {
float: left;
width: 300px;
margin-left: -300px;
background: #00f;
}
</style>
</head>
<body>
<div class="container">
<div class="left">你好</div>
<div class="right">我好</div>
</div>
</body>
</html>
(6)flex 实现两栏布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
/* div {
height: 500px;
} */
/* .box {
overflow: hidden;
} */
/* .container {
padding: 0 300px 0 200px;
border: 1px solid black;
} */
html,
body {
height: 100%;
}
div {
height: 100%;
}
.container {
display: flex;
}
.content {
flex: 1 1;
order: 2;
background: #f00;
}
.left {
flex: 0 0 200px;
background: #0f0;
}
.right {
flex: 1 1;
background: #00f;
}
</style>
</head>
<body>
<div class="container">
<div class="left">你好</div>
<div class="right">我好</div>
</div>
</body>
</html>
(7) position + margin
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
/* div {
height: 500px;
} */
/* .box {
overflow: hidden;
} */
/* .container {
padding: 0 300px 0 200px;
border: 1px solid black;
} */
html,
body {
height: 100%;
}
div {
height: 100%;
}
.container {
display: flex;
position: relative;
}
.content {
flex: 1 1;
order: 2;
background: #f00;
}
.left {
position: absolute;
width: 300px;
background: #0f0;
}
.right {
width: 100%;
margin-left: 300px;
background: #00f;
}
</style>
</head>
<body>
<div class="container">
<div class="left">你好</div>
<div class="right">我好</div>
</div>
</body>
</html>
2.实现三列布局的方式
(1) position + margin-left + margin-right
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
div {
height: 500px;
}
.box {
position: relative;
}
.left {
position: absolute;
left: 0;
top: 0;
width: 200px;
background: green;
}
.right {
position: absolute;
right: 0;
top: 0;
width: 200px;
background: red;
}
.middle {
margin-left: 200px;
margin-right: 200px;
background: black;
}
</style>
</head>
<body>
<div class="box">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
</body>
</html>
(2)通过 float + margin
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
div {
height: 500px;
}
.left {
float: left;
width: 200px;
height: 200px;
background: green;
}
.right {
float: right;
width: 200px;
height: 200px;
background: red;
}
.middle {
margin-left: 210px;
margin-right: 210px;
background: black;
height: 200px;
}
</style>
</head>
<body>
<div class="box">
<div class="left"></div>
<div class="right"></div>
<div class="middle"></div>
</div>
</body>
</html>
(3)圣杯布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.container {
padding: 0 300px 0 200px;
border: 1px solid black;
}
.content {
float: left;
width: 100%;
background: #f00;
}
.left {
width: 200px;
background: #0f0;
float: left;
margin-left: -100%;
position: relative;
left: -200px;
}
.right {
width: 300px;
background: #00f;
float: left;
margin-left: -300px;
position: relative;
right: -300px;
}
</style>
</head>
<body>
<div class="container">
<div class="content">中间内容</div>
<div class="left">左侧区域</div>
<div class="right">右侧区域</div>
</div>
</body>
</html>
(4)双飞翼布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
html,
body {
height: 100%;
}
div {
height: 100%;
}
.main {
float: left;
width: 100%;
background: #f00;
}
.main .content {
margin-left: 200px;
margin-right: 300px;
}
.left {
width: 200px;
background: #0f0;
float: left;
margin-left: -100%;
}
.right {
width: 300px;
background: #00f;
float: left;
margin-left: -300px;
}
</style>
</head>
<body>
<div class="main">
<div class="content">hello world</div>
</div>
<div class="left">你好</div>
<div class="right">王鹏浩</div>
</body>
</html>
(5)flex 布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
html,
body {
height: 100%;
}
div {
height: 100%;
}
.container {
display: flex;
}
.content {
flex: 1 1;
order: 2;
background: #f00;
}
.left {
flex: 0 0 200px;
order: 1;
background: #0f0;
}
.right {
flex: 0 0 300px;
order: 3;
background: #00f;
}
</style>
</head>
<body>
<div class="container">
<div class="content">hello world</div>
<div class="left">你好</div>
<div class="right">王鹏浩</div>
</div>
</body>
</html>
23.CSS实现自适应正方形、等宽高比矩形
- width 设置百分比
- padding 撑高
- 如果只是要相对于 body 而言的话,还可以使用 vw 和 vh
- 伪元素设置 margin-top: 100%撑高
(1).双重嵌套,外层 relative,内层 absolute
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.outer {
padding-top: 50%;
height: 0;
background: #ccc;
width: 50%;
position: relative;
}
.inner {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: blue;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner">hello</div>
</div>
</body>
</html>
(2).padding 撑高画正方形
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.outer {
width: 400px;
height: 600px;
background: blue;
}
.inner {
width: 100%;
height: 0;
padding-bottom: 100%;
background: red;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner"></div>
</div>
</body>
</html>
(3).相对于视口 VW VH
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.inner {
width: 1vw;
height: 1vw;
background: blue;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner"></div>
</div>
</body>
</html>
(4).伪元素设置 margin-top
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.inner {
width: 100px;
overflow: hidden;
background: blue;
}
.inner::after {
content: "";
margin-top: 100%;
display: block;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner"></div>
</div>
</body>
</html>
参考链接: CSS实现自适应正方形、等宽高比矩形
24.CSS sprites 的理解及其好处
- 雪碧图,也叫 CSS 精灵,是一种 CSS 图像合成技术,开发人员往往将小图标合并在一起后的图片称作雪碧图
- 使用工具将多张图片打包成一张雪碧图,并为其生成合适的 CSS,每张图都有相应的 CSS 类,该类定义了 background-image、background-position 和 background-size 属性。使用图片时将相应的类添加到元素中。
好处:
- 减少加载多张图片的 HTTP 请求次数
- 提前加载资源
缺点:
- CSS Sprite 维护成本过高,稍微改动需要重新合并图片
- 加载速度在 HTTP2 开启后不明显,HTTP2 多路复用,多张图片也可以重复利用一个连接通道搞定
26.WEB标准以及W3C
对于结构的要求:
规范的标签可以提高搜索引擎对页面的抓取效率,对SEO很有帮助
- 标签要闭合
- 标签字母小写
- 标签不允许随意嵌套👉
对于CSS和JS来说: - 尽量使用外链CSS样式表和JS脚本。同时结构,表现和行为分为三块,符合规范。此外,还得提高页面渲染速度,提高用户体验。
- 尽量少用行内样式,保证结构和表现分离。标签的id和class等的属性命名要做到见文知意,标签越少,加载越快,用户体验就会越高。同时代码方面也会更易于维护,便于改版。
- 不需要变动内容,便可一同打印版本而不需要复制内容,提高网站易用性。👉
27.css实现瀑布流布局
28.TailwindCSS v3.0 一大波新特性来袭!
29.CSS预编译
1.Sass官网 2.Sass/SCSS 简明入门教程 在大型项目中,为了提高CSS的可维护性,人们开始使用CSS预编译技术。
CSS预编译部分的面试题主要考察开发者对CSS预编译技术的使用。
当然,CSS预编译技术中的变量、混合、方法、继承、作用域、语句、插值等也是应试者需要了解的。
目前CSS预编译器主要有3种,分别是Less、 Sass、Stylus,应试者可以选择一种,了解它的使用方式。
1.scss是什么及其几大特性?
sass是CSS预处理语言,scss是Sass语言中一套语法的拓展名。scss的特征是可以将CSS当作函数编写,可以定义变量,可以嵌套定义,可以使用语句等。
2.安装和使用Sass的步骤是什么?
Sass快熟入门与简单实战 具体步骤如下。
(1)通过npm安装css-loader、 node-loader、sass- loader等加载器模块。
(2)在 webpack .config. js配置文件中定义Sass加载器。
3.Sass和Less有什么区别?
区别如下:
(1)编译环境不一样。 Sass的安装需要Ruby环境,是在服务器端处理的。而Less需要引入 less.js来处理,然后Less代码输岀CSS到浏览器中;也可以在开发环境中使用Less,然后编译成CSS文件,直接放到项目中运行。
(2)变量名不一样。 Less中使用@,而Sass中使用$。
(3)插值语法不同。 Less中使用@{key}
,Sass中使用#{$key}
。
(4)Sass的混合相当于Less的方法,Sass的继承相当于Less的混合。
(5)输出设置不同。 Less没有输出设置。Sass提供4种输出选项:nested、compact、 compressed和 expanded。nested选项用于嵌套缩进的CSS代码(默认), expanded选项用于展开多行CSS代码, compact选项显示简洁格式的CSS代码, compressed选项显示压缩后的CSS代码。
(6)Sass支持条件语句,如if…else、for循环等,而Less不支持。
(7)引用外部CSS文件的方式不同。 Sass引用外部文件时必须以“ ”开头,文件名如果以下划线“”命名,Sass会认为该文件是一个引用文件,不会将其编译为CSS文件。Less引用外部文件和CSS中的@ import没什么差异。
(8)Sass和Less的工具库不同。 Sass有工具库 Compass。简单说,Sass和 Compass的关系有点像 JavaScript和 jQuery的关系, Compass是Sass的工具库。在它的基础上,封装了一系列有用的模块和模板,补充和强化了Sass的功能。Less有UI组件库 Bootstrap, Bootstrap是Web前端开发中一个比较有名的前端UI组件库, Bootstrap中样式文件的部分源码就是采用Less语法编写的。
总之,不管是Sass,还是Less,都可以将它们视为一种基于CSS之上的高级语言,其目的是使得CSS开发更灵活和更强大。Sass的功能比Less强大,可以认为Sass是种真正的编程语言;Less则相对清晰眀了,易于上手,对编译环境的要求比较宽松。
4.什么是CSS预处理器/后处理器?
预处理器(例如,Less、Sass、 Stylus)是用来把Sass或Less预编译成CSS的工具,増强了CSS代码的复用性。它有层级、 mixin、变量、循环、函数等,具有很方便的UI组件模块化开发能力,能极大地提高工作效率。
后处理器(如 PostCSS)通常被视为在完成的样式表中根据CSS规范处理CSS,让其更有效。目前最常做的是给CSS属性添加浏览器私有前缀,解决跨浏览器兼容性的问题。
5.UI组件库中三大预编译的样式穿透
【问题】:
用到很多vue常用的组件库(element, vant, vuetify),虽然配好了样式但是还是需要更改其他的样式。
【解决】
三大样式穿透 >>> , ::v-deep , /deep/
在style经常用scoped属性实现组件的私有化,所以才需要样式穿透
需要注意:
>>> 只作用于css
- ::v-deep 只作用于sass
- /deep/ 只作用于less
【示例】
//CSS
<style>
.num-input {
width: 90px;
margin-top: 15px;
>>> .ivu-input {
text-align: center!important;
}
}
</style>
//sass
<style lang="scss" scoped>
.conBox ::v-deep .el-input__inner{
padding:0 10px;
}
</style>
//less
<style lang="less" scoped>
.conBox /deep/ .el-input__inner{
padding:0 10px;
}
</style>
我项目中的
<style lang="scss" scoped>
.fieldColor ::v-deep .van-field__control{
color:#fff;
}
</style>
6.当Sass和新CSS功能发生冲突时的解决方案
7.SCSS的应用
1.如何实现 App 一键换肤? 2.如何利用 SCSS 实现一键换肤
30.进阶:玩转 CSS 变量
31.CSS代码整洁之道
- 你需要知道良好的 CSS 编码习惯
- A Guide to CSS Rules - CSS 规则书写不完全指南
- 如何写出更“美”的CSS代码?
- 改善 CSS 的 10 个最佳实践
- 如何写出更“美”的CSS代码?
- 如何写出一套可维护的CSS库?设计模式和架构
32.CSS性能优化
将css文件放在页面最上面,多个css可合并,并尽量减少http请求
避免过渡约束,避免使用后代选择符,链式选择符,多种类型选择符
避免不必要的命名空间,避免不必要的重复样式,移除空的css规则
使用具有语义的名字,使用紧凑的语法
避免使用 !important
尽可能地精简规则,尽可能合并不同类的重复规则,修复解析错误
正确使用display属性
inline后不应该使用width、height、margin、padding以及float
inline-block后不应该使用float;block后不应该使用vertical-align不滥用浮动,遵守盒模型规则
不滥用web字体,不声明过多font-size,不重复定义h1-h6,不给h1-h6定义过多样式
值为0时不需要任何单位
标准化各种浏览器前缀👉
33.提高用户体验技巧
- 深入理解 CSS 中的溢出问题
- Web 用户体验设计提升指南
- 浏览器暂时未支持:CSS 悬门妙法之提速网页渲染
34.12种增强CSS技能并加快开发速度的资源
二.常见需求
1.自定义属性
之前我们通常是在预处理器里才可以使用变量,而现在 CSS 里也支持了变量的用法。通过自定义属性就可以在想要使用的地方引用它。
自定义属性也和普通属性一样具有级联性,申明在 :root 下的时候,在全文档范围内可用,而如果是在某个元素下申明自定义属性,则只能在它及它的子元素下才可以使用。
自定义属性必须通过 --x 的格式申明,比如:–theme-color: red; 使用自定义属性的时候,需要用 var 函数。比如:
<!-- 定义自定义属性 -->
:root {
--theme-color: red;
}
<!-- 使用变量 -->
h1 {
color: var(--theme-color);
}
上图这个是使用 CSS 自定义属性配合 JS 实现的动态调整元素的 box-shadow,具体可以看这个 codepen demo。
2. 移动端兼容常见问题汇总
(1)1px 边框解决方案
Retina 显示屏比普通的屏幕有着更高的分辨率,所以在移动端的 1px 边框就会看起来比较粗,为了美观通常需要把这个线条细化处理。这里有篇文章列举了 7 中方案可以参考一下:7种方法解决移动端Retina屏幕1px边框问题,而这里附上最后一种通过伪类和 transform 实现的相对完美的解决方案:
而这里附上最后一种通过伪类和 transform 实现的相对完美的解决方案:
只设置单条底部边框:
.scale-1px-bottom {
position: relative;
border:none;
}
.scale-1px-bottom::after {
content: '';
position: absolute;
left: 0;
bottom: 0;
background: #000;
width: 100%;
height: 1px;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
}
同时设置 4 条边框:
.scale-1px {
position: relative;
margin-bottom: 20px;
border:none;
}
.scale-1px::after {
content: '';
position: absolute;
top: 0;
left: 0;
border: 1px solid #000;
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: 200%;
height: 200%;
-webkit-transform: scale(0.5);
transform: scale(0.5);
-webkit-transform-origin: left top;
transform-origin: left top;
}
(2) 响应式设计
一、是什么
响应式网站设计(Responsive Web design)是一种网络页面设计布局,页面的设计与开发应当根据用户行为以及设备环境(系统平台、屏幕尺寸、屏幕定向等)进行相应的响应和调整
描述响应式界面最著名的一句话就是“Content is like water”
大白话便是“如果将屏幕看作容器,那么内容就像水一样”
响应式网站常见特点:
- 同时适配PC + 平板 + 手机等
- 标签导航在接近手持终端设备时改变为经典的抽屉式导航
- 网站的布局会根据视口来调整模块的大小和位置
二、实现方式
响应式设计的基本原理是通过媒体查询检测不同的设备屏幕尺寸做处理,为了处理移动端,页面头部必须有meta声明viewport
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no”>
属性对应如下:
- width=device-width: 是自适应手机屏幕的尺寸宽度
- maximum-scale:是缩放比例的最大值
- inital-scale:是缩放的初始化
- user-scalable:是用户的可以缩放的操作
通过meta标签对viewport的设置,定义了页面的缩放比例;要了解这些参数的意义,我们需要先知道几个视口宽度的意义。
- layoutviewport布局宽度,就是网页的宽度
- visualviewport可是宽度,就是浏览器窗口的宽度,这个值决定了我们手机一屏能看到的内容;visualviewport和layoutviewport的
- 大小关系,决定了是否会出现滚动条,当visualviewport更大或者刚好等于layoutviewport时是不会出现滚动条的。
- idealviewport为浏览器定义的可完美适配移动端的viewport,固定不变,可以认为是设备视口宽度device-width。
meta的设置其实就是对layoutviewport和visualviewport进行设置。 - width=device-width表示页面宽度layoutviewport与设备视口宽度idealviewport一致
- initial-scale=1表示页面宽度和网页宽度与设备视口宽度的初始缩放比例,visualviewport由这个比例决定,但是对于layoutviewport来说,它同时受到两个属性的影响,然后取其中较大的那个值。
user-scale=no禁止缩放
所以现在我们知道,这段在移动端常见的代码的意思,即将visualviewport和layoutviewport设置为idealviewport的值;这样我们在移动端就不会出现滚动条,网页内容可以比较好的展示出来,在这个前提下我们再考虑页面的适配问题。
UI出图的时候一般是有一个固定的宽度的,而我们实际的移动端设备的宽度却都不太一样,但是如果页面元素的缩放比例和页面宽度的缩放比例一致,在不同尺寸的设备下我们网页的效果也将会是一致的。
实现响应式布局的方式有如下:
- 媒体查询
- 百分比
- 视口单位vw/vh
- 使用相对单位 rem
媒体查询
CSS3中的增加了更多的媒体查询,就像if条件表达式一样,我们可以设置不同类型的媒体条件,并根据对应的条件,给相应符合条件的媒体调用相对应的样式表
使用@Media查询,可以针对不同的媒体类型定义不同的样式,如:
@media screen and (max-width: 1920px) { ... }
当视口在375px - 600px之间,设置特定字体大小18px
@media screen (min-width: 375px) and (max-width: 600px) {
body {
font-size: 18px;
}
}
通过媒体查询,可以通过给不同分辨率的设备编写不同的样式来实现响应式的布局,比如我们为不同分辨率的屏幕,设置不同的背景图片
比如给小屏幕手机设置@2x图,为大屏幕手机设置@3x图,通过媒体查询就能很方便的实现
百分比
通过百分比单位 " % " 来实现响应式的效果
比如当浏览器的宽度或者高度发生变化时,通过百分比单位,可以使得浏览器中的组件的宽和高随着浏览器的变化而变化,从而实现响应式的效果
height、width属性的百分比依托于父标签的宽高,但是其他盒子属性则不完全依赖父元素:
- 子元素的top/left和bottom/right如果设置百分比,则相对于直接非static定位(默认定位)的父元素的高度/宽度
- 子元素的padding如果设置百分比,不论是垂直方向或者是水平方向,都相对于直接父亲元素的width,而与父元素的height无关。
- 子元素的margin如果设置成百分比,不论是垂直方向还是水平方向,都相对于直接父元素的width
- border-radius不一样,如果设置border-radius为百分比,则是相对于自身的宽度
视口单位vw/vh
将视口宽度window.innerWidth和视口高度window.innerHeight(即layoutviewport)等分为 100 份。
vw : 1vw 为视口宽度的 1% vh : 1vh 为视口高度的 1% vmin : vw 和 vh 中的较小值 vmax : 选取 vw 和 vh 中的较大值
和rem相比较,视口单位不需要使用js对根元素进行设置,兼容性稍差,但是大部分设备都已经支持了,同样的无须再开发时进行单位换算,直接使用相关的插件postcss-px-to-viewport在输出的时候进行转换。
与百分比布局很相似,在以前文章提过与%的区别,这里就不再展开述说
可以看到每个属性都使用百分比,会照成布局的复杂度,所以不建议使用百分比来实现响应式
相对单位rem
浅析rem布局方案
rem 是相对于根元素 html 的 font-size 来做计算,默认情况下浏览器字体大小为16px,此时1rem = 16px。通常在页面初始化时加载时通过对document.documentElement.style.fontSize 设置来实现。一般我们将根元素html的font-size设置为宽度的1/10,不同设备的宽度不同,但是同样数值的rem比例与设备的宽度比例是一致的。
document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
在实际项目中我们无须在开发中自己进行转换,可以使用pxtorem在输出的时候将px转换为rem。
可以利用前面提到的媒体查询,针对不同设备分辨率改变font-size的值,如下:
@media screen and (max-width: 414px) {
html {
font-size: 18px
}
}
@media screen and (max-width: 375px) {
html {
font-size: 16px
}
}
@media screen and (max-width: 320px) {
html {
font-size: 12px
}
}
为了更准确监听设备可视窗口变化,我们可以在css之前插入script标签,内容如下:
//动态为根元素设置字体大小
function init () {
// 获取屏幕宽度
var width = document.documentElement.clientWidth
// 设置根元素字体大小。此时为宽的10等分
document.documentElement.style.fontSize = width / 10 + 'px'
}
//首次加载应用,设置一次
init()
// 监听手机旋转的事件的时机,重新设置
window.addEventListener('orientationchange', init)
// 监听手机窗口变化,重新设置
window.addEventListener('resize', init)
无论设备可视窗口如何变化,始终设置rem为width的1/10,实现了百分比布局
除此之外,我们还可以利用主流UI框架,如:element ui、antd提供的栅格布局实现响应式
小结
响应式设计实现通常会从以下几方面思考:
- 弹性盒子(包括图片、表格、视频)和媒体查询等技术
- 使用百分比布局创建流式布局的弹性UI,同时使用媒体查询限制元素的尺寸和内容变更范围
- 使用相对单位使得内容自适应调节
- 选择断点,针对不同断点实现不同布局和内容展示
三、总结
响应式布局优点可以看到:
- 面对不同分辨率设备灵活性强
- 能够快捷解决多设备显示适应问题
缺点:
- 仅适用布局、信息、框架并不复杂的部门类型网站
- 兼容各种设备工作量大,效率低下
- 代码累赘,会出现隐藏无用的元素,加载时间加长
- 其实这是一种折中性质的设计解决方案,多方面因素影响而达不到最佳效果
- 一定程度上改变了网站原有的布局结构,会出现用户混淆的情况
参考阅读:
3.PC端兼容性问题汇总
(1)消除浏览器默认样式
针对同一个类型的 HTML 标签,不同的浏览器往往有不同的表现,所以在网站制作的时候,开发者通常都是需要将这些浏览器的默认样式清除,让网页在不同的浏览器上能够保持一致。
针对清除浏览器默认样式这件事,在很早之前 CSS 大师 Eric A. Meyer 就干过。它就是写一堆通用的样式用来重置浏览器默认样式,这些样式通常会放到一个命名为 reset.css 文件中。比如大师的 reset.css[17] 是这么写的。
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
他的这份 reset.css 据说是被使用最广泛的重设样式的方案了。
除了 reset.css 外,后来又出现了 Normalize.css。关于 Normalize.css, 其作者 necolas 专门写了一篇文章介绍了它,并谈到了它和 reset.css 的区别。这个是他写那篇文章的翻译版:让我们谈一谈 Normalize.css。
文章介绍到:Normalize.css 只是一个很小的CSS文件,但它在默认的 HTML 元素样式上提供了跨浏览器的高度一致性。相比于传统的 CSS reset,Normalize.css 是一种现代的、为 HTML5 准备的优质替代方案,现在已经有很多知名的框架和网站在使用它了。
Normalize.css 的具体样式可以看这里 Normalize.css
区别于 reset.css,Normalize.css 有如下特点:
- reset.css 几乎为所有标签都设置了默认样式,而 Normalize.css 则是有选择性的保护了部分有价值的默认值;
- 修复了很多浏览器的 bug,而这是 reset.css 没做到的;
- 不会让你的调试工具变的杂乱,相反 reset.css 由
- 设置了很多默认值,所以在浏览器调试工具中往往会看到一大堆的继承样式,显得很杂乱;
- Normalize.css 是模块化的,所以可以选择性的去掉永远不会用到的部分,比如表单的一般化
- Normalize.css 有详细的说明文档;
5.长文本省略处理
默认:字符太长溢出了容器
处理方案① 字符超出部分换行
②字符超出位置使用连字符
③单行文本超出省略
④多行文本超出省略
查看以上这些方案的示例: codepen demo
有意思的是刚好前两天看到 chokcoco 针对文本溢出也写了一篇文章,主要突出的是对整块的文本溢出处理。啥叫整块文本?比如,下面这种技术标签就是属于整块文本:
另外他还对 iOS/Safari 做了兼容处理,感兴趣的可以去阅读下:
作者本人的Github:CSS奇巧淫技巧
6.水平垂直居中
让元素在父元素中呈现出水平垂直居中的形态,无非就 3 种情况:
- 单行的文本、inline 或者 inline-block 元素;
- 固定宽高的块级盒子;
- 不固定宽高的块级盒子;
以下列到的所有水平垂直居中方案这里写了个 codepen demo,配合示例阅读效果更佳。
单行的文本、inline 或 inline-block 元素
水平居中
此类元素需要水平居中,则父级元素必须是块级元素(block level),且父级元素上需要这样设置样式:
.parent {
text-align: center;
}
垂直居中
方法一:通过设置上下内间距一致达到垂直居中的效果:
.single-line {
padding-top: 10px;
padding-bottom: 10px;
}
方法二:通过设置 height 和 line-height 一致达到垂直居中:
.single-line {
height: 100px;
line-height: 100px;
}
固定宽高的块级盒子
方法一:absolute + 负 margin
方法二:absolute + margin auto
方法三:absolute + calc
不固定宽高的块级盒子
这里列了 6 种方法,参考了颜海镜 写的文章 ,其中的两种 line-height 和 writing-mode 方案看后让我惊呼:还有这种操作?学到了学到了
方法一:absolute + transform
方法二:table-cell
方法三:flex
方法四:grid
方法五:line-height + vertical-align
方法六:writing-mode
8.CSS 实现优惠券的技巧
10.常见面试题
(1)面试官:让Chrome支持小于12px 的文字方式有哪些?区别?
(2)面试官:flex:7 1 100px中这三个参数你知道什么意思吗?
flex子元素伸缩属性
- 第一个参数表示: flex-grow 定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大
- 第二个参数表示: flex-shrink 定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小
- 第三个参数表示: flex-basis给上面两个属性分配多余空间之前, 计算项目是否有多余空间, 默认值为 auto, 即项目本身的大小
1.扩大情况
<style>
.item {
display: flex;
width: 500px;
height: 100px;
}
.item0 {
width: 50px;
flex: none;
background-color: red;
}
.item1 {
flex: 1 1 50px;
background-color: green;
}
.item2 {
flex: 7 1 100px;
background-color: blue;
}
</style>
<body>
<div class="item">
<div class="item0">0</div>
<div class="item1">1</div>
<div class="item2">2</div>
</div>
</body>
看到上面的效果来分析结果吧
为什么item0设置的是50px,还是50px呢?
为什么item1设置的是50px,怎么变成87.5px呢?
为什么item2设置的是100px,怎么变成362.5px呢?
当空间充足时,flex子项的宽度计算公式是: 自身的基础宽度 + 容器剩余宽度 *(自身伸张比例 / 所有子项伸张比例之和 ),要注意两种缩写
- flex:none是flex: 0 0 auto的缩写
- flex:num 是flex:numb 1 0%的缩写。如flex:1 => flex: 1 1 0%。
我们在item中设置了总得容器宽度为500px,容器中的item0、itme1、item2分别先占有自身的基础宽度,容器中剩余宽度则采用放大比例来进行放大。
剩余宽度 :500 - 50 - 50 - 100 = 300
item0本身宽度设置了50px,flex: none 等价于 flex: 0 0 auto,所有item0不参与放大,还是50px
item0宽度:50 + 300*( 0 / (0+1+7)) = 50
item1本身宽度设置的是flex: 1 1 50px中的第三个参数的值50px,当是扩大的情况下,我们只要看第一个参数就好了,item0的第一个参数是0,item1的第一个参数是1,item2的第一个参数是7,所以容器剩余宽度将会被分为8份,item1占一份,即为37.5px,item1总的宽度为87.5px
item1宽度:50 + 300 * ( 1 /(0+1+7)) = 87.5
item2同理可得,item2占7份,即为262.5,item2总的宽度为362.5
item2宽度:100 + 300 *( 7 /(0+1+7))= 362.5
2.缩小情况
<style>
.item00 {
display: flex;
width:300px;
height: 100px;
}
.item0 {
width:300px;
background-color: red;
}
.item1 {
flex: 1 1 100px;
background-color: green;
}
.item2 {
flex: 2 2 200px;
background-color: blue;
}
</style>
当空间充足不足时,flex子项的宽度计算公式是: 自身的基础宽度 - 超出宽度 (自身宽度收缩比例/总权重)
超出宽度=300+100+200-300=300
总权重=300 * 1+100* 1+2002=800 //理解一下总权重如何得出
item1的宽度=300 - 300 * 3001/800 =300 - 112.5=187.5;(只有width属性时,flex的属性值是0 1 auto,空间不足时也会收缩)
item2的宽度=100 - 300 * 1001/800 =100 - 37.5=62.5;
item3的宽度=200 - 300 * 2002 /800 =200-150=50;
注意flex:num这种缩写写法,展开相当于flex:num 1 0%,此时的flex-basis是0%,不是设置的width;计算总权重时该项的权重为0
(3)有哪些方式(CSS)可以隐藏页面元素?[visibility \display\opacity的差别]
opacity:0 :本质上是将元素的透明度将为0,就看起来隐藏了,但是依然占据空间且可以交互
①DOM 结构:透明度为 100%,元素隐藏,占据空间;
②事件监听:可以进行 DOM 事件监听;
③性 能:提升为合成层,不会触发重绘,性能较高;
④ 继 承:会被子元素继承,且,子元素并不能通过 opacity: 1 来取消隐藏;
⑤transition:opacity 可以延时显示和隐藏,可以设置过渡效果
⑥rgba()和opacity的透明效果有什么不同:
rgba()和opacity都能实现透明效果,但最大的不同是opacity作用于元素,以及元素内的所有内容的透明度,而rgba()只作用于元素的颜色或其背景色。(设置rgba透明的元素的子元素不会继承透明效果!)visibility:hidden : 与上⼀个方法类似的效果,占据空间,但是不可以交互了
①DOM 结构:元素被隐藏,但是会被渲染不会消失,占据空间;
②事件监听:无法进行 DOM 事件监听;
③性 能:动态改变此属性时会引起重绘,性能较高;
④继 承:会被子元素继承,子元素可以通过设置 visibility: visible; 来取消隐藏;
⑤transition:visibility 会立即显示,隐藏时会延时display:none : 这个是彻底隐藏了元素,元素从文档流中消失,既不占据空间也不交互,也不影响布局
①DOM 结构:浏览器不会渲染 display 属性为 none 的元素,不占据空间;
②事件监听:无法进行 DOM 事件监听;
③性能:动态改变此属性时会引起重排,性能较差;
④继承:不会被子元素继承,毕竟子类也不会被渲染;
⑤ transition:transition 不支持 display。
- overflow:hidden : 这个只隐藏元素溢出的部分,但是占据空间且不可交互
- z-index:-9999 : 原理是将层级放到底部,这样就被覆盖了,看起来隐藏了
- transform: scale(0,0) : 平面变换,将元素缩放为0,但是依然占据空间,但不可交互
- 利用绝对定位将元素移除可视区
- 使用 clip-path 进行裁剪
三.CSS奇巧淫技
1.有意思!奇妙的 CSS shapes(CSS图形)
2.5个你可能不知道的很棒CSS功能
3.Github – iCSS
4.不可思议的纯 CSS 滚动进度条效果
6.N个常见的CSS3动效技巧大全
7.CSS @property,让不可能变可能
8.N款非常实用的CSS3工具
参考链接1.如何用一行CSS分别实现10种常见布局?2.你会用到的 15个前端小知识3.一文梳理CSS必会知识点4.字节跳动最爱考的前端面试题:CSS 基础5.这份前端实践指南太牛逼了!全是干货,做业务必备!7.【笔记】常见 CSS 面试题 8.1.5 万字 CSS 基础拾遗(核心知识、常见需求) 10.Charts.css:一个数据可视化开源神器 11.【一起读书】40个来自CSS世界中的实用技巧汇总 14.104道 CSS 面试题,助你查漏补缺(上) 15. CSS入门后,我从前端到全栈 | JTalk大前端 16. 前端基础篇之CSS世界 17. 2020前端面试必会知识点之css(上篇)