CSS

一、CSS基础

1. CSS选择器及其优先级

选择器 格式 优先级权重
id选择器 #id 100
类选择器 .classname 10
属性选择器 a[ref=“eee”] 10
伪类选择器 li:last-child 10
标签选择器 div 1
伪元素选择器 li:after 1
相邻兄弟选择器 h1+p 0
子选择器 ul>li 0
后代选择器 li a 0
通配符选择器 * 0

对于选择器的优先级

  • 标签选择器、伪元素选择器:1;
  • 类选择器、伪类选择器、属性选择器:10;
  • id 选择器:100;
  • 内联样式:1000;

注意事项:

  • !important声明的样式的优先级最高;
  • 如果优先级相同,则最后出现的样式生效;
  • 继承得到的样式的优先级最低;
  • 通用选择器(*)、子选择器(>)和相邻同胞选择器(+)并不在这四个等级中,所以它们的权值都为 0 ;
  • 样式表的来源不同时,优先级顺序为:内联样式 > 内部样式 > 外部样式 > 浏览器用户自定义样式 > 浏览器默认样式。

2. CSS中可继承与不可继承属性有哪些

一、无继承性的属性

  1. display:规定元素应该生成的框的类型
  2. 文本属性
  • vertical-align:垂直文本对齐
  • text-decoration:规定添加到文本的装饰
  • text-shadow:文本阴影效果
  • white-space:空白符的处理
  • unicode-bidi:设置文本的方向
  1. 盒子模型的属性:width、height、margin、border、padding
  2. 背景属性:background、background-color、background-image、background-repeat、background-position、background-attachment
  3. 定位属性:float、clear、position、top、right、bottom、left、min-width、min-height、max-width、max-height、overflow、clip、z-index
  4. 生成内容属性:content、counter-reset、counter-increment
  5. 轮廓样式属性:outline-style、outline-width、outline-color、outline
  6. 页面样式属性:size、page-break-before、page-break-after
  7. 声音样式属性:pause-before、pause-after、pause、cue-before、cue-after、cue、play-during

二、有继承性的属性

  1. 字体系列属性
  • font-family:字体系列
  • font-weight:字体的粗细
  • font-size:字体的大小
  • font-style:字体的风格
  1. 文本系列属性
  • text-indent:文本缩进
  • text-align:文本水平对齐
  • line-height:行高
  • word-spacing:单词之间的间距
  • letter-spacing:中文或者字母之间的间距
  • text-transform:控制文本大小写(就是uppercase、lowercase、capitalize这三个)
  • color:文本颜色
  1. 元素可见性
  • visibility:控制元素显示隐藏
  1. 列表布局属性
  • list-style:列表风格,包括list-style-type、list-style-image等
  1. 光标属性
  • cursor:光标显示为何种形态

3. display的属性值及其作用

属性值 作用
none 元素不显示,并且会从文档流中移除。
block 块类型。默认宽度为父元素宽度,可设置宽高,换行显示。
inline 行内元素类型。默认宽度为内容宽度,不可设置宽高,同行显示。
inline-block 默认宽度为内容宽度,可以设置宽高,同行显示。
list-item 像块类型元素一样显示,并添加样式列表标记。
table 此元素会作为块级表格来显示。
inherit 规定应该从父元素继承display属性的值。

4. display的block、inline和inline-block的区别

 (1)block:会独占一行,多个元素会另起一行,可以设置width、height、margin和padding属性;

 (2)inline:元素不会独占一行,设置width、height属性无效。但可以设置水平方向的margin和padding属性,不能设置垂直方向的padding和margin;

 (3)inline-block:将对象设置为inline对象,但对象的内容作为block对象呈现,之后的内联对象会被排列在同一行内。

对于行内元素和块级元素,其特点如下:

(1)行内元素

  • 设置宽高无效;
  • 可以设置水平方向的margin和padding属性,不能设置垂直方向的padding和margin;
  • 不会自动换行;

(2)块级元素

  • 可以设置宽高;
  • 设置margin和padding都有效;
  • 可以自动换行;
  • 多个块状,默认排列从上到下。

5. 隐藏元素的方法有哪些

  • display: none:渲染树不会包含该渲染对象,因此该元素不会在页面中占据位置,也不会响应绑定的监听事件。
  • visibility: hidden:元素在页面中仍占据空间,但是不会响应绑定的监听事件。
  • opacity: 0:将元素的透明度设置为 0,以此来实现元素的隐藏。元素在页面中仍然占据空间,并且能够响应元素绑定的监听事件。
  • position: absolute:通过使用绝对定位将元素移除可视区域内,以此来实现元素的隐藏。
  • z-index: 负值:来使其他元素遮盖住该元素,以此来实现隐藏。
  • clip/clip-path :使用元素裁剪的方法来实现元素的隐藏,这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。
  • transform: scale(0,0):将元素缩放为 0,来实现元素的隐藏。这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。

6. link和@import的区别

两者都是外部引用CSS的方式,它们的区别如下:

  • link是XHTML标签,除了加载CSS外,还可以定义RSS等其他事务;@import属于CSS范畴,只能加载CSS。
  • link引用CSS时,在页面载入时同时加载;@import需要页面网页完全载入以后加载。
  • link是XHTML标签,无兼容问题;@import是在CSS2.1提出的,低版本的浏览器不支持。
  • link支持使用Javascript控制DOM去改变样式;而@import不支持。

8. display:none与visibility:hidden的区别

这两个属性都是让元素隐藏,不可见。两者**区别如下:**

(1)在渲染树中

  • display:none会让元素完全从渲染树中消失,渲染时不会占据任何空间;
  • visibility:hidden不会让元素从渲染树中消失,渲染的元素还会占据相应的空间,只是内容不可见。

(2)是否是**继承属性**

  • display:none是非继承属性,子孙节点会随着父节点从渲染树消失,通过修改子孙节点的属性也无法显示;
  • visibility:hidden是继承属性,子孙节点消失是由于继承了hidden,通过设置visibility:visible可以让子孙节点显示;

(3)修改常规文档流中元素的 display 通常会造成文档的重排,但是修改visibility属性只会造成本元素的重绘;

(4)如果使用读屏器,设置为display:none的内容不会被读取,设置为visibility:hidden的内容会被读取。

9. 伪元素和伪类的区别和作用?

  • 伪元素:在内容元素的前后插入额外的元素或样式,但是这些元素实际上并不在文档中生成。它们只在外部显示可见,但不会在文档的源代码中找到它们,因此,称为“伪”元素。例如:
1
2
3
4
p::before {content:"第一章:";}
p::after {content:"Hot!";}
p::first-line {background:red;}
p::first-letter {font-size:30px;}
  • 伪类:将特殊的效果添加到特定选择器上。它是已有元素上添加类别的,不会产生新的元素。例如:
