如何实现一个三角形?
原理:border
在前端 CSS 里,要把方块转变为三角形,主要借助边框属性来实现。下面为你介绍具体的实现方法:
css
.triangle {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid #3498db;
}
实现方法
原理:元素的border是由三角形组合而成

- 宽高设为 0:把元素的宽度和高度都设成 0,这样元素本身就不会占据空间。
- 利用边框:通过设置不同方向的边框,让它们相互叠加,从而形成三角形。
- 控制边框颜色:将左右边框的颜色设为透明,底部边框设置成你想要的颜色,这样就呈现出一个朝上的三角形。
改变三角形的方向:
- 朝上的三角形:左右边框透明,底部边框设置颜色。
- 朝下的三角形:左右边框透明,顶部边框设置颜色。
- 朝左的三角形:上下边框透明,右边框设置颜色。
- 朝右的三角形:上下边框透明,左边框设置颜色。
下面是一个朝下三角形的示例:
css
.triangle-down {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-top: 100px solid #e74c3c;
}
Flex:1 和 Flex auto 的区别?
在 Flexbox 布局中,flex: auto 和 flex: 1 是两个不同的简写值,简写语法如下
ini
flex: [flex-grow] [flex-shrink] [flex-basis];
flex-grow
定义如何瓜分主轴上的剩余空间,默认值是 0,即使还有剩余空间也不瓜分。
- 数值越大,分配到的剩余空间越大(按比例来,如下图所示)
- 计算方式:剩余空间 x,flex-grow 的值分别为 a,b,c
-
- 每个元素可以分配的剩余空间为: a/(a+b+c) * x,b/(a+b+c) * x,c/(a+b+c) * x
- 以A为例:1/(1+2+3) = 1/6,A"瓜分"到的
150*1/6=25,实际宽度为100+25=125。

flex-shrink
由于 flex 默认不换行,所以当父容器空间不足时,则将子元素"收缩",默认值为 1(即空间不够时会缩小)
- 数值越大,收缩比例越高(如下图)
- 计算方式:三个元素的宽度为 w1 w2 w3,flex-shrink 分别为 a,b,c,以 A 元素为例计算
-
- 计算总压缩权重:
sum = a * w1 + b * w2 + c * w3(300 * 1 + 150 * 2 + 200 * 3 = 1200) - 计算每个元素压缩率:
S1 = a * w1 / sum(300*1 / 1200 = 0.25) - 计算每个元素宽度:
width - 压缩率 * 溢出空间(300 - (150 * 0.25) = 262.5)
- 计算总压缩权重:
注意:
- 如果子容器没有超出父容器,设置 flex-shrink 无效
- 计算方式和 flex-grow 是不一样的

flex-basis
指定了 flex 元素在主轴方向上的初始大小,默认值为 auto(即由项目自身内容或 width/height 决定),也可以设为具体数值(如 100px)或百分比。
- 优先级:
max-width/min-width > flex-basis > width > box flex-basis是「初始尺寸」,flex-grow(扩展)和flex-shrink(收缩)都是基于这个初始尺寸来计算空间分配 / 收缩的
flex: 1 和 flex: auto 的区别
真正的差异只有 flex-basis:一个是 0%,一个是 auto。
| 简写属性 | 完整写法 | flex-grow | flex-shrink | flex-basis |
|---|---|---|---|---|
| flex:1 | flex: 1 1 0% | 1 | 1 | 0% |
| flex:auto | flex: 1 1 auto | 1 | 1 | auto |
flex:1
- 忽略自身元素内容大小,强制按比例均分空间
- 如下所示,即使文本长度不一样,每个子元素的宽度依旧相等

flex: auto
- 优先保留元素自身内容尺寸,再分剩余空间。
- 如下图所示,文本长度(元素宽度)不一样时,每个元素宽度不一样

