面试官:问几个简单的CSS吧

如何实现一个三角形?

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

实现方法 原理:元素的border是由三角形组合而成

  • 宽高设为 0:把元素的宽度和高度都设成 0,这样元素本身就不会占据空间。
  • 利用边框:通过设置不同方向的边框,让它们相互叠加,从而形成三角形。
  • 控制边框颜色:将左右边框的颜色设为透明,底部边框设置成你想要的颜色,这样就呈现出一个朝上的三角形。

改变三角形的方向:

  • 朝上的三角形:左右边框透明,底部边框设置颜色。
  • 朝下的三角形:左右边框透明,顶部边框设置颜色。
  • 朝左的三角形:上下边框透明,右边框设置颜色。
  • 朝右的三角形:上下边框透明,左边框设置颜色。

下面是一个朝下三角形的示例: .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 体验AI代码助手 代码解读复制代码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。

image.png

flex:1

忽略自身元素内容大小,强制按比例均分空间 如下所示,即使文本长度不一样,每个子元素的宽度依旧相等

flex: auto

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

应用场景 需要 “等分空间”—— 用 flex:1

  • 如卡片等分显示,多个导航栏均等显示

需要“优先保证内容显示”—— 用 flex:auto

  • 搜索框布局,需要优先保证输入框可输入宽度

Float 为什么要清除浮动?以及如何清除? 最开始的作用:图文环绕 要实现这样的效果,决定了 float 的两个特性:

“破坏文档流”,使得父元素得高度塌陷。 禁止行框盒子与浮动元素发生重叠

一:为什么要清除浮动? 当子元素设置了float: left/right后,脱离文档流会引发以下问题:

    • 父容器高度塌陷:父元素的高度默认由子元素撑开,但浮动元素 “飘” 起来后,父元素会认为内部没有可撑开高度的内容,高度变为 0。
    • 布局混乱:页面下方的元素会 “钻” 到浮动元素下方,导致排版错位、重叠等问题。
    • 背景和边框显示异常:父容器的背景和边框无法正常包裹浮动元素。

如以下布局: `

浮动元素
`

二:如何清除浮动?(按推荐度排序) 以下是常见的清除浮动方法: clearfix 伪元素法(最佳实践 / 主流方案) 通过 CSS 为父容器添加伪元素,自动清除浮动。

原理:clear: both 表示元素的左右两侧都不允许有浮动元素; 不增加冗余 HTML 标签,兼容性好(支持所有主流浏览器) 可封装成通用类

.clearfix::after { content: ""; display: block; clear: both; /* 核心:清除左右浮动 */ visibility: hidden; /* 隐藏伪元素 */ height: 0; /* 避免占用额外空间 */ }

BFC(块级格式化上下文) 为父容器设置overflow: auto/hidden,使其创建 BFC

原理:BFC 会包裹内部的浮动元素,自动计算父元素高度。 缺点:如果子元素有超出父元素的内容(如下拉菜单、弹出层),会被 overflow: hidden 裁剪掉,适合简单布局。

使用 flexbox 或 Grid 布局

原理:现代布局方式会自动包含子元素,无需清除浮动。 缺点:兼容性没上面的高

额外标签法(不推荐,冗余标签) 在所有浮动子元素的末尾,添加一个空的块级标签(如

),并设置 clear: both。

原理:直接在浮动元素后插入一个清除浮动的元素,强制父元素识别高度; 缺点:增加无意义的 HTML 冗余标签

如何实现 0.5px 边框? 在标准 css 中,通常无法直接设置 0.5px 的边框宽度,因为 css 像素的浏览器的最小渲染单位,而不支持亚像素级的渲染。但是可以通过一些技巧来模拟实现。 伪元素 可以使用伪元素 ::before 或 ::after 来创建一个额外的边框层,并设置高度为 0.5px。 `.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 属性来模拟一个细边框的效果 .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 (根相对单位)

参考基准:根元素(即 标签)的字体大小。 计算规则:如果 的 font-size 为 16px,则 1rem = 16px,2rem = 32px。 特点:全局统一,不受父元素字体大小影响,避免嵌套层级过深导致的尺寸失控。

浏览器的默认字体尺寸为 16px,所以有以下设置 html { font-size: 62.%; /* 公式16px*62.5%=10px */ }

什么是 BFC? BFC (块级格式化上下文):

简单来说,BFC是一个完全独立的空间(布局环境),让空间里的子元素不会影响到外面的布局

当浮动时,会导致高度塌陷问题,如下图所示:

黄色框向左浮动,使它脱离了原本的位置,由此绿色框被定位到灰色父元素,并与浮动元素重叠。 由于父元素灰色框没有创建 BFC,由此计算高度时不会考虑灰色框的区域,也就是常见的 高度坍塌 问题

// 灰色框
// 黄色框,向左浮动
// 绿色框

如何创建 BFC

  • 根元素或其他包含它的元素
  • 浮动:float: 不为 none
  • 绝对定位元素:position: absolute / fixed
  • 行内块级元素:display: inline-block
  • 表格单元格:display: table-cell
  • overflow 的值 不为 visible 的元素
  • 弹性盒子:display: flex / inline-flex

BFC 的应用和效果 应用一:防止高度坍塌 给灰色框创建一个新的 BFC 后,高度计算时会包括浮动元素(灰色框高度变化) `.BFC { overflow: hiddle; }