1
2
a:hover {color: #FF00FF}
p:first-child {color: red}

总结:伪类是通过在元素选择器上加⼊伪类改变元素状态,⽽伪元素通过对元素的操作进⾏对元素的改变。

11. 对盒模型的理解

CSS3中的盒模型有以下两种:标准盒子模型、IE盒子模型

img

img

盒模型都是由四个部分组成的,分别是margin、border、padding和content。

标准盒模型和IE盒模型的区别在于设置width和height时,所对应的范围不同:

  • 标准盒模型的width和height属性的范围只包含了content,
  • IE盒模型的width和height属性的范围包含了border、padding和content。

可以通过修改元素的box-sizing属性来改变元素的盒模型:

  • box-sizing: content-box表示标准盒模型(默认值)
  • box-sizing: border-box表示IE盒模型(怪异盒模型)

14. CSS3中有哪些新特性

  • 新增各种CSS选择器 (: not(.input):所有 class 不是“input”的节点)
  • 圆角 (border-radius:8px)
  • 多列布局 (multi-column layout)
  • 阴影和反射 (Shadoweflect)
  • 文字特效 (text-shadow)
  • 文字渲染 (Text-decoration)
  • 线性渐变 (gradient)
  • 旋转 (transform)
  • 增加了旋转,缩放,定位,倾斜,动画,多背景

16. 常见的图片格式及使用场景

(1)BMP,是无损的、既支持索引色也支持直接色的点阵图。这种图片格式几乎没有对数据进行压缩,所以BMP格式的图片通常是较大的文件。

(2)GIF是无损的、采用索引色的点阵图。采用LZW压缩算法进行编码。文件小,是GIF格式的优点,同时,GIF格式还具有支持动画以及透明的优点。但是GIF格式仅支持8bit的索引色,所以GIF格式适用于对色彩要求不高同时需要文件体积较小的场景。

(3)JPEG是有损的、采用直接色的点阵图。JPEG的图片的优点是采用了直接色,得益于更丰富的色彩,JPEG非常适合用来存储照片,与GIF相比,JPEG不适合用来存储企业Logo、线框类的图。因为有损压缩会导致图片模糊,而直接色的选用,又会导致图片文件较GIF更大。

(4)PNG-8是无损的、使用索引色的点阵图。PNG是一种比较新的图片格式,PNG-8是非常好的GIF格式替代者,在可能的情况下,应该尽可能的使用PNG-8而不是GIF,因为在相同的图片效果下,PNG-8具有更小的文件体积。除此之外,PNG-8还支持透明度的调节,而GIF并不支持。除非需要动画的支持,否则没有理由使用GIF而不是PNG-8。

(5)PNG-24是无损的、使用直接色的点阵图。PNG-24的优点在于它压缩了图片的数据,使得同样效果的图片,PNG-24格式的文件大小要比BMP小得多。当然,PNG24的图片还是要比JPEG、GIF、PNG-8大得多。

(6)SVG是无损的矢量图。SVG是矢量图意味着SVG图片由直线和曲线以及绘制它们的方法组成。当放大SVG图片时,看到的还是线和曲线,而不会出现像素点。SVG图片在放大时,不会失真,所以它适合用来绘制Logo、Icon等。

(7)WebP是谷歌开发的一种新图片格式,WebP是同时支持有损和无损压缩的、使用直接色的点阵图。从名字就可以看出来它是为Web而生的,什么叫为Web而生呢?就是说相同质量的图片,WebP具有更小的文件体积。现在网站上充满了大量的图片,如果能够降低每一个图片的文件大小,那么将大大减少浏览器和服务器之间的数据传输量,进而降低访问延迟,提升访问体验。目前只有Chrome浏览器和Opera浏览器支持WebP格式,兼容性不太好。

  • 在无损压缩的情况下,相同质量的WebP图片,文件大小要比PNG小26%;
  • 在有损压缩的情况下,具有相同图片精度的WebP图片,文件大小要比JPEG小25%~34%;
  • WebP图片格式支持图片透明度,一个无损压缩的WebP图片,如果要支持透明度只需要22%的格外文件大小。

17. 对 CSSSprites 的理解

CSSSprites(精灵图),将一个页面涉及到的所有图片都包含到一张大图中去,然后利用CSS的 background-image,background-repeat,background-position属性的组合进行背景定位。

优点:

  • 利用CSS Sprites能很好地减少网页的http请求,从而大大提高了页面的性能,这是CSS Sprites最大的优点;
  • CSS Sprites能减少图片的字节,把3张图片合并成1张图片的字节总是小于这3张图片的字节总和。

缺点:

  • 在图片合并时,要把多张图片有序的、合理的合并成一张图片,还要留好足够的空间,防止板块内出现不必要的背景。在宽屏及高分辨率下的自适应页面,如果背景不够宽,很容易出现背景断裂;
  • CSSSprites在开发的时候相对来说有点麻烦,需要借助photoshop或其他工具来对每个背景单元测量其准确的位置。
  • 维护方面:CSS Sprites在维护的时候比较麻烦,页面背景有少许改动时,就要改这张合并的图片,无需改的地方尽量不要动,这样避免改动更多的CSS,如果在原来的地方放不下,又只能(最好)往下加图片,这样图片的字节就增加了,还要改动CSS

22. CSS预处理器/后处理器是什么?为什么要使用它们?

预处理器,如:lesssassstylus,用来预编译sass或者less,增加了css代码的复用性。层级,mixin, 变量,循环, 函数等对编写以及开发UI组件都极为方便。

后处理器, 如: postCss,通常是在完成的样式表中根据css规范处理css,让其更加有效。目前最常做的是给css属性添加浏览器私有前缀,实现跨浏览器兼容性的问题。

css预处理器为css增加一些编程特性,无需考虑浏览器的兼容问题,可以在CSS中使用变量,简单的逻辑程序,函数等在编程语言中的一些基本的性能,可以让css更加的简洁,增加适应性以及可读性,可维护性等。

其它css预处理器语言:Sass(Scss), Less, Stylus, Turbine, Swithch css, CSS Cacheer, DT Css

使用原因:

  • 结构清晰, 便于扩展
  • 可以很方便的屏蔽浏览器私有语法的差异
  • 可以轻松实现多重继承
  • 完美的兼容了CSS代码,可以应用到老项目中

26. Sass、Less 是什么?为什么要使用他们?

他们都是 CSS 预处理器,是 CSS 上的一种抽象层。他们是一种特殊的语法/语言编译成 CSS。 例如 Less 是一种动态样式语言,将 CSS 赋予了动态语言的特性,如变量,继承,运算, 函数,LESS 既可以在客户端上运行 (支持 IE 6+, Webkit, Firefox),也可以在服务端运行 (借助 Node.js)。

为什么要使用它们?

  • 结构清晰,便于扩展。 可以方便地屏蔽浏览器私有语法差异。封装对浏览器语法差异的重复处理, 减少无意义的机械劳动。
  • 可以轻松实现多重继承。 完全兼容 CSS 代码,可以方便地应用到老项目中。LESS 只是在 CSS 语法上做了扩展,所以老的 CSS 代码也可以与 LESS 代码一同编译。

27. 对媒体查询的理解?

媒体查询由⼀个可选的媒体类型和零个或多个使⽤媒体功能的限制了样式表范围的表达式组成,例如宽度、⾼度和颜⾊。媒体查询,添加⾃CSS3,允许内容的呈现针对⼀个特定范围的输出设备⽽进⾏裁剪,⽽不必改变内容本身,适合web⽹⻚应对不同型号的设备⽽做出对应的响应适配。

媒体查询包含⼀个可选的媒体类型和满⾜CSS3规范的条件下,包含零个或多个表达式,这些表达式描述了媒体特征,最终会被解析为true或false。如果媒体查询中指定的媒体类型匹配展示⽂档所使⽤的设备类型,并且所有的表达式的值都是true,那么该媒体查询的结果为true。那么媒体查询内的样式将会⽣效。

1
2
3
4
5
6
7
8
9
10
<!-- link元素中的CSS媒体查询 --> 
<link rel="stylesheet" media="(max-width: 800px)" href="example.css" />
<!-- 样式表中的CSS媒体查询 -->
<style>
@media (max-width: 600px) {
.facet_sidebar {
display: none;
}
}
</style>

简单来说,使用 @media 查询,可以针对不同的媒体类型定义不同的样式。@media 可以针对不同的屏幕尺寸设置不同的样式,特别是需要设置设计响应式的页面,@media 是非常有用的。当重置浏览器大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面。

25. 单行、多行文本溢出隐藏

  • 单行文本溢出
1
2
3
overflow: hidden;            // 溢出隐藏
text-overflow: ellipsis; // 溢出用省略号显示
white-space: nowrap; // 规定段落中的文本不进行换行
  • 多行文本溢出
1
2
3
4
5
overflow: hidden;            // 溢出隐藏
text-overflow: ellipsis; // 溢出用省略号显示
display:-webkit-box; // 作为弹性伸缩盒子模型显示。
-webkit-box-orient:vertical; // 设置伸缩盒子的子元素排列方式:从上到下垂直排列
-webkit-line-clamp:3; // 显示的行数

注意:由于上面的三个属性都是 CSS3 的属性,没有浏览器可以兼容,所以要在前面加一个-webkit- 来兼容一部分浏览器。

1. 常见的CSS布局单位

常用的布局单位包括像素(px),百分比(%),emremvw/vh

(1)像素px)是页面布局的基础,一个像素表示终端(电脑、手机、平板等)屏幕所能显示的最小的区域,像素分为两种类型:CSS像素和物理像素:

  • CSS像素:为web开发者提供,在CSS中使用的一个抽象单位;
  • 物理像素:只与设备的硬件密度有关,任何设备的物理像素都是固定的。

