除此之外,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 把内容替换成图片,完全没考虑过会把它当成容器。
参考:
格式化上下文
格式化上下文(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
块格式化上下文,它是一个独立的渲染区域,只有块级盒子参与,它规定了内部的块级盒子如何布局,并且与这个区域外部毫不相干。
BFC 渲染规则
- 内部的盒子会在垂直方向,一个接一个地放置;
- 盒子垂直方向的距离由 margin 决定,属于同一个 BFC 的两个相邻盒子的 margin 会发生重叠;
- 每个元素的 margin 的左边,与包含块 border 的左边相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此;
- BFC 的区域不会与 float 盒子重叠;
- BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
- 计算 BFC 的高度时,浮动元素也参与计算。
如何创建 BFC?
- 根元素:html
- 非溢出的可见元素:overflow 不为 visible
- 设置浮动:float 属性不为 none
- 设置定位:position 为 absolute 或 fixed
- 定义成块级的非块级元素:display: inline-block/table-cell/table-caption/flex/inline-flex/grid/inline-grid
BFC 应用场景
1、 自适应两栏布局
应用原理:BFC 的区域不会和浮动区域重叠,所以就可以把侧边栏固定宽度且左浮动,而对右侧内容触发 BFC,使得它的宽度自适应该行剩余宽度。
.aside {
float: left;
width: 100px;
}
.main {
overflow: auto;
}
复制代码
2、清除内部浮动
浮动造成的问题就是父元素高度坍塌,所以清除浮动需要解决的问题就是让父元素的高度恢复正常。而用 BFC 清除浮动的原理就是:计算 BFC 的高度时,浮动元素也参与计算。只要触发父元素的 BFC 即可。
.parent {
overflow: hidden;
}
复制代码
3、 防止垂直 margin 合并
BFC 渲染原理之一:同一个 BFC 下的垂直 margin 会发生合并。所以如果让 2 个元素不在同一个 BFC 中即可阻止垂直 margin 合并。那如何让 2 个相邻的兄弟元素不在同一个 BFC 中呢?可以给其中一个元素外面包裹一层,然后触发其包裹层的 BFC,这样一来 2 个元素就不会在同一个 BFC 中了。
.demo3 .a,
.demo3 .b {
border: 1px solid #999;
margin: 10px;
}
.contain-b {
overflow: hidden;
}
复制代码
针对以上 3 个 示例 ,可以结合这个 BFC 应用示例 配合观看更佳。
参考:CSS 原理 - Formatting Context
IFC
IFC 的形成条件非常简单,块级元素中仅包含内联级别元素,需要注意的是当IFC中有块级元素插入时,会产生两个匿名块将父元素分割开来,产生两个 IFC。
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 环境是怎么样的呢?
It can get very complicated once you start looking into it.
复制代码对应上面这样一串 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 和图我就不做了。
层叠上下文
在电脑显示屏幕上的显示的页面其实是一个三维的空间,水平方向是 X 轴,竖直方向是 Y 轴,而屏幕到眼睛的方向可以看成是 Z 轴。众 HTML 元素依据自己定义的属性的优先级在 Z 轴上按照一定的顺序排开,而这其实就是层叠上下文所要描述的东西。
我们对层叠上下文的第一印象可能要来源于 z-index,认为它的值越大,距离屏幕观察者就越近,那么层叠等级就越高,事实确实是这样的,但层叠上下文的内容远非仅仅如此:
- z-index 能够在层叠上下文中对元素的堆叠顺序其作用是必须配合定位才可以;
- 除了 z-index 之外,一个元素在 Z 轴上的显示顺序还受层叠等级和层叠顺序影响;
在看层叠等级和层叠顺序之前,我们先来看下如何产生一个层叠上下文,特定的 HTML 元素或者 CSS 属性产生层叠上下文,MDN 中给出了这么一个列表,符合以下任一条件的元素都会产生层叠上下文:
- html 文档根元素
- 声明 position: absolute/relative 且 z-index 值不为 auto 的元素;
- 声明 position: fixed/sticky 的元素;
- flex 容器的子元素,且 z-index 值不为 auto;
- grid 容器的子元素,且 z-index 值不为 auto;
- opacity 属性值小于 1 的元素;
- mix-blend-mode 属性值不为 normal 的元素;
- 以下任意属性值不为 none 的元素:
- transform
- filter
- perspective
- clip-path
- mask / mask-image / mask-border
- isolation 属性值为 isolate 的元素;
- -webkit-overflow-scrolling 属性值为 touch 的元素;
- will-change 值设定了任一属性而该属性在 non-initial 值时会创建层叠上下文的元素;
- contain 属性值为 layout、paint 或包含它们其中之一的合成值(比如 contain: strict、contain: content)的元素。
层叠等级
层叠等级指节点在三维空间 Z 轴上的上下顺序。它分两种情况:
- 在同一个层叠上下文中,它描述定义的是该层叠上下文中的层叠上下文元素在 Z 轴上的上下顺序;
- 在其他普通元素中,它描述定义的是这些普通元素在 Z 轴上的上下顺序;
普通节点的层叠等级优先由其所在的层叠上下文决定,层叠等级的比较只有在当前层叠上下文中才有意义,脱离当前层叠上下文的比较就变得无意义了。
层叠顺序
在同一个层叠上下文中如果有多个元素,那么他们之间的层叠顺序是怎么样的呢?
以下这个列表越往下层叠优先级越高,视觉上的效果就是越容易被用户看到(不会被其他元素覆盖):
- 层叠上下文的 border 和 background
- z-index < 0 的子节点
- 标准流内块级非定位的子节点
- 浮动非定位的子节点
- 标准流内行内非定位的子节点
- z-index: auto/0 的子节点
- z-index > 0的子节点
如何比较两个元素的层叠等级?
- 在同一个层叠上下文中,比较两个元素就是按照上图的介绍的层叠顺序进行比较。
- 如果不在同一个层叠上下文中的时候,那就需要比较两个元素分别所处的层叠上下文的等级。
- 如果两个元素都在同一个层叠上下文,且层叠顺序相同,则在 HTML 中定义越后面的层叠等级越高。
参考:彻底搞懂CSS层叠上下文、层叠等级、层叠顺序、z-index
值和单位
CSS 的声明是由属性和值组成的,而值的类型有许多种:
- 数值:长度值 ,用于指定例如元素 width、border-width、font-size 等属性的值;
- 百分比:可以用于指定尺寸或长度,例如取决于父容器的 width、height 或默认的 font-size;
- 颜色:用于指定 background-color、color 等;
- 坐标位置:以屏幕的左上角为坐标原点定位元素的位置,比如常见的 background-position、top、right、bottom 和 left 等属性;
- 函数:用于指定资源路径或背景图片的渐变,比如 url()、linear-gradient() 等;
而还有些值是需要带单位的,比如 width: 100px,这里的 px 就是表示长度的单位,长度单位除了 px 外,比较常用的还有 em、rem、vw/vh 等。那他们有什么区别呢?又应该在什么时候使用它们呢?
px
屏幕分辨率是指在屏幕的横纵方向上的像素点数量,比如分辨率 1920×1080 意味着水平方向含有 1920 个像素数,垂直方向含有 1080 个像素数。
而 px 表示的是 CSS 中的像素,在 CSS 中它是绝对的长度单位,也是最基础的单位,其他长度单位会自动被浏览器换算成 px。但是对于设备而言,它其实又是相对的长度单位,比如宽高都为 2px,在正常的屏幕下,其实就是 4 个像素点,而在设备像素比(devicePixelRatio) 为 2 的 Retina 屏幕下,它就有 16 个像素点。所以屏幕尺寸一致的情况下,屏幕分辨率越高,显示效果就越细腻。
讲到这里,还有一些相关的概念需要理清下:
设备像素(Device pixels)
设备屏幕的物理像素,表示的是屏幕的横纵有多少像素点;和屏幕分辨率是差不多的意思。
设备像素比(DPR)
设备像素比表示 1 个 CSS 像素等于几个物理像素。
计算公式:DPR = 物理像素数 / 逻辑像素数;
在浏览器中可以通过 window.devicePixelRatio 来获取当前屏幕的 DPR。
像素密度(DPI/PPI)
像素密度也叫显示密度或者屏幕密度,缩写为 DPI(Dots Per Inch) 或者 PPI(Pixel Per Inch)。从技术角度说,PPI 只存在于计算机显示领域,而 DPI 只出现于打印或印刷领域。
计算公式:像素密度 = 屏幕对角线的像素尺寸 / 物理尺寸
比如,对于分辨率为 750 * 1334 的 iPhone 6 来说,它的像素密度为:
Math.sqrt(750 * 750 + 1334 * 1334) / 4.7 = 326ppi
复制代码
设备独立像素(DIP)
DIP 是特别针对 Android设备而衍生出来的,原因是安卓屏幕的尺寸繁多,因此为了显示能尽量和设备无关,而提出的这个概念。它是基于屏幕密度而计算的,认为当屏幕密度是 160 的时候,px = DIP。
计算公式:dip = px * 160 / dpi
em
em 是 CSS 中的相对长度单位中的一个。居然是相对的,那它到底是相对的谁呢?它有 2 层意思:
- 在 font-size 中使用是相对于父元素的 font-size 大小,比如父元素 font-size: 16px,当给子元素指定 font-size: 2em 的时候,经过计算后它的字体大小会是 32px;
- 在其他属性中使用是相对于自身的字体大小,如 width/height/padding/margin 等;
我们都知道每个浏览器都会给 HTML 根元素 html 设置一个默认的 font-size,而这个值通常是 16px。这也就是为什么 1em = 16px 的原因所在了。
em 在计算的时候是会层层计算的,比如:
div { font-size: 2em; }
p { font-size: 2em; }
复制代码
对于如上一个结构的 HTML,由于根元素 html 的字体大小是 16px,所以 p 标签最终计算出来后的字体大小会是 16 * 2 * 2 = 64px
rem
rem(root em) 和 em 一样,也是一个相对长度单位,不过 rem 相对的是 HTML 的根元素 html。
rem 由于是基于 html 的 font-size 来计算,所以通常用于自适应网站或者 H5 中。
比如在做 H5 的时候,前端通常会让 UI 给 750px 宽的设计图,而在开发的时候可以基于 iPhone X 的尺寸 375px * 812px 来写页面,这样一来的话,就可以用下面的 JS 依据当前页面的视口宽度自动计算出根元素 html 的基准 font-size 是多少。
(function (doc, win) {
var docEl = doc.documentElement,
resizeEvt = ‘orientationchange’ in window ? ‘orientationchange’ : ‘resize’,
psdWidth = 750, // 设计图宽度
recalc = function () {
var clientWidth = docEl.clientWidth;
if ( !clientWidth ) return;
if ( clientWidth >= 640 ) {
docEl.style.fontSize = 200 * ( 640 / psdWidth ) + ‘px’;
} else {
docEl.style.fontSize = 200 * ( clientWidth / psdWidth ) + ‘px’;
}
};
if ( !doc.addEventListener ) return;
// 绑定事件的时候最好配合防抖函数
win.addEventListener( resizeEvt, debounce(recalc, 1000), false );
doc.addEventListener( ‘DOMContentLoaded’, recalc, false );
function debounce(func, wait) {
var timeout;
return function () {
var context = this;
var args = arguments;
clearTimeout(timeout)
timeout = setTimeout(function(){
func.apply(context, args)
}, wait);
}
}
})(document, window);
复制代码
比如当视口是 375px 的时候,经过计算 html 的 font-size 会是 100px,这样有什么好处呢?好处就是方便写样式,比如从设计图量出来的 header 高度是 50px 的,那我们写样式的时候就可以直接写:
header {
height: 0.5rem;
}
复制代码
每个从设计图量出来的尺寸只要除于 100 即可得到当前元素的 rem 值,都不用经过计算,非常方便。偷偷告诉你,如果你把上面那串计算 html 标签 font-size 的 JS 代码中的 200 替换成 2,那在计算 rem 的时候就不需要除于 100 了,从设计图量出多大 px,就直接写多少个 rem。
vw/vh
vw 和 vh 分别是相对于屏幕视口宽度和高度而言的长度单位:
- 1vw = 视口宽度均分成 100 份中 1 份的长度;
- 1vh = 视口高度均分成 100 份中 1 份的长度;
在 JS 中 100vw = window.innerWidth,100vh = window.innerHeight。
vw/vh 的出现使得多了一种写自适应布局的方案,开发者不再局限于 rem 了。
相对视口的单位,除了 vw/vh 外,还有 vmin 和 vmax:
- vmin:取 vw 和 vh 中值较小的;
- vmax:取 vw 和 vh 中值较大的;
颜色体系
CSS 中用于表示颜色的值种类繁多,足够构成一个体系,所以这里就专门拿出一个小节来讲解它。
根据 CSS 颜色草案 中提到的颜色值类型,大概可以把它们分为这几类:
- 颜色关键字
- transparent 关键字
- currentColor 关键字
- RGB 颜色
- HSL 颜色
颜色关键字
颜色关键字(color keywords)是不区分大小写的标识符,它表示一个具体的颜色,比如 white(白),黑(black)等;
可接受的关键字列表在CSS的演变过程中发生了改变:
- CSS 标准 1 只接受 16 个基本颜色,称为 VGA 颜色,因为它们来源于 VGA 显卡所显示的颜色集合而被称为 VGA colors (视频图形阵列色彩)。
- CSS 标准 2 增加了 orange 关键字。
- 从一开始,浏览器接受其它的颜色,由于一些早期浏览器是 X11 应用程序,这些颜色大多数是 X11 命名的颜色列表,虽然有一点不同。SVG 1.0 是首个正式定义这些关键字的标准;CSS 色彩标准 3 也正式定义了这些关键字。它们经常被称作扩展的颜色关键字, X11 颜色或 SVG 颜色 。
- CSS 颜色标准 4 添加可 rebeccapurple 关键字来纪念 web 先锋 Eric Meyer。
如下这张图是 16 个基础色,又叫 VGA 颜色。截止到目前为止 CSS 颜色关键字总共有 146 个,这里可以查看 完整的色彩关键字列表。
需要注意的是如果声明的时候的颜色关键字是错误的,浏览器会忽略它。
transparent 关键字
transparent 关键字表示一个完全透明的颜色,即该颜色看上去将是背景色。从技术上说,它是带有 alpha 通道为最小值的黑色,是 rgba(0,0,0,0) 的简写。
透明关键字有什么应用场景呢?
实现三角形
下面这个图是用 4 条边框填充的正方形,看懂了它你大概就知道该如何用 CSS 写三角形了。
div {
border-top-color: #ffc107;
border-right-color: #00bcd4;
border-bottom-color: #e26b6b;
border-left-color: #cc7cda;
border-width: 50px;
border-style: solid;
}
复制代码
用 transparent 实现三角形的原理:
- 首先宽高必须是 0px,通过边框的粗细来填充内容;
- 那条边需要就要加上颜色,而不需要的边则用 transparent;
- 想要什么样姿势的三角形,完全由上下左右 4 条边的中有颜色的边和透明的边的位置决定;
- 等腰三角形:设置一条边有颜色,然后紧挨着的 2 边是透明,且宽度是有颜色边的一半;直角三角形:设置一条边有颜色,然后紧挨着的任何一边透明即可。
看下示例:
增大点击区域
常常在移动端的时候点击的按钮的区域特别小,但是由于现实效果又不太好把它做大,所以常用的一个手段就是通过透明的边框来增大按钮的点击区域:
.btn {
border: 5px solid transparent;
}
复制代码
currentColor 关键字
currentColor 会取当前元素继承父级元素的文本颜色值或声明的文本颜色值,即 computed 后的 color 值。
比如,对于如下 CSS,该元素的边框颜色会是 red:
.btn {
color: red;
border: 1px solid currentColor;
}
复制代码
RGB[A] 颜色
RGB[A] 颜色是由 R(red)-G(green)-B(blue)-A(alpha) 组成的色彩空间。
在 CSS 中,它有两种表示形式:
- 十六进制符号;
- 函数符;
十六进制符号
RGB 中的每种颜色的值范围是 00~ff,值越大表示颜色越深。所以一个颜色正常是 6 个十六进制字符加上 # 组成,比如红色就是 #ff0000。
如果 RGB 颜色需要加上不透明度,那就需要加上 alpha 通道的值,它的范围也是 00~ff,比如一个带不透明度为 67% 的红色可以这样写 #ff0000aa。
使用十六进制符号表示颜色的时候,都是用 2 个十六进制表示一个颜色,如果这 2 个字符相同,还可以缩减成只写 1 个,比如,红色 #f00;带 67% 不透明度的红色 #f00a。
函数符
当 RGB 用函数表示的时候,每个值的范围是 0~255 或者 0%~100%,所以红色是 rgb(255, 0, 0), 或者 rgb(100%, 0, 0)。
如果需要使用函数来表示带不透明度的颜色值,值的范围是 0~1 及其之间的小数或者 0%~100%,比如带 67% 不透明度的红色是 rgba(255, 0, 0, 0.67) 或者 rgba(100%, 0%, 0%, 67%)
需要注意的是 RGB 这 3 个颜色值需要保持一致的写法,要嘛用数字要嘛用百分比,而不透明度的值的可以不用和 RGB 保持一致写法。比如 rgb(100%, 0, 0) 这个写法是无效的;而 rgb(100%, 0%, 0%, 0.67) 是有效的。
在第 4 代 CSS 颜色标准中,新增了一种新的函数写法,即可以把 RGB 中值的分隔逗号改成空格,而把 RGB 和 alpha 中的逗号改成 /,比如带 67% 不透明度的红色可以这样写 rgba(255 0 0 / 0.67)。另外还把 rgba 的写法合并到 rgb 函数中了,即 rgb 可以直接写带不透明度的颜色。
HSL[A] 颜色
HSL[A] 颜色是由色相(hue)-饱和度(saturation)-亮度(lightness)-不透明度组成的颜色体系。
- 色相(H)是色彩的基本属性,值范围是 0
360 或者 0deg360deg, 0 (或 360) 为红色, 120 为绿色, 240 为蓝色; - 饱和度(S)是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取 0~100% 的数值;0% 为灰色, 100% 全色;
- 亮度(L),取 0~100%,0% 为暗,100% 为白;
- 不透明度(A),取 0
100%,或者01及之间的小数;
写法上可以参考 RGB 的写法,只是参数的值不一样。
给一个按钮设置不透明度为 67% 的红色的 color 的写法,以下全部写法效果一致:
button {
color: #ff0000aa;
color: #f00a;
color: rgba(255, 0, 0, 0.67);
color: rgb(100% 0% 0% / 67%);
color: hsla(0, 100%, 50%, 67%);
color: hsl(0deg 100% 50% / 67%);
}
复制代码
小提示:在 Chrome DevTools 中可以按住 shift + 鼠标左键可以切换颜色的表示方式。
媒体查询
媒体查询是指针对不同的设备、特定的设备特征或者参数进行定制化的修改网站的样式。
你可以通过给 <link>
加上 media 属性来指定该样式文件只能对什么设备生效,不指定的话默认是 all,即对所有设备都生效:
都支持哪些设备类型?
- all:适用于所有设备;
- print:适用于在打印预览模式下在屏幕上查看的分页材料和文档;
- screen:主要用于屏幕;
- speech:主要用于语音合成器。
需要注意的是:通过 media 指定的 资源尽管不匹配它的设备类型,但是浏览器依然会加载它。
除了通过 <link>
让指定设备生效外,还可以通过 @media
让 CSS 规则在特定的条件下才能生效。响应式页面就是使用了 @media 才让一个页面能够同时适配 PC、Pad 和手机端。
@media (min-width: 1000px) {}
复制代码
媒体查询支持逻辑操作符:
- and:查询条件都满足的时候才生效;
- not:查询条件取反;
- only:整个查询匹配的时候才生效,常用语兼容旧浏览器,使用时候必须指定媒体类型;
- 逗号或者 or:查询条件满足一项即可匹配;
媒体查询还支持众多的媒体特性,使得它可以写出很复杂的查询条件:
/* 用户设备的最小高度为680px或为纵向模式的屏幕设备 */
@media (min-height: 680px), screen and (orientation: portrait) {}
复制代码
常见需求
自定义属性
之前我们通常是在预处理器里才可以使用变量,而现在 CSS 里也支持了变量的用法。通过自定义属性就可以在想要使用的地方引用它。
自定义属性也和普通属性一样具有级联性,申明在 :root 下的时候,在全文档范围内可用,而如果是在某个元素下申明自定义属性,则只能在它及它的子元素下才可以使用。
自定义属性必须通过 --x
的格式申明,比如:–theme-color: red; 使用自定义属性的时候,需要用 var 函数。比如:
:root {
–theme-color: red;
}
h1 {
color: var(–theme-color);
}
复制代码
上图这个是使用 CSS 自定义属性配合 JS 实现的动态调整元素的 box-shadow,具体可以看这个 codepen demo。
1px 边框解决方案
Retina 显示屏比普通的屏幕有着更高的分辨率,所以在移动端的 1px 边框就会看起来比较粗,为了美观通常需要把这个线条细化处理。这里有篇文章列举了 7 中方案可以参考一下:7种方法解决移动端Retina屏幕1px边框问题
而这里附上最后一种通过伪类和 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;
}
复制代码
清除浮动
什么是浮动:浮动元素会脱离文档流并向左/向右浮动,直到碰到父元素或者另一个浮动元素。
为什么要清楚浮动,它造成了什么问题?
因为浮动元素会脱离正常的文档流,并不会占据文档流的位置,所以如果一个父元素下面都是浮动元素,那么这个父元素就无法被浮动元素所撑开,这样一来父元素就丢失了高度,这就是所谓的浮动造成的父元素高度坍塌问题。
父元素高度一旦坍塌将对后面的元素布局造成影响,为了解决这个问题,所以需要清除浮动,让父元素恢复高度,那该如何做呢?
这里介绍两种方法:通过 BFC 来清除、通过 clear 来清除。
BFC 清除浮动
前面介绍 BFC 的时候提到过,计算 BFC 高度的时候浮动子元素的高度也将计算在内,利用这条规则就可以清楚浮动。
假设一个父元素 parent 内部只有 2 个子元素 child,且它们都是左浮动的,这个时候 parent 如果没有设置高度的话,因为浮动造成了高度坍塌,所以 parent 的高度会是 0,此时只要给 parent 创造一个 BFC,那它的高度就能恢复了。
而产生 BFC 的方式很多,我们可以给父元素设置overflow: auto 来简单的实现 BFC 清除浮动,但是为了兼容 IE 最好用 overflow: hidden。
.parent {
overflow: hidden;
}
复制代码
通过 overflow: hidden 来清除浮动并不完美,当元素有阴影或存在下拉菜单的时候会被截断,所以该方法使用比较局限。
通过 clear 清除浮动
我先把结论贴出来:
.clearfix {
zoom: 1;
}
.clearfix::after {
content: “”;
display: block;
clear: both;
}
复制代码
这种写法的核心原理就是通过 ::after 伪元素为在父元素的最后一个子元素后面生成一个内容为空的块级元素,然后通过 clear 将这个伪元素移动到所有它之前的浮动元素的后面,画个图来理解一下。
可以结合这个 codepen demo 一起理解上图的 clear 清楚浮动原理。
上面这个 demo 或者图里为了展示需要所以给伪元素的内容设置为了 ::after,实际使用的时候需要设置为空字符串,让它的高度为 0,从而父元素的高度都是由实际的子元素撑开。
该方式基本上是现在人人都在用的清除浮动的方案,非常通用。
消除浏览器默认样式
针对同一个类型的 HTML 标签,不同的浏览器往往有不同的表现,所以在网站制作的时候,开发者通常都是需要将这些浏览器的默认样式清除,让网页在不同的浏览器上能够保持一致。
针对清除浏览器默认样式这件事,在很早之前 CSS 大师 Eric A. Meyer 就干过。它就是写一堆通用的样式用来重置浏览器默认样式,这些样式通常会放到一个命名为 reset.css 文件中。比如大师的 reset.css 是这么写的:
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 有详细的说明文档;
长文本处理
默认:字符太长溢出了容器
字符超出部分换行
字符超出位置使用连字符
单行文本超出省略
多行文本超出省略
查看以上这些方案的示例: codepen demo
有意思的是刚好前两天看到 chokcoco 针对文本溢出也写了一篇文章,主要突出的是对整块的文本溢出处理。啥叫整块文本?比如,下面这种技术标签就是属于整块文本:
另外他还对 iOS/Safari 做了兼容处理,感兴趣的可以去阅读下:CSS 整块文本溢出省略特性探究。
水平垂直居中
让元素在父元素中呈现出水平垂直居中的形态,无非就 2 种情况:
- 单行的文本、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
方法二:line-height + vertical-align
方法三:writing-mode
方法四:table-cell
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
![](https://i-blog.csdnimg.cn/blog_migrate/6d7872185628b19a5b96de470a392b33.jpeg)
最后
由于文档内容过多,为了避免影响到大家的阅读体验,在此只以截图展示部分内容,详细完整版的JavaScript面试题文档,或更多前端资料可以点此处免费获取。
图片转存中…(img-4aUlcL1D-1712377615011)]
方法三:writing-mode
[外链图片转存中…(img-cvZsCODw-1712377615011)]
方法四:table-cell
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-HmhQcDu4-1712377615011)]
[外链图片转存中…(img-uAGN4ncJ-1712377615012)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
[外链图片转存中…(img-loGUzygW-1712377615012)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
![](https://i-blog.csdnimg.cn/blog_migrate/6d7872185628b19a5b96de470a392b33.jpeg)
最后
[外链图片转存中…(img-UTRGJWVH-1712377615012)]
[外链图片转存中…(img-9Q3rEdxk-1712377615012)]
由于文档内容过多,为了避免影响到大家的阅读体验,在此只以截图展示部分内容,详细完整版的JavaScript面试题文档,或更多前端资料可以点此处免费获取。