Skip to content

HTML

如何理解 HTML 语义化标签

HTML 的语义化标签是指使用带有明确含义的标签来描述网页内容的结构和含义,例如使用 <header> 标签表示头部、<footer> 表示底部、<nav> 表示导航菜单等。主要有以下几个优点:

  1. SEO 优化: 搜索引擎能够更好地理解网页内容,哪些部分是重要的,从而提高网页的搜索引擎排名。
  2. 可读性: 语义化标签能够让代码的结构更加清晰易懂,开发者可以更快地理解和维护代码。
  3. 可访问性:屏幕阅读器能够更好地解析和阅读网页内容,提升无障碍访问体验。

CSS

引入 CSS 的三种方式

  1. 内联样式: 直接在标签内部使用 style 属性设置样式。
  2. 内部样式表: 使用 <style> 标签在 HTML 文件的 <head> 标签内部定义样式。
  3. 外部样式表: <link ref="stylesheet" href="xxx"> 引入外部的 CSS 文件。

物理像素与逻辑像素

  1. 物理像素:物理像素是在设备制造过程中固定下来的像素,也被称为“设备像素”,通常用 dp 表示。我们经常提到的屏幕分辨率,如 1920*1080,就是指的物理像素,它反映的是显示器上的像素点数量。
  2. 逻辑像素:逻辑像素通常用来描述图像尺寸,这是一种可以动态变化的像素,一般用dip表示。例如一张 300*300 像素大小的图片,在正常情况下,它的尺寸为 300*300 个逻辑像素,但是当我们将其放大 2 倍时,它的尺寸就变为了 600*600 个逻辑像素。

物理像素与逻辑像素的比值称之为设备像素比,通常用dpr表示,当我们缩放浏览器时,实际上就是在改变设备像素比。在一般的电脑上,设备像素是等于逻辑像素的,也就是 dpr = 1.0 ,但是在高分辨率的电脑上,二者不一定相等,例如,在一台 2k 分辨率的电脑上,dpr 可能为 1.5,意味着 1 个逻辑像素对应 1.5 个物理像素。这样做是为了保证图片在高分辨率屏幕上的清晰度,因为如果不进行缩放,图片在高分辨率屏幕上的尺寸会显得过小。

我们可以通过 window.devicePixelRatio 属性来查看当前设备的 dpr 值;也可以通过 meta 标签的 initial-scale 来调整 dpr 值(其实就相当于缩放浏览器)。

这一部分的知识有时候会用来解决不同设备上的 1px 边框问题,例如在 dpr 为 2 的设备上,1px 的边框实际上是 2px,我们可以通过媒体查询结合scale来解决这个问题。

css
@media (-webkit-min-device-pixel-ratio: 2) {
  .border-1px::after {
    transform: scale(0.5);
  }
}

CSS 选择器优先级

!important > 内联样式 > ID > 类 > 标签 > 通配符 > 继承 > 浏览器默认样式

权重相同时,后面的样式会覆盖前面的样式,这就是 CSS 的层叠性。

伪类与伪元素

  • 伪类:单冒号开头, 用于为元素的特定状态设置样式. 如:hover:active:focus等。
  • 伪元素:双冒号开头, 用于创建一些不在文档树中的元素,并为其设置样式。如::before::after...

定位 - position

  • static: 默认值, 即标准的文档定位.
  • relative: 相对定位,相对于自身原来的位置进行定位,不会脱离文档流,不会影响其他元素的位置。
  • absolute: 绝对定位,相对于最近的static定位的祖先元素进行定位(没有则相对于视窗),脱离文档流,会影响其他元素的位置。
  • fixed: 固定定位,相对于视窗进行定位,脱离文档流,会影响其他元素的位置。
  • sticky: 粘性定位,相对于最近的滚动祖先元素和视窗进行定位,脱离文档流,会影响其他元素的位置。

盒模型 - box-sizing

  • content-box: 默认值,宽度和高度只包括内容,不包括 border 与 padding
  • border-box: 怪异盒模型

回流与重绘

  • 重绘: 当元素的样式发生改变,但不影响布局时,浏览器将使用重绘对元素进行更新,例如改变 colorbackground-colorvisibility 等属性。
  • 回流: 当元素的几何尺寸、位置或者某些属性发生改变时,浏览器会重新渲染页面,称为回流。例如改变 widthheightpaddingmargindisplayborder-width 等属性。
  • 回流一定会引起重绘,重绘不一定会引起回流。

隐藏元素的方法

  • display: none: 隐藏元素,不占据空间,不能触发事件,会导致回流。
  • visibility: hidden: 隐藏元素,占据空间,不能触发事件,导致重绘。
  • opacity: 0: 隐藏元素,占据空间,可以触发事件,不导致回流重绘,而是触发 CSS3 硬件加速。
  • 通过定位将元素移出视窗之外。

CSS3 硬件加速通过将特定的 CSS 属性应用于元素,例如transformopacityfilter等,浏览器会将这些元素的渲染和动画操作交给 GPU 来处理,从而提高性能和流畅度。

BFC

BFC 中文是块级格式化上下文, 是块级盒子布局发生的区域, 也是浮动元素与其他元素交互的区域. BFC 通常用来包含内部浮动元素,防止父元素高度塌陷, 也可以用来避免垂直外边距重叠

创建 BFC 的方式有很多, 例如: 浮动元素、绝对定位元素、行内块元素、overflow 不为 visible 的元素等。