(2)百分比%),当浏览器的宽度或者高度发生变化时,通过百分比单位可以使得浏览器中的组件的宽和高随着浏览器的变化而变化,从而实现响应式的效果。一般认为子元素的百分比相对于直接父元素。

(3)em和rem相对于px更具灵活性,它们都是相对长度单位,它们之间的区别:em相对于父元素,rem相对于根元素。

  • em: 文本相对长度单位。相对于当前对象内文本的字体尺寸。如果当前行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸(默认16px)。(相对父元素的字体大小倍数)。
  • rem: rem是CSS3新增的一个相对单位,相对于根元素(html元素)的font-size的倍数。作用:利用rem可以实现简单的响应式布局,可以利用html元素中字体的大小与屏幕间的比值来设置font-size的值,以此实现当屏幕分辨率变化时让元素也随之变化。

(4)vw/vh是与视图窗口有关的单位,vw表示相对于视图窗口的宽度,vh表示相对于视图窗口高度,除了vw和vh外,还有vmin和vmax两个相关的单位。

  • vw:相对于视窗的宽度,视窗宽度是100vw;
  • vh:相对于视窗的高度,视窗高度是100vh;
  • vmin:vw和vh中的较小值;
  • vmax:vw和vh中的较大值;

vw/vh 和百分比很类似,两者的区别:

  • 百分比(%):大部分相对于祖先元素,也有相对于自身的情况比如(border-radius、translate等)
  • vw/vm:相对于视窗的尺寸

2. px、em、rem的区别及使用场景

三者的区别:

  • px是固定的像素,一旦设置了就无法因为适应页面大小而改变。
  • em和rem相对于px更具有灵活性,他们是相对长度单位,其长度不是固定的,更适用于响应式布局。
  • em是相对于其父元素来设置字体大小,这样就会存在一个问题,进行任何元素设置,都有可能需要知道他父元素的大小。而rem是相对于根元素,这样就意味着,只需要在根元素确定一个参考值。

使用场景:

  • 对于只需要适配少部分移动设备,且分辨率对页面影响不大的,使用px即可 。
  • 对于需要适配各种移动设备,使用rem,例如需要适配iPhone和iPad等分辨率差别比较挺大的设备。

3. 两栏布局的实现

一般两栏布局指的是左边一栏宽度固定,右边一栏宽度自适应,两栏布局的具体实现:

  • 利用浮动,将左边元素宽度设置为200px,并且设置向左浮动。将右边元素的margin-left设置为200px,宽度设置为auto(默认为auto,撑满整个父元素)。
1
2
3
4
5
6
7
8
9
10
11
12
13
.outer {
height: 100px;
}
.left {
float: left;
width: 200px;
background: tomato;
}
.right {
margin-left: 200px;
width: auto;
background: gold;
}
  • 利用浮动,左侧元素设置固定大小,并左浮动,右侧元素设置overflow: hidden; 这样右边就触发了BFC,BFC的区域不会与浮动元素发生重叠,所以两侧就不会发生重叠。
1
2
3
4
5
6
7
8
9
10
11
.left{
width: 100px;
height: 200px;
background: red;
float: left;
}
.right{
height: 300px;
background: blue;
overflow: hidden;
}
  • 利用flex布局,将左边元素设置为固定宽度200px,将右边的元素设置为flex:1。
1
2
3
4
5
6
7
8
9
10
11
12
.outer {
display: flex;
height: 100px;
}
.left {
width: 200px;
background: tomato;
}
.right {
flex: 1;
background: gold;
}
  • 利用绝对定位,将父级元素设置为相对定位。左边元素设置为absolute定位,并且宽度设置为200px。将右边元素的margin-left的值设置为200px。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.outer {
position: relative;
height: 100px;
}
.left {
position: absolute;
width: 200px;
height: 100px;
background: tomato;
}
.right {
margin-left: 200px;
background: gold;
}
  • 利用绝对定位,将父级元素设置为相对定位。左边元素宽度设置为200px,右边元素设置为绝对定位,左边定位为200px,其余方向定位为0。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.outer {
position: relative;
height: 100px;
}
.left {
width: 200px;
background: tomato;
}
.right {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 200px;
background: gold;
}

4. 三栏布局的实现

三栏布局一般指的是页面中一共有三栏,左右两栏宽度固定,中间自适应的布局,三栏布局的具体实现:

  • 利用绝对定位,左右两栏设置为绝对定位,中间设置对应方向大小的margin的值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
.outer {
position: relative;
height: 100px;
}

.left {
position: absolute;
width: 100px;
height: 100px;
background: tomato;
}

.right {
position: absolute;
top: 0;
right: 0;
width: 200px;
height: 100px;
background: gold;
}