应用场景
需要 "等分空间"------ 用 flex:1
- 如卡片等分显示,多个导航栏均等显示
需要"优先保证内容显示"------ 用 flex:auto
- 搜索框布局,需要优先保证输入框可输入宽度
Float 为什么要清除浮动?以及如何清除?
最开始的作用:图文环绕
要实现这样的效果,决定了 float 的两个特性:
- "破坏文档流",使得父元素得高度塌陷。
- 禁止行框盒子与浮动元素发生重叠

一:为什么要清除浮动?
当子元素设置了float: left/right后,脱离文档流会引发以下问题:
- 父容器高度塌陷 :父元素的高度默认由子元素撑开,但浮动元素 "飘" 起来后,父元素会认为内部没有可撑开高度的内容,高度变为
0。 - 布局混乱:页面下方的元素会 "钻" 到浮动元素下方,导致排版错位、重叠等问题。
- 背景和边框显示异常:父容器的背景和边框无法正常包裹浮动元素。
如以下布局:
ini
<div class="parent">
<div class="float-item">浮动元素</div>
</div>
<div class="next">后续元素</div>

二:如何清除浮动?(按推荐度排序)
以下是常见的清除浮动方法:
clearfix 伪元素法(最佳实践 / 主流方案)
通过 CSS 为父容器添加伪元素,自动清除浮动。
- 原理:
clear: both表示元素的左右两侧都不允许有浮动元素; - 不增加冗余 HTML 标签,兼容性好(支持所有主流浏览器)
- 可封装成通用类
css
.clearfix::after {
content: "";
display: block;
clear: both; /* 核心:清除左右浮动 */
visibility: hidden; /* 隐藏伪元素 */
height: 0; /* 避免占用额外空间 */
}
BFC(块级格式化上下文)
为父容器设置overflow: auto/hidden,使其创建 BFC
- 原理:BFC 会包裹内部的浮动元素,自动计算父元素高度。
- 缺点:如果子元素有超出父元素的内容(如下拉菜单、弹出层),会被
overflow: hidden裁剪掉,适合简单布局。
使用 flexbox 或 Grid 布局
- 原理:现代布局方式会自动包含子元素,无需清除浮动。
- 缺点:兼容性没上面的高
额外标签法(不推荐,冗余标签)
在所有浮动子元素的末尾,添加一个空的块级标签(如 <div>),并设置 clear: both。
- 原理:直接在浮动元素后插入一个清除浮动的元素,强制父元素识别高度;
- 缺点:增加无意义的 HTML 冗余标签
如何实现 0.5px 边框?
在标准 css 中,通常无法直接设置 0.5px 的边框宽度,因为 css 像素的浏览器的最小渲染单位,而不支持亚像素级的渲染。但是可以通过一些技巧来模拟实现。
伪元素
可以使用伪元素 ::before 或 ::after 来创建一个额外的边框层,并设置高度为 0.5px。
css
.element {
position: relative;
}
.element::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 200%; /* 缩放后还原宽度 */
height: 200%; /* 缩放后还原高度 */
border: 1px solid #ccc; /* 先设 1px 边框 */
transform: scale(0.5); /* 缩放 0.5 倍,边框变为 0.5px */
transform-origin: 0 0; /* 缩放原点定位到左上角,避免偏移 */
box-sizing: border-box; /* 边框计入宽高,防止溢出 */
pointer-events: none; /* 伪元素不拦截点击事件 */
}
阴影效果
可以使用 box-shadow 属性来模拟一个细边框的效果
css
.element {
border: 1px solid transparent; /* 隐藏主边框 */
box-shadow: 0 0 0 0.5px #000; /* 模拟 0.5px 边框 */
}
em 与 rem 的区别?
1. em (相对单位)
- 参考基准 :当前元素的字体大小 (
font-size)。 - 计算规则 :如果当前元素的
font-size为16px,则1em = 16px,2em = 32px。 - 特点 :嵌套元素会继承父元素的字体大小,导致多次嵌套时可能出现尺寸累积。
2. rem (根相对单位)
- 参考基准 :根元素 (即
<html>标签)的字体大小。 - 计算规则 :如果
<html>的font-size为16px,则1rem = 16px,2rem = 32px。 - 特点 :全局统一,不受父元素字体大小影响,避免嵌套层级过深导致的尺寸失控。
浏览器的默认字体尺寸为 16px,所以有以下设置
css
html {
font-size: 62.%; /* 公式16px*62.5%=10px */
}
什么是 BFC?
BFC (块级格式化上下文):
- 简单来说,BFC是一个完全独立的空间(布局环境),让空间里的子元素不会影响到外面的布局
当浮动时,会导致高度塌陷问题,如下图所示:
- 黄色框向左浮动,使它
脱离了原本的位置,由此绿色框被定位到灰色父元素,并与浮动元素重叠。 - 由于父元素灰色框没有创建 BFC,由此计算高度时不会考虑灰色框的区域,也就是常见的
高度坍塌问题
arduino
<div class='box'> // 灰色框
<div class='left' /> // 黄色框,向左浮动
<div class='right' /> // 绿色框
</div>

