通过JS动态控制CSS规则的可行方案(内联style里的css变量var)

254 阅读2分钟

最近遇到一个需求,翻译成前端语言就是:控制ElMesssge消息弹窗在页面中的位置,不希望它只是简单的固定定位到整个视口中间,而是定位到左右布局的右边的main区域中间,因为左边是菜单栏,这样看起来更和谐;目前的消息框会受鼠标hover的影响,如果鼠标在上面,它就一直不会关闭,希望调整为不受鼠标的影响,该什么时候关闭就什么时候关闭。

image.png 拿到需求后,做出以下分析:

  1. 不受鼠标影响很简单,直接给el-message的point-events属性设为none就行,因为是继承属性,因此为其下的el-icon单独设为auto,这样虽然在hover关闭icon时,弹窗关闭也会受影响,但无伤大雅
  2. 消息出现在main区域中间,直接通过css修改ElMessage的样式即可,将它的left值改为50%+菜单栏宽度,或right值为main宽度的50%
  3. 但事情没那么简单,菜单栏的宽度是可被用户手动调整的,因此如果要准确控制,必须得有办法通过JS修改CSS规则
  4. 因为当时没想到可行的办法,就放弃了这个方案,转而封装ElMessage,使其appendTo属性是main元素,将position改为absolute,同时手动调用close方法手动关闭弹窗。这个方法的代价就是,需要用这个封装的方法替代项目中所有的ElMessage,几百个文件都要改,不过得益于ide强大的搜索功能,替换的也很快,功能也实现了
  5. 几天后,我发现项目的html标签的style属性上挂了很多--开头的css变量,它们都是被用来网站换肤的颜色变量,这才恍然大悟,我可以通过这种方式实现js对css规则的控制,这样这个需求就可以这样做:为el-message的left属性单独声明一个css变量,在菜单栏挂载和宽度被调整时,通过修改html的style来设置它的值,如果有些页面布局不一样,比如没有菜单栏,就需要在菜单栏被卸载时或该页面挂载时,重置该变量为50%或需要的值
.el-message {
  pointer-events: none;
  left: var(--main-message-left, 50%) !important;
  .el-icon {
    pointer-events: auto;
  }
}
const sideBarWidth=sideBarEl.offsetWidth
document.documentElement.style.setProperty(
    '--main-message-left',
    `calc(${sideBarWidth.value}px + 50%)`
  );

image.png 总结:虽然是个小功能,却涉及到两种方案的权衡,因为已经更改了几百个文件,再改回来也比较麻烦,而且我也被分到新的项目,所以目前还是使用的原来的那个方案,如果后面有其他人维护到我写的代码,希望可以get我的想法,在此基础上修改也是ok的。