.center {
margin-left: 100px;
margin-right: 200px;
height: 100px;
background: lightgreen;
}
  • 利用flex布局,左右两栏设置固定大小,中间一栏设置为flex:1。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.outer {
display: flex;
height: 100px;
}

.left {
width: 100px;
background: tomato;
}

.right {
width: 100px;
background: gold;
}

.center {
flex: 1;
background: lightgreen;
}
  • 利用浮动,左右两栏设置固定大小,并设置对应方向的浮动。中间一栏设置左右两个方向的margin值,注意这种方式,中间一栏必须放到最后:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.outer {
height: 100px;
}

.left {
float: left;
width: 100px;
height: 100px;
background: tomato;
}

.right {
float: right;
width: 200px;
height: 100px;
background: gold;
}

.center {
height: 100px;
margin-left: 100px;
margin-right: 200px;
background: lightgreen;
}
  • 圣杯布局,利用浮动和负边距来实现。父级元素设置左右的 padding,三列均设置向左浮动,中间一列放在最前面,宽度设置为父级元素的宽度,因此后面两列都被挤到了下一行,通过设置 margin 负值将其移动到上一行,再利用相对定位,定位到两边。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
.outer {
height: 100px;
padding-left: 100px;
padding-right: 200px;
}

.left {
position: relative;
left: -100px;

float: left;
margin-left: -100%;

width: 100px;
height: 100px;
background: tomato;
}

.right {
position: relative;
left: 200px;

float: right;
margin-left: -200px;

width: 200px;
height: 100px;
background: gold;
}

.center {
float: left;

width: 100%;
height: 100px;
background: lightgreen;
}
  • 双飞翼布局,双飞翼布局相对于圣杯布局来说,左右位置的保留是通过中间列的 margin 值来实现的,而不是通过父元素的 padding 来实现的。本质上来说,也是通过浮动和外边距负值来实现的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
.outer {
height: 100px;
}

.left {
float: left;
margin-left: -100%;

width: 100px;
height: 100px;
background: tomato;
}

.right {
float: left;
margin-left: -200px;

width: 200px;
height: 100px;
background: gold;
}

.wrapper {
float: left;

width: 100%;
height: 100px;
background: lightgreen;
}

.center {
margin-left: 100px;
margin-right: 200px;
height: 100px;
}

5. 水平垂直居中的实现

  • 利用绝对定位,先将元素的左上角通过top:50%和left:50%定位到页面的中心,然后再通过translate来调整元素的中心点到页面的中心。该方法需要考虑浏览器兼容问题。
1
2
3
4
5
6
7
8
9
10
.parent {
position: relative;
}

.child {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
}
  • 利用绝对定位,设置四个方向的值都为0,并将margin设置为auto,由于宽高固定,因此对应方向实现平分,可以实现水平和垂直方向上的居中。该方法适用于盒子有宽高的情况:
1
2
3
4
5
6
7
8
9
10
11
12
.parent {
position: relative;
}

.child {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
  • 利用绝对定位,先将元素的左上角通过top:50%和left:50%定位到页面的中心,然后再通过margin负值来调整元素的中心点到页面的中心。该方法适用于盒子宽高已知的情况
1
2
3
4
5
6
7
8
9
10
11
.parent {
position: relative;
}

.child {
position: absolute;
top: 50%;
left: 50%;
margin-top: -50px; /* 自身 height 的一半 */
margin-left: -50px; /* 自身 width 的一半 */
}
  • 使用flex布局,通过align-items:center和justify-content:center设置容器的垂直和水平方向上为居中对齐,然后它的子元素也可以实现垂直和水平的居中。该方法要考虑兼容的问题,该方法在移动端用的较多:
1
2
3
4
5
.parent {
display: flex;
justify-content:center;
align-items:center;
}

6. 如何根据设计稿进行移动端适配?

移动端适配主要有两个维度:

  • 适配不同像素密度,针对不同的像素密度,使用 CSS 媒体查询,选择不同精度的图片,以保证图片不会失真;
  • 适配不同屏幕大小,由于不同的屏幕有着不同的逻辑像素大小,所以如果直接使用 px 作为开发单位,会使得开发的页面在某一款手机上可以准确显示,但是在另一款手机上就会失真。为了适配不同屏幕的大小,应按照比例来还原设计稿的内容。

为了能让页面的尺寸自适应,可以使用 rem,em,vw,vh 等相对单位。

7. 对Flex布局的理解及其使用场景

二、页面布局

1. 常见的CSS布局单位

常用的布局单位包括像素(px),百分比(%),emremvw/vh

(1)像素px)是页面布局的基础,一个像素表示终端(电脑、手机、平板等)屏幕所能显示的最小的区域,像素分为两种类型:CSS像素和物理像素:

  • CSS像素:为web开发者提供,在CSS中使用的一个抽象单位;
  • 物理像素:只与设备的硬件密度有关,任何设备的物理像素都是固定的。

(2)百分比%),当浏览器的宽度或者高度发生变化时,通过百分比单位可以使得浏览器中的组件的宽和高随着浏览器的变化而变化,从而实现响应式的效果。一般认为子元素的百分比相对于直接父元素。

(3)em和rem相对于px更具灵活性,它们都是相对长度单位,它们之间的区别:em相对于父元素,rem相对于根元素。

  • em: 文本相对长度单位。相对于当前对象内文本的字体尺寸。如果当前行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸(默认16px)。(相对父元素的字体大小倍数)。
  • rem: rem是CSS3新增的一个相对单位,相对于根元素(html元素)的font-size的倍数。作用:利用rem可以实现简单的响应式布局,可以利用html元素中字体的大小与屏幕间的比值来设置font-size的值,以此实现当屏幕分辨率变化时让元素也随之变化。

(4)vw/vh是与视图窗口有关的单位,vw表示相对于视图窗口的宽度,vh表示相对于视图窗口高度,除了vw和vh外,还有vmin和vmax两个相关的单位。

  • vw:相对于视窗的宽度,视窗宽度是100vw;
  • vh:相对于视窗的高度,视窗高度是100vh;
  • vmin:vw和vh中的较小值;
  • vmax:vw和vh中的较大值;

vw/vh 和百分比很类似,两者的区别:

  • 百分比(%):大部分相对于祖先元素,也有相对于自身的情况比如(border-radius、translate等)
  • vw/vm:相对于视窗的尺寸

2. px、em、rem的区别及使用场景

三者的区别:

  • px是固定的像素,一旦设置了就无法因为适应页面大小而改变。
  • em和rem相对于px更具有灵活性,他们是相对长度单位,其长度不是固定的,更适用于响应式布局。
  • em是相对于其父元素来设置字体大小,这样就会存在一个问题,进行任何元素设置,都有可能需要知道他父元素的大小。而rem是相对于根元素,这样就意味着,只需要在根元素确定一个参考值。

使用场景:

  • 对于只需要适配少部分移动设备,且分辨率对页面影响不大的,使用px即可 。
  • 对于需要适配各种移动设备,使用rem,例如需要适配iPhone和iPad等分辨率差别比较挺大的设备。

3. 两栏布局的实现

