分析css问题并快速定位样式来源

440 阅读3分钟

最近刚入职,几乎每天都在修复别人的bug,今天终于收尾了。所以有空来记录一下其中的一个小问题,当然,最重要的还是解决问题的过程和方法逻辑。

ant design vue中可以通过修改less通用变量来定制主题,但是很多大型ui框架的变量会被多个组件引用,这就导致当修改其中一个基础变量时,部分依赖该变量的组件会样式出错。本篇文章就是记录从问题发现到解决的全过程。

1. 问题描述:

PopConfirm气泡确认框内的按钮文字没有垂直居中:

image.png

2. 问题分析:

如果是直接修复bug很简单,直接随便调整一下样式让它垂直居中就好了,甚至让它“看上去”垂直居中也行。但还是想搞清楚,这个bug为什么会出现。

首先,审查元素发现是一个固定高度24px<button></button>包裹了一个超出其高度<span>确 定\</span>

image.png

<span>确 定\</span>的高度由内部的字体大小行高决定:

image.png

字体大小 * 行高 font-size: 16px;line-height: 1.5715;相乘得出span高度是25.144px,所以高度span超出,又因为文字在span里垂直居中,所以文字button上没有垂直居中。

3. 原因排查

下面就找产生问题的几个样式,哪个是罪魁祸首。

.ant-btn-sm { height: 24px; font-size: 16px; }
.ant-btn { line-height: 1.5715; }

3.1 首先,与ant design vue官网的PopConfirm样式作对比发现,官网的.ant-btn-sm14px

image.png

所以问题基本就在font-size: 16px;上。那么这个样式从哪里来?

3.2 下面常规步骤就是整个项目检索font-size: 16px;,但挨个检查都不是`.ant-btn-sm的样式:

image.png

这里应该可以用正则匹配跨行文本,缩检查范围,等我知道了回来补上。

3.3 通过devtool的元素面板的样式部分,点击定位编译后的样式文件:

image.png

全选复制到txt中:

image.png

这个文件怎么看都是组件自己的样式文件。所以猜测是否在编译阶段动态的更改了组件样式

3.4 查看vite.config.ts文件,发现确实自定义了一个东西为16px

// vite.config.ts
import { defineConfig } from 'vite'

export default defineConfig({
  css: {
    preprocessorOptions: {
      less: {
        modifyVars: {
          // ...
          'font-size-base': '16px', // 主字号
          // ...
        },
        javascriptEnabled: true
      }
    }
  }
})

4. 原理探究

找到vite中css.preprocessorOptions说明:

image.png

这个选项是传选项给各个css预处理器的入口,点击查看less的选项,搜索modifyVars

image.png

意思就是它能在运行时修改less的变量。

而这个配置的目的显然也是对ant design vue的定制化配置,没什么大问题。但是为什么font-size-base的变量会影响到.ant-btn-sm的字体大小呢?查看组件样式源码:

// style/themes/default.less
@btn-font-size-sm: @font-size-base;
image.png

5. 问题解决

在vite.config.ts中手动恢复14px的字体大小:

// vite.config.ts
import { defineConfig } from 'vite'

export default defineConfig({
  css: {
    preprocessorOptions: {
      less: {
        modifyVars: {
          // ...
          'font-size-base': '16px', // 主字号
          'btn-font-size-sm': '14px', // 因为@btn-font-size-sm: @font-size-base; 这里恢复14px大小
          // ...
        },
        javascriptEnabled: true
      }
    }
  }
})