如何创建 BFC
- 根元素或其他包含它的元素
- 浮动:
float: 不为 none - 绝对定位元素:
position: absolute / fixed - 行内块级元素:
display: inline-block - 表格单元格:
display: table-cell overflow的值不为 visible的元素- 弹性盒子:
display: flex / inline-flex
BFC 的应用和效果
应用一:防止高度坍塌
给灰色框创建一个新的 BFC 后,高度计算时会包括浮动元素(灰色框高度变化)
ini
.BFC {
overflow: hiddle;
}
<div className='box BFC'>
<div className='left' />
<div className='right' />
</div>

应用二:阻止与浮动元素重叠
- 如下例:由于绿色框没有创建 BFC,其中的白色块受到黄色框(浮动元素)的影响,被挤到右边的同时超出了绿色框的范围。
xml
<style>
.little{
background: #fff;
width: 50px;
height: 50px;
margin: 10px;
float: left;
}
</style>
<div className='box BFC'>
<div className='left' />
<div className='right'>
<div className='little' />
<div className='little' />
<div className='little' />
</div>
</div>

- 给绿色框创建 BFC 后,则并不会与黄色框发生重叠,同时由于 BFC 的隔离作用(
一个独立容器),白色块不会受到黄色浮动框的影响(也说明其每个元素的margin box的左边,与容器块border box的左边相接触) - 注意:触发 BFC
不能阻止其他形式的脱离文档流的元素覆盖正常流元素(比如绝对定位元素)
css
<div className='right BFC'>
...
</div>

应用三:阻止 margin 合并
阻止相邻元素的 margin 合并
给两个框分别添加 margin,由图可知相邻的 margin 会被合并
ini
<div className="box BFC">
<div className="left" /> // margin: 20px;
<div className="right" /> // margin: 20px;
</div>

- 给其中一个元素(也可以两个元素)设置 BFC,可以
阻止 margin 的合并 - 注意:块级元素会默认铺满一行
ini
<div className="box BFC">
<div className="BFC">
<div className="left" />
</div>
<div className="right" />
</div>

应用四:自适应两栏布局
- 利用 BFC
不会与浮动元素重叠的特性,同时由于块级元素默认铺满整行,就可以实现两栏自适应布局
ini
<div className="box BFC">
<div className="left" /> // 保持左浮动
<div className="right BFC" /> // 删除 width
</div>