flex:1 是什么的缩写

  • flexflex-growflex-shrinkflex-basis 的缩写,分别表示元素的放大比例、缩小比例、初始尺寸。
  • flex: 1 等价于 flex: 1 1 0,表示元素放大/缩小时的比例为 1,初始尺寸为 0。

元素水平垂直居中的方法

水平居中:

  • 行内元素: text-align: center
  • 块级元素:
    • 外边距 margin: 0 auto
    • flex 布局 justify-content: center
    • 绝对定位 left: 50%; transform: translateX(-50%)

垂直居中:

  • 行内元素:设置line-height等于height
  • 块级元素:
    • flex 布局 align-items: center
    • 绝对定位 top: 50%; transform: translateY(-50%)

CSS 预处理器的作用

预处理器支持我们编写一种类似 CSS 但实际并不是 CSS 的语言,例如 SCSS、LESS 等,它们在原有的 CSS 基础上提供了一些更加便利的功能,例如我们可以使用嵌套的方式编写样式、定义变量参与计算、允许一个选择器集成另一个选择器的样式等等。

预处理器与原生 CSS 中变量的区别

预处理器的变量是在编译阶段就被解析为实际的值,无法在运行时改变,而原生 CSS 的变量是在运行时解析的,可以根据上下文动态改变。(因此我们可以借助原生的 CSS 变量实现明亮与暗黑模式的切换)

CSS 后处理器的作用

最常见的 CSS 后处理器就是 PostCSS,预处理器处理的是类似 CSS 的语言,而后处理器处理的是 CSS 本身,它可以帮助我们对 CSS 进行更多的操作,例如当我们需要适配低版本的浏览器是,可以使用 autoprefixer 这个插件自动添加浏览器前缀,还可以对 CSS 进行压缩、优化等操作。

  • @import 导入的 CSS 文件是串行加载的,不能并行加载多个 CSS 文件,而 link 标签可以并行加载多个 CSS 文件。
  • @import 导入的 CSS 文件会等到包含它的 CSS 文件加载完毕后再加载,会导致页面的加载速度变慢。
  • 需要注意的是,此处特指原生@import,如果我们使用 CSS 预处理器,实际上并不会存在上述问题。

CSS 模块化有哪些解决方案?

CSS 的模块化是指将 CSS 代码拆分成更小、更具独立性的模块,以便更好地管理、维护和复用样式。CSS 模块化最主要的是解决多个样式文件之间的命名冲突问题,常见的解决方案有:

  • 对于 Vue 来说,可以使用 scoped 属性来实现样式的模块化,它会给每个组件的样式添加一个唯一的 data-v-xxxx 属性,从而避免样式冲突。
  • CSS Modules:在 Vite 项目中,可以以 xxx.module.css 的形式去定义一个 CSS Module 文件,并且通过下面的方式去导入与使用:
js
import classes from './example.module.css'
document.getElementById('foo').className = classes.red
  • TailwindCSS: 提供了大量原子化的 CSS 类,其核心思想是通过组合这些小的实用类去构建复杂的组件,从而避免命名冲突的问题。
  • BEM: 这是一种命名约定,用于创建可重用的组件并使代码更具可读性。BEM 的命名规则如下
  • CSS in Js: CSS in JS 是一种将 CSS 样式直接写在 JavaScript 中的解决方案,常见的库有 Styled Components 和 Emotion。它们允许你在 JavaScript 中定义样式,并将样式与组件紧密结合:

场景题

文本溢出

单行文本溢出

css
.text-overflow {
  white-space: nowrap; /* 强制单行显示 */
  overflow: hidden; /* 溢出部分隐藏 */
  text-overflow: ellipsis; /* 溢出部分显示省略号 */
}

多行文本溢出

css
.line-clamp-2 {
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2; /* 显示的行数 */
  -webkit-box-orient: vertical;
}

三角形

正方形

【0.5px】问题

现在,可爱的美工妹子【哆啦】觉得 1px 的边框还是太粗了,她想要你实现 0.5px 的边框,你可以做到吗?

解题要点: transformtransform-origin伪元素

问题分析:

我们知道 CSS 的最小尺寸为 1px,想要实现 0.5px 的边框,显然不能通过直接设置尺寸来实现,我们需要借助一点其他的工具———transformscale函数.

但需要注意的是,transform 的对象是整个盒子,无法指定某个特定的属性去放缩。当我们对某个 div 盒子使用 scale 放缩的时候,无论是边框还是内容大小都会发生改变。例如本例中当我们试图通过 scale(0.5) 去获得 0.5px 的边框时,盒子内容大小(长宽、字体大小等属性)也会变为原来的一半。

这时我们可以考虑使用伪元素,将伪元素的长宽设为原来的 200%(因为后面缩小为了 50%),并设置 border 为 1px 以及, 随后再对伪元素进行transform操作,这样就不会影响到原来的内容了。

至此我们已经能得到 0.5px 的边框了,但是它的位置与预期效果还存在较大差距。

  1. 我们需要利用定位的方式将其覆盖在原来的内容上。

  2. 我们还需要随后呢还需要调整 transform-origin 的取值,具体取值其实与定位的设置有关.

这里给出我的参考代码

html
<div class="box thin-border">0.5px边框</div>

<style>
    .box{
        width: 200px;
        height: 200px;
        line-height: 200px;
        text-align: center;
    }
    .thin-border{
        position: relative;
    }
    .thin-border::after{
        position: absolute;
        left: 0;
        top: 0;
        content: "";
        border: 1px solid red;
        width: 200%;
        height: 200%;
        transform: scale(0.5);
        transform-origin: top left;
    }
</style>