一般两栏布局指的是左边一栏宽度固定,右边一栏宽度自适应,两栏布局的具体实现:

  • 利用浮动,将左边元素宽度设置为200px,并且设置向左浮动。将右边元素的margin-left设置为200px,宽度设置为auto(默认为auto,撑满整个父元素)。
1
2
3
4
5
6
7
8
9
10
11
12
13
.outer {
height: 100px;
}
.left {
float: left;
width: 200px;
background: tomato;
}
.right {
margin-left: 200px;
width: auto;
background: gold;
}
  • 利用浮动,左侧元素设置固定大小,并左浮动,右侧元素设置overflow: hidden; 这样右边就触发了BFC,BFC的区域不会与浮动元素发生重叠,所以两侧就不会发生重叠。
1
2
3
4
5
6
7
8
9
10
11
.left{
width: 100px;
height: 200px;
background: red;
float: left;
}
.right{
height: 300px;
background: blue;
overflow: hidden;
}
  • 利用flex布局,将左边元素设置为固定宽度200px,将右边的元素设置为flex:1。
1
2
3
4
5
6
7
8
9
10
11
12
.outer {
display: flex;
height: 100px;
}
.left {
width: 200px;
background: tomato;
}
.right {
flex: 1;
background: gold;
}
  • 利用绝对定位,将父级元素设置为相对定位。左边元素设置为absolute定位,并且宽度设置为200px。将右边元素的margin-left的值设置为200px。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.outer {
position: relative;
height: 100px;
}
.left {
position: absolute;
width: 200px;
height: 100px;
background: tomato;
}
.right {
margin-left: 200px;
background: gold;
}
  • 利用绝对定位,将父级元素设置为相对定位。左边元素宽度设置为200px,右边元素设置为绝对定位,左边定位为200px,其余方向定位为0。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.outer {
position: relative;
height: 100px;
}
.left {
width: 200px;
background: tomato;
}
.right {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 200px;
background: gold;
}

4. 三栏布局的实现

三栏布局一般指的是页面中一共有三栏,左右两栏宽度固定,中间自适应的布局,三栏布局的具体实现:

  • 利用绝对定位,左右两栏设置为绝对定位,中间设置对应方向大小的margin的值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
.outer {
position: relative;
height: 100px;
}

.left {
position: absolute;
width: 100px;
height: 100px;
background: tomato;
}

.right {
position: absolute;
top: 0;
right: 0;
width: 200px;
height: 100px;
background: gold;
}

.center {
margin-left: 100px;
margin-right: 200px;
height: 100px;
background: lightgreen;
}
  • 利用flex布局,左右两栏设置固定大小,中间一栏设置为flex:1。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.outer {
display: flex;
height: 100px;
}

.left {
width: 100px;
background: tomato;
}

.right {
width: 100px;
background: gold;
}

.center {
flex: 1;
background: lightgreen;
}
  • 利用浮动,左右两栏设置固定大小,并设置对应方向的浮动。中间一栏设置左右两个方向的margin值,注意这种方式,中间一栏必须放到最后:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.outer {
height: 100px;
}

.left {
float: left;
width: 100px;
height: 100px;
background: tomato;
}

.right {
float: right;
width: 200px;
height: 100px;
background: gold;
}

.center {
height: 100px;
margin-left: 100px;
margin-right: 200px;
background: lightgreen;
}
  • 圣杯布局,利用浮动和负边距来实现。父级元素设置左右的 padding,三列均设置向左浮动,中间一列放在最前面,宽度设置为父级元素的宽度,因此后面两列都被挤到了下一行,通过设置 margin 负值将其移动到上一行,再利用相对定位,定位到两边。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
.outer {
height: 100px;
padding-left: 100px;
padding-right: 200px;
}

.left {
position: relative;
left: -100px;

float: left;
margin-left: -100%;

width: 100px;
height: 100px;
background: tomato;
}

.right {
position: relative;
left: 200px;

float: right;
margin-left: -200px;

width: 200px;
height: 100px;
background: gold;
}

.center {
float: left;

width: 100%;
height: 100px;
background: lightgreen;
}
  • 双飞翼布局,双飞翼布局相对于圣杯布局来说,左右位置的保留是通过中间列的 margin 值来实现的,而不是通过父元素的 padding 来实现的。本质上来说,也是通过浮动和外边距负值来实现的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
.outer {
height: 100px;
}

.left {
float: left;
margin-left: -100%;

width: 100px;
height: 100px;
background: tomato;
}

.right {
float: left;
margin-left: -200px;

width: 200px;
height: 100px;
background: gold;
}

.wrapper {
float: left;

width: 100%;
height: 100px;
background: lightgreen;
}

.center {
margin-left: 100px;
margin-right: 200px;
height: 100px;
}

5. 水平垂直居中的实现

  • 利用绝对定位,先将元素的左上角通过top:50%和left:50%定位到页面的中心,然后再通过translate来调整元素的中心点到页面的中心。该方法需要考虑浏览器兼容问题。
1
2
3
4
5
6
7
8
9
10
.parent {
position: relative;
}

.child {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
}
  • 利用绝对定位,设置四个方向的值都为0,并将margin设置为auto,由于宽高固定,因此对应方向实现平分,可以实现水平和垂直方向上的居中。该方法适用于盒子有宽高的情况:
1
2
3
4
5
6
7
8
9
10
11
12
.parent {
position: relative;
}

.child {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
  • 利用绝对定位,先将元素的左上角通过top:50%和left:50%定位到页面的中心,然后再通过margin负值来调整元素的中心点到页面的中心。该方法适用于盒子宽高已知的情况
1
2
3
4
5
6
7
8
9
10
11
.parent {
position: relative;
}

.child {
position: absolute;
top: 50%;
left: 50%;
margin-top: -50px; /* 自身 height 的一半 */
margin-left: -50px; /* 自身 width 的一半 */
}
  • 使用flex布局,通过align-items:center和justify-content:center设置容器的垂直和水平方向上为居中对齐,然后它的子元素也可以实现垂直和水平的居中。该方法要考虑兼容的问题,该方法在移动端用的较多:
1
2
3
4
5
.parent {
display: flex;
justify-content:center;
align-items:center;
}

6. 如何根据设计稿进行移动端适配?

移动端适配主要有两个维度:

  • 适配不同像素密度,针对不同的像素密度,使用 CSS 媒体查询,选择不同精度的图片,以保证图片不会失真;
  • 适配不同屏幕大小,由于不同的屏幕有着不同的逻辑像素大小,所以如果直接使用 px 作为开发单位,会使得开发的页面在某一款手机上可以准确显示,但是在另一款手机上就会失真。为了适配不同屏幕的大小,应按照比例来还原设计稿的内容。

为了能让页面的尺寸自适应,可以使用 rem,em,vw,vh 等相对单位。

7. 对Flex布局的理解及其使用场景

Flex是FlexibleBox的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为Flex布局。行内元素也可以使用Flex布局。注意,设为Flex布局以后,子元素的float、clear和vertical-align属性将失效。采用Flex布局的元素,称为Flex容器(flex container),简称”容器”。它的所有子元素自动成为容器成员,称为Flex项目(flex item),简称”项目”。容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis),项目默认沿水平主轴排列。