什么是盒模型?
可以认为每个html标签都是一个方块,然后这个方块又包着几个小方块,如同盒子一层层的包裹着,这就是所谓的盒模型。
默认width只是内容宽度,不是整体大小。
W3C 标准盒模型:box-sizing: content-box
内容的宽高度不包含 border 和 padding
- 属性 width, height 只包含内容 content ,不包含 border 和 padding。
- width = 内容的宽度
- height = 内容的高度
实际占用空间大于设定的宽高。
IE 盒模型:box-sizing: border-box
内容的宽高度包含 border 和 padding
- 属性 width, height 包含 border 和 padding,指的是 content+padding+border。
- width = border + padding + 内容的宽度
- height = border + padding + 内容的高度
这种模式的优势在于:
- 可以确切知道每个元素会占据多少空间,特别适合做栅格系统、卡片布局等需要精确控制尺寸的场景。
使用技巧
- 如果不想让 padding 或 margin 改变盒模型定义的宽高,则使用 border-box
- 尽量使用标准的W3C模型(需在页面中声明 DOCTYPE 类型),这样可以避免多个浏览器对同一页面的不兼容
-
- 若不声明 DOCTYPE 类型,IE浏览器会将盒子模型解释为IE盒子模型,FireFox 等会将其解释为 W3C 盒子模型;
- 若在页面中声明了 DOCTYPE 类型,所有的浏览器都会把盒模型解释为 W3C 盒模型。
css有哪些选择器?以及优先级?
层叠(Cascading)是CSS的一个核心机制,它决定了当多个样式规则应用到同一个元素时,哪些规则会生效,以及生效的顺序。
常见的 css 选择器
元素选择器(Element Selector):选择指定元素类型的所有元素(p)类选择器(Class Selector):选择具有指定类名的元素,使用"."符号表示(.class)ID选择器(ID Selector):选择具有指定id的唯一元素,使用"#"符号表示(#myId)属性选择器(Attribute Selector):选择具有指定属性或属性值的元素([type="text"])后代选择器(Descendant Selector):选择指定元素的后代元素,使用空格分隔,例如div p选择所有div元素内部的p元素。直接子元素选择器(Child Selector):选择指定元素的直接子元素,使用">"符号表示,例如div > p选择所有div元素的直接子元素p。伪类选择器(Pseudo-class Selector):选择具有特定状态或行为的元素,例如:hover选择鼠标悬停的元素。伪元素选择器(Pseudo-element Selector):选择元素的特定部分,例如::before选择元素的前面插入内容。
选择器优先级和权重列表
| 样式类型 | 权重值 | 示例 |
|---|---|---|
| 内联样式 | 1000 | style="color: red" |
| ID选择器 | 100 | #header |
| 类选择器 | 10 | .blue, .active |
| 元素选择器 | 1 | div, p |
| 通用选择器 | 0 | * |
注意点:
- CSS 选择器的特殊性(Specificity,权重) 遵循位权计算规则 ,存在层级壁垒 ,低层级选择器的数量无论堆叠多少,都永远无法跨越层级超过高层级选择器,这是和普通「数字加法」最本质的区别。
- 高位权重只要有值,低位权重堆到无穷大也无法超越。
- 同权重时,「后声明」覆盖「先声明」
- 继承的样式权重为 0, 会被子元素自身的任意选择器覆盖
重绘与回流的区别?
重绘(Repaint)和回流(Reflow)是与浏览器渲染引擎相关的概念,它们可以影响网页的性能。
回流
先画「骨架」------ 确定每个元素的位置、大小、间距(比如盒子的宽高、top/left、margin);
如果骨架变了(如盒子宽度变化),就需要重新计算所有相关元素的位置和尺寸,这个过程就是回流。
常见操作:(只要改变元素的几何属性,就会触发回流)
- 修改元素尺寸、位置、字体、文本
- 增减 / 修改 DOM 节点
- 修改浏览器窗口
- 读取某些布局属性:
offsetWidth/offsetHeight/clientWidth/getComputedStyle()(浏览器为了获取准确值,会强制触发回流)。 - 使用 JavaScript 计算样式或布局。
重绘
骨架不变,只改「外观」------ 比如改颜色、背景、阴影、透明度。
只需要在原有骨架上重新上色,不用动结构,这个过程就是重绘。
常见操作:只改视觉样式,不碰布局,仅触发重绘
- 修改颜色、阴影、透明度、背景图、光标等
性能优化:减少不必要的回流/重绘
批量修改,减少多次回流
- 合并样式修改
ini
const box = document.getElementById('box');
// 每改一个样式,触发一次回流
box.style.width = '200px';
box.style.height = '100px';
// 合并style属性 或 添加类名
box.style.cssText = 'width:200px; height:100px; margin:20px;';
// CSS:.box-new { width:200px; height:100px; margin:20px; }
box.classList.add('box-new');
- 先「离线」修改 DOM,再「上线」
把元素从 DOM 树中移除,修改完成后再加回去(仅触发 2 次回流:移除 + 添加)
ini
const ul = document.getElementById('list');
// 1. 离线:移除DOM
ul.style.display = 'none';
// 2. 批量修改(无回流)
for (let i = 0; i < 100; i++) {
const li = document.createElement('li');
li.textContent = `Item ${i}`;
ul.appendChild(li);
}
// 3. 上线:重新显示
ul.style.display = 'block';
避免频繁读取「触发回流的属性」
如下例所示:每次读 offsetWidth 都触发回流,共 100 次,如果先缓存属性值,则仅触发一次;
ini
const box = document.getElementById('box');
let width = 0;
for (let i = 0; i < 100; i++) {
width = box.offsetWidth; // 每次读取都强制回流
box.style.left = `${width + i}px`;
}
// 先读取一次,缓存值
const baseWidth = box.offsetWidth;
let width = baseWidth;
for (let i = 0; i < 100; i++) {
width = baseWidth + i; // 用缓存值计算,不触发回流
...
}
利用「文档碎片(DocumentFragment)」批量添加 DOM
文档碎片是「虚拟 DOM 容器」,修改碎片内的元素不会触发页面回流,最后一次性添加到页面:
ini
// 创建文档碎片(离线容器)
const fragment = document.createDocumentFragment();
// 批量添加元素到碎片(无回流)
for (let i = 0; i < 100; i++) {
const li = document.createElement('li');
li.textContent = `Item ${i}`;
fragment.appendChild(li);
}
// 一次性添加到页面(仅1次回流)
document.getElementById('list').appendChild(fragment);
使用 CSS3 硬件加速,减少回流 / 重绘
给元素添加transform/opacity(现代浏览器)等属性时,浏览器会将元素放到「GPU 层」渲染,避免触发全局回流:
css
.box {
position: absolute;
top: 10px; /* 改top会触发回流 */
}
.box {
transform: translateY(10px); /* 硬件加速,无回流 */
}
核心区别:
- 回流是「布局重新计算」(耗性能),重绘是「外观重新渲染」(低消耗)
- 回流必触发重绘,重绘不触发回流;
水平垂直居中的方式有哪些?
position: absolute + transform: translate
- 传统方式,基于定位,这类方法兼容性最好,适用于所有现代浏览器和一些旧版浏览器。
- 这是最常用、最灵活的方法之一,不需要知道元素的具体宽高。
css
.parent {
position: relative;
width: 400px;
height: 300px;
border: 1px solid #ccc;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 150px; /* 子元素的宽高可以是固定的,也可以是自适应的 */
height: 100px;
background-color: lightblue;
}
position: absolute + 负 margin
- 一种经典方法,但是需要知道子元素的固定宽高
- 兼容性极佳,元素脱离文档流。
css
.child {
position: absolute;
top: 50%;
left: 50%;
width: 150px;
height: 100px;
margin-top: -50px; /* -height / 2 */
margin-left: -75px; /* -width / 2 */
background-color: lightcoral;
}
Flexbox 布局 (现代方法)
- 现代 css 布局的首选方案,简单直观
- 元素不脱离文档流,无需知道子元素宽高,还能处理更复杂的对齐和发布需求
css
.parent {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
width: 400px;
height: 300px;
border: 1px solid #ccc;
}
Grid 布局 (更现代的方法)
Grid 布局是二维布局系统,同样可以非常简单地实现居中。
- 元素不脱离文档流,代码更加简洁强大。
- 但兼容性没那么高,不支持 IE10 及以下版本。
css
.parent {
display: grid;
place-items: center; /* 水平垂直居中,是 align-items 和 justify-items 的简写 */
width: 400px;
height: 300px;
border: 1px solid #ccc;
}
.child {
width: 150px;
height: 100px;
background-color: lightsalmon;
}
其他
只作为拓展思路
- margin: auto;
- table: text-align + vertical-align