`

应用二:阻止与浮动元素重叠

如下例:由于绿色框没有创建 BFC,其中的白色块受到黄色框(浮动元素)的影响,被挤到右边的同时超出了绿色框的范围。

` .little{ background: #fff; width: 50px; height: 50px; margin: 10px; float: left; }

`

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

`

...

`

应用三:阻止 margin 合并 阻止相邻元素的 margin 合并 给两个框分别添加 margin,由图可知相邻的 margin 会被合并 `

// margin: 20px;
// margin: 20px;

`

给其中一个元素(也可以两个元素)设置 BFC,可以阻止 margin 的合并 注意:块级元素会默认铺满一行

<div className="box BFC"> <div className="BFC"> <div className="left" /> </div> <div className="right" />

``

应用四:自适应两栏布局

利用 BFC 不会与浮动元素重叠的特性,同时由于块级元素默认铺满整行,就可以实现两栏自适应布局

`

// 保持左浮动
// 删除 width

`

什么是盒模型?

可以认为每个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选择元素的前面插入内容。

选择器优先级和权重列表

image.png

注意点:

  • CSS 选择器的特殊性(Specificity,权重) 遵循位权计算规则,存在层级壁垒,低层级选择器的数量无论堆叠多少,都永远无法跨越层级超过高层级选择器,这是和普通「数字加法」最本质的区别。
  • 高位权重只要有值,低位权重堆到无穷大也无法超越。
  • 同权重时,「后声明」覆盖「先声明」
  • 继承的样式权重为 0, 会被子元素自身的任意选择器覆盖

重绘与回流的区别? 重绘(Repaint)和回流(Reflow)是与浏览器渲染引擎相关的概念,它们可以影响网页的性能。 回流 先画「骨架」—— 确定每个元素的位置、大小、间距(比如盒子的宽高、top/left、margin); 如果骨架变了(如盒子宽度变化),就需要重新计算所有相关元素的位置和尺寸,这个过程就是回流。 常见操作:(只要改变元素的几何属性,就会触发回流)

  • 修改元素尺寸、位置、字体、文本
  • 增减 / 修改 DOM 节点
  • 修改浏览器窗口
  • 读取某些布局属性:offsetWidth/offsetHeight/clientWidth/getComputedStyle()(浏览器为了获取准确值,会强制触发回流)。
  • 使用 JavaScript 计算样式或布局。

重绘 骨架不变,只改「外观」—— 比如改颜色、背景、阴影、透明度。 只需要在原有骨架上重新上色,不用动结构,这个过程就是重绘。 常见操作:只改视觉样式,不碰布局,仅触发重绘

修改颜色、阴影、透明度、背景图、光标等

性能优化:减少不必要的回流/重绘 批量修改,减少多次回流

合并样式修改

`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');`

  1. 先「离线」修改 DOM,再「上线」 把元素从 DOM 树中移除,修改完成后再加回去(仅触发 2 次回流:移除 + 添加) 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 体验AI代码助手 代码解读复制代码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 体验AI代码助手 代码解读复制代码// 创建文档碎片(离线容器) 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 层」渲染,避免触发全局回流: `.box { position: absolute; top: 10px; /* 改top会触发回流 */ }

.box { transform: translateY(10px); /* 硬件加速,无回流 */ }`

核心区别:

回流是「布局重新计算」(耗性能),重绘是「外观重新渲染」(低消耗) 回流必触发重绘,重绘不触发回流;

水平垂直居中的方式有哪些? position: absolute + transform: translate

传统方式,基于定位,这类方法兼容性最好,适用于所有现代浏览器和一些旧版浏览器。 这是最常用、最灵活的方法之一,不需要知道元素的具体宽高。

`.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

一种经典方法,但是需要知道子元素的固定宽高 兼容性极佳,元素脱离文档流。

.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 布局的首选方案,简单直观 元素不脱离文档流,无需知道子元素宽高,还能处理更复杂的对齐和发布需求

.parent { display: flex; justify-content: center; /* 水平居中 */ align-items: center; /* 垂直居中 */ width: 400px; height: 300px; border: 1px solid #ccc; }

Grid 布局 (更现代的方法) Grid 布局是二维布局系统,同样可以非常简单地实现居中。

元素不脱离文档流,代码更加简洁强大。 但兼容性没那么高,不支持 IE10 及以下版本。

`.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

——转载自:Sport

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
科叼
下载 APP