以下6个属性设置在容器上

  • flex-direction属性决定主轴的方向(即项目的排列方向)。
  • flex-wrap属性定义,如果一条轴线排不下,如何换行。
  • flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。
  • justify-content属性定义了项目在主轴上的对齐方式。
  • align-items属性定义项目在交叉轴上如何对齐。
  • align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。

以下6个属性设置在项目上

  • order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
  • flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
  • flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
  • flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
  • flex属性是flex-grow,flex-shrink和flex-basis的简写,默认值为0 1 auto。
  • align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。

简单来说:

flex布局是CSS3新增的一种布局方式,可以通过将一个元素的display属性值设置为flex从而使它成为一个flex容器,它的所有子元素都会成为它的项目。一个容器默认有两条轴:一个是水平的主轴,一个是与主轴垂直的交叉轴。可以使用flex-direction来指定主轴的方向。可以使用justify-content来指定元素在主轴上的排列方式,使用align-items来指定元素在交叉轴上的排列方式。还可以使用flex-wrap来规定当一行排列不下时的换行方式。对于容器中的项目,可以使用order属性来指定项目的排列顺序,还可以使用flex-grow来指定当排列空间有剩余的时候,项目的放大比例,还可以使用flex-shrink来指定当排列空间不足时,项目的缩小比例。

9. 响应式设计的概念及基本原理

响应式网站设计(Responsive Web design)是一个网站能够兼容多个终端,而不是为每一个终端做一个特定的版本。

关于原理: 基本原理是通过媒体查询(@media)查询检测不同的设备屏幕尺寸做处理。

关于兼容: 页面头部必须有mate声明的viewport

1
<meta name="’viewport’" content="”width=device-width," initial-scale="1." maximum-scale="1,user-scalable=no”"/>

三、定位与浮动

1. 为什么需要清除浮动?清除浮动的方式

浮动的定义: 非IE浏览器下,容器不设高度且子元素浮动时,容器高度不能被内容撑开。 此时,内容会溢出到容器外面而影响布局。这种现象被称为浮动(溢出)。

浮动的工作原理:

  • 浮动元素脱离文档流,不占据空间(引起“高度塌陷”现象)
  • 浮动元素碰到包含它的边框或者其他浮动元素的边框停留

浮动元素可以左右移动,直到遇到另一个浮动元素或者遇到它外边缘的包含框。浮动框不属于文档流中的普通流,当元素浮动之后,不会影响块级元素的布局,只会影响内联元素布局。此时文档流中的普通流就会表现得该浮动框不存在一样的布局模式。当包含框的高度小于浮动框的时候,此时就会出现“高度塌陷”。

浮动元素引起的问题?

  • 父元素的高度无法被撑开,影响与父元素同级的元素
  • 与浮动元素同级的非浮动元素会跟随其后
  • 若浮动的元素不是第一个元素,则该元素之前的元素也要浮动,否则会影响页面的显示结构

清除浮动的方式如下:

  • 给父级div定义height属性
  • 最后一个浮动元素之后添加一个空的div标签,并添加clear:both样式
  • 包含浮动元素的父级标签添加overflow:hidden或者overflow:auto
  • 使用 :after 伪元素。由于IE6-7不支持 :after,使用 zoom:1 触发 hasLayout**
1
2
3
4
5
6
7
8
9
.clearfix:after{
content: "\200B";
display: table;
height: 0;
clear: both;
}
.clearfix{
*zoom: 1;
}

使用clear属性清除浮动,其语法如下:

1
clear:none|left|right|both

如果单看字面意思,clear:left 是“清除左浮动”,clear:right 是“清除右浮动”,实际上,这种解释是有问题的,因为浮动一直还在,并没有清除。

官方对clear属性解释:“元素盒子的边不能和前面的浮动元素相邻”,对元素设置clear属性是为了避免浮动元素对该元素的影响,而不是清除掉浮动。

还需要注意 clear 属性指的是元素盒子的边不能和前面的浮动元素相邻,注意这里“前面的”3个字,也就是clear属性对“后面的”浮动元素是不闻不问的。考虑到float属性要么是left,要么是right,不可能同时存在,同时由于clear属性对“后面的”浮动元素不闻不问,因此,当clear:left有效的时候,clear:right必定无效,也就是此时clear:left等同于设置clear:both;同样地,clear:right如果有效也是等同于设置clear:both。由此可见,clear:left和clear:right这两个声明就没有任何使用的价值,至少在CSS世界中是如此,直接使用clear:both吧。

一般使用伪元素的方式清除浮动:

1
2
3
4
5
.clear::after{
content:'';
display: block;
clear:both;
}

clear属性只有块级元素才有效的,而::after等伪元素默认都是内联水平,这就是借助伪元素清除浮动影响时需要设置display属性值的原因。

3. 对BFC的理解,如何创建BFC

先来看两个相关的概念:

  • Box: Box 是 CSS 布局的对象和基本单位,⼀个⻚⾯是由很多个 Box 组成的,这个Box就是我们所说的盒模型。
  • Formatting context:块级上下⽂格式化,它是⻚⾯中的⼀块渲染区域,并且有⼀套渲染规则,它决定了其⼦元素将如何定位,以及和其他元素的关系和相互作⽤。

块格式化上下文(Block Formatting Context,BFC)是Web页面的可视化CSS渲染的一部分,是布局过程中生成块级盒子的区域,也是浮动元素与其他元素的交互限定区域。

通俗来讲:BFC是一个独立的布局环境,可以理解为一个容器,在这个容器中按照一定规则进行物品摆放,并且不会影响其它环境中的物品。如果一个元素符合触发BFC的条件,则BFC中的元素布局不受外部影响。

创建BFC的条件:

  • 根元素:body;
  • 元素设置浮动:float 除 none 以外的值;
  • 元素设置绝对定位:position (absolute、fixed);
  • display 值为:inline-block、table-cell、table-caption、flex等;
  • overflow 值为:hidden、auto、scroll;

BFC的特点:

  • 垂直方向上,自上而下排列,和文档流的排列方式一致。
  • 在BFC中上下相邻的两个容器的margin会重叠
  • 计算BFC的高度时,需要计算浮动元素的高度
  • BFC区域不会与浮动的容器发生重叠
  • BFC是独立的容器,容器内部元素不会影响外部元素
  • 每个元素的左margin值和容器的左border相接触

BFC的作用:

  • 解决margin的重叠问题:由于BFC是一个独立的区域,内部的元素和外部的元素互不影响,将两个元素变为两个BFC,就解决了margin重叠的问题。
  • 解决高度塌陷的问题:在对子元素设置浮动后,父元素会发生高度塌陷,也就是父元素的高度变为0。解决这个问题,只需要把父元素变成一个BFC。常用的办法是给父元素设置overflow:hidden
  • 创建自适应两栏布局:可以用来创建自适应两栏布局:左边的宽度固定,右边的宽度自适应。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.left{
width: 100px;
height: 200px;
background: red;
float: left;
}
.right{
height: 300px;
background: blue;
overflow: hidden;
}

<div class="left"></div>
<div class="right"></div>

左侧设置float:left,右侧设置overflow: hidden。这样右边就触发了BFC,BFC的区域不会与浮动元素发生重叠,所以两侧就不会发生重叠,实现了自适应两栏布局。

4. 什么是margin重叠问题?如何解决?

问题描述:

两个块级元素的上外边距和下外边距可能会合并(折叠)为一个外边距,其大小会取其中外边距值大的那个,这种行为就是外边距折叠。需要注意的是,浮动的元素和绝对定位这种脱离文档流的元素的外边距不会折叠。重叠只会出现在垂直方向

计算原则:

折叠合并后外边距的计算原则如下:

  • 如果两者都是正数,那么就去最大者
  • 如果是一正一负,就会正值减去负值的绝对值
  • 两个都是负值时,用0减去两个中绝对值大的那个

解决办法:

对于折叠的情况,主要有两种:兄弟之间重叠父子之间重叠

(1)兄弟之间重叠

  • 底部元素变为行内盒子:display: inline-block
  • 底部元素设置浮动:float
  • 底部元素的position的值为absolute/fixed

(2)父子之间重叠

  • 父元素加入:overflow: hidden
  • 父元素添加透明边框:border:1px solid transparent
  • 子元素变为行内盒子:display: inline-block
  • 子元素加入浮动属性或定位

层叠顺序,英文称作 stacking order,表示元素发生层叠时有着特定的垂直显示顺序。下面是盒模型的层叠规则:

img

对于上图,由上到下分别是:

(1)背景和边框:建立当前层叠上下文元素的背景和边框。

(2)负的z-index:当前层叠上下文中,z-index属性值为负的元素。

(3)块级盒:文档流内非行内级非定位后代元素。

(4)浮动盒:非定位浮动元素。

(5)行内盒:文档流内行内级非定位后代元素。

(6)z-index:0:层叠级数为0的定位元素。

(7)正z-index:z-index属性值为正的定位元素。

注意: 当定位元素z-index:auto,生成盒在当前层叠上下文中的层级为 0,不会建立新的层叠上下文,除非是根元素。

6. position的属性有哪些,区别是什么

position有以下属性值:

属性值 概述
absolute 生成绝对定位的元素,相对于static定位以外的一个父元素进行定位。元素的位置通过left、top、right、bottom属性进行规定。
relative 生成相对定位的元素,相对于其原来的位置进行定位。元素的位置通过left、top、right、bottom属性进行规定。
fixed 生成绝对定位的元素,指定元素相对于屏幕视⼝(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变,⽐如回到顶部的按钮⼀般都是⽤此定位⽅式。
static 默认值,没有定位,元素出现在正常的文档流中,会忽略 top, bottom, left, right 或者 z-index 声明,块级元素从上往下纵向排布,⾏级元素从左向右排列。
inherit 规定从父元素继承position属性的值

前面三者的定位方式如下:

  • relative:元素的定位永远是相对于元素自身位置的,和其他元素没关系,也不会影响其他元素。

img

  • fixed:元素的定位是相对于 window (或者 iframe)边界的,和其他元素没有关系。但是它具有破坏性,会导致其他元素位置的变化。

img

  • absolute:元素的定位相对于前两者要复杂许多。如果为 absolute 设置了 top、left,浏览器会根据什么去确定它的纵向和横向的偏移量呢?答案是浏览器会递归查找该元素的所有父元素,如果找到一个设置了position:relative/absolute/fixed的元素,就以该元素为基准定位,如果没找到,就以浏览器边界定位。如下两个图所示:

img

img

7. display、float、position的关系

(1)首先判断display属性是否为none,如果为none,则position和float属性的值不影响元素最后的表现。

(2)然后判断position的值是否为absolute或者fixed,如果是,则float属性失效,并且display的值应该被设置为table或者block,具体转换需要看初始转换值。

(3)如果position的值不为absolute或者fixed,则判断float属性的值是否为none,如果不是,则display的值则按上面的规则转换。注意,如果position的值为relative并且float属性的值存在,则relative相对于浮动后的最终位置定位。

(4)如果float的值为none,则判断元素是否为根元素,如果是根元素则display属性按照上面的规则转换,如果不是,则保持指定的display属性值不变。

总的来说,可以把它看作是一个类似优先级的机制,”position:absolute”和”position:fixed”优先级最高,有它存在的时候,浮动不起作用,’display’的值也需要调整;其次,元素的’float’特性的值不是”none”的时候或者它是根元素的时候,调整’display’的值;最后,非根元素,并且非浮动元素,并且非绝对定位的元素,’display’特性值同设置值。

四、场景应用

1. 实现一个三角形

CSS绘制三角形主要用到的是border属性,也就是边框。

平时在给盒子设置边框时,往往都设置很窄,就可能误以为边框是由矩形组成的。实际上,border属性是右三角形组成的,下面看一个例子:

1
2
3
4
5
6
div {
width: 0;
height: 0;
border: 100px solid;
border-color: orange blue red green;
}

将元素的长宽都设置为0,显示出来的效果是这样的:

img

所以可以根据border这个特性来绘制三角形:

(1)三角1

1
2
3
4
5
6
7
div {
width: 0;
height: 0;
border-top: 50px solid red;
border-right: 50px solid transparent;
border-left: 50px solid transparent;
}

img

(2)三角2

1
2
3
4
5
6
7
div {
width: 0;
height: 0;
border-bottom: 50px solid red;
border-right: 50px solid transparent;
border-left: 50px solid transparent;
}

img

(3)三角3

1
2
3
4
5
6
7
div {
width: 0;
height: 0;
border-left: 50px solid red;
border-top: 50px solid transparent;
border-bottom: 50px solid transparent;
}

img

(4)三角4

1
2
3
4
5
6
7
div {
width: 0;
height: 0;
border-right: 50px solid red;
border-top: 50px solid transparent;
border-bottom: 50px solid transparent;
}

img

(5)三角5

1
2
3
4
5
6
div {
width: 0;
height: 0;
border-top: 100px solid red;
border-right: 100px solid transparent;
}

img

还有很多,就不一一实现了,总体的原则就是通过上下左右边框来控制三角形的方向,用边框的宽度比来控制三角形的角度。

2. 实现一个扇形

用CSS实现扇形的思路和三角形基本一致,就是多了一个圆角的样式,实现一个90°的扇形:

1
2
3
4
5
6
7
div{
border: 100px solid transparent;
width: 0;
height: 0;
border-radius: 100px;
border-top-color: red;
}

img

(1)实现圆:

1
2
3
4
5
6
div {
background-color: red;
height: 100px;
width: 100px;
border-radius: 50%;
}

注意:在使用border-radius时,使用50%和100%都可以得到一个圆,那这两个值到底有什么区别呢:border-radius的值是百分比的话,就相当于盒子的宽度和高度的百分比。如一个50px 150px的方形,如果border-radius设置为100%,则等价于:

1
border-radius: 50px/150px; 1

而border-radius又是由border-top-left-radius、border-top-right-radius、border-bottom-left-radius、border-bottom-right-radius组成,所有上面border-radius:100%又等价于:

1
2
3
4
border-top-left-radius: 100%; 
border-top-right-radius: 100%;
border-bottom-left-radius: 100%;
border-bottom-right-radius: 100%;

1
2
3
4
border-top-left-radius: 50px 150px; 
border-top-right-radius: 50px 150px;
border-bottom-left-radius: 50px 150px;
border-bottom-right-radius: 50px 150px;

为什么border-radius设置成100%和50%都能画成圆呢?因为,在W3C中对重合曲线做了规定:如果两个相邻的半径和超过了对应的盒子的边的长度,那么浏览器要重新计算以保证它们不重合。也就是说,如果相邻圆角的半径都设置成大于50%,那么浏览器会根据图形的实际情况做一些计算。因此,为了避免不必要的计算,建议使用border-radius: 50%。

(2)实现半圆:

1
2
3
4
5
6
div {
background-color: red;
width: 100px;
height: 50px;
border-radius: 0px 0px 100px 100px;
}
  • 利用vw来实现:
1
2
3
4
5
.square {
width: 10%;
height: 10vw;
background: tomato;
}
  • 利用元素的margin/padding百分比是相对父元素width的性质来实现:
1
2
3
4
5
6
.square {
width: 20%;
height: 0;
padding-top: 20%;
background: orange;
}
  • 利用子元素的margin-top的值来实现:
1
2
3
4
5
6
7
8
9
10
.square {
width: 30%;
overflow: hidden;
background: yellow;
}
.square::after {
content: '';
display: block;
margin-top: 100%;
}
1
<div class="trapezoid"></div>

(1)实现一个直角梯形:

1
2
3
4
5
6
.trapezoid {
height: 0;
width: 100px;
border-bottom: 100px solid red;
border-right: 40px solid transparent;
}

效果:

img

(2)实现一个等腰梯形

1
2
3
4
5
6
7
.trapezoid {
height:0;
width:100px;
border-width:0 40px 100px 40px;
border-style:none solid solid;
border-color:transparent transparent red;
}

效果:

img

5. 画一条0.5px的线

  • 采用transform: scale()的方式,该方法用来定义元素的2D 缩放转换:
1
transform: scale(0.5,0.5);
  • 采用meta viewport的方式
1
<meta name="viewport" content="width=device-width, initial-scale=0.5, minimum-scale=0.5, maximum-scale=0.5"/>

这样就能缩放到原来的0.5倍,如果是1px那么就会变成0.5px。viewport只针对于移动端,只在移动端上才能看到效果

6. 设置小于12px的字体

在谷歌下css设置字体大小为12px及以下时,显示都是一样大小,都是默认12px。

解决办法:

  • 使用Webkit的内核的-webkit-text-size-adjust的私有CSS属性来解决,只要加了-webkit-text-size-adjust:none;字体大小就不受限制了。但是chrome更新到27版本之后就不可以用了。所以高版本chrome谷歌浏览器已经不再支持-webkit-text-size-adjust样式,所以要使用时候慎用。
  • 使用css3的transform缩放属性-webkit-transform:scale(0.5); 注意-webkit-transform:scale(0.75);收缩的是整个元素的大小,这时候,如果是内联元素,必须要将内联元素转换成块元素,可以使用display:block/inline-block/…;
  • 使用图片:如果是内容固定不变情况下,使用将小于12px文字内容切出做图片,这样不影响兼容也不影响美观。

7. 如何解决 1px 问题?

1px 问题指的是:在一些 Retina屏幕 的机型上,移动端页面的 1px 会变得很粗,呈现出不止 1px 的效果。原因很简单——CSS 中的 1px 并不能和移动设备上的 1px 划等号。它们之间的比例关系有一个专门的属性来描述:

1
window.devicePixelRatio = 设备的物理像素 / CSS像素。

打开 Chrome 浏览器,启动移动端调试模式,在控制台去输出这个 devicePixelRatio 的值。这里选中 iPhone6/7/8 这系列的机型,输出的结果就是2:

img

这就意味着设置的 1px CSS 像素,在这个设备上实际会用 2 个物理像素单元来进行渲染,所以实际看到的一定会比 1px 粗一些。

解决**1px 问题的三种思路:**

思路一:直接写 0.5px

如果之前 1px 的样式这样写:

1
border:1px solid #333

可以先在 JS 中拿到 window.devicePixelRatio 的值,然后把这个值通过 JSX 或者模板语法给到 CSS 的 data 里,达到这样的效果(这里用 JSX 语法做示范):

1
<div id="container" data-device={{window.devicePixelRatio}}></div>

然后就可以在 CSS 中用属性选择器来命中 devicePixelRatio 为某一值的情况,比如说这里尝试命中 devicePixelRatio 为2的情况:

1
2
3
#container[data-device="2"] {
border:0.5px solid #333
}

直接把 1px 改成 1/devicePixelRatio 后的值,这是目前为止最简单的一种方法。这种方法的缺陷在于兼容性不行,IOS 系统需要8及以上的版本,安卓系统则直接不兼容。

思路二:伪元素先放大后缩小

这个方法的可行性会更高,兼容性也更好。唯一的缺点是代码会变多。

思路是先放大、后缩小:**在目标元素的后面追加一个 ::after 伪元素,让这个元素布局为 absolute 之后、整个伸展开铺在目标元素上,然后把它的宽和高都设置为目标元素的两倍,border值设为 1px。接着借助 CSS 动画特效中的放缩能力,把整个伪元素缩小为原来的 50%。此时,伪元素的宽高刚好可以和原有的目标元素对齐,而 border 也缩小为了 1px 的二分之一**,间接地实现了 0.5px 的效果。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#container[data-device="2"] {
position: relative;
}
#container[data-device="2"]::after{
position:absolute;
top: 0;
left: 0;
width: 200%;
height: 200%;
content:"";
transform: scale(0.5);
transform-origin: left top;
box-sizing: border-box;
border: 1px solid #333;
}
}

思路三:viewport 缩放来解决

这个思路就是对 meta 标签里几个关键属性下手:

1
<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">

这里针对像素比为2的页面,把整个页面缩放为了原来的1/2大小。这样,本来占用2个物理像素的 1px 样式,现在占用的就是标准的一个物理像素。根据像素比的不同,这个缩放比例可以被计算为不同的值,用 js 代码实现如下:

1
2
3
const scale = 1 / window.devicePixelRatio;
// 这里 metaEl 指的是 meta 标签对应的 Dom
metaEl.setAttribute('content', `width=device-width,user-scalable=no,initial-scale=${scale},maximum-scale=${scale},minimum-scale=${scale}`);

这样解决了,但这样做的副作用也很大,整个页面被缩放了。这时 1px 已经被处理成物理像素大小,这样的大小在手机上显示边框很合适。但是,一些原本不需要被缩小的内容,比如文字、图片等,也被无差别缩小掉了。


CSS
https://www.zhengcookie.site/2025/07/12/CSS/
作者
zhengcookie
发布于
2025年7月12日
许可协议