blog icon indicating copy to clipboard operation
blog copied to clipboard

css var 背景图片处理

Open huangshuwei opened this issue 3 years ago • 0 comments

前言

我们在做主题切换时希望统一通过 css var 处理。假设我们希望做白色和黑色两种主题,背景图的切换理想情况我们希望通过以下方式实现。

首先定义2套 css var 样式

// theme-vars.less

.theme-white{
   --bg-img:url('./bg-img-white.png');
}

.theme-black{
   --bg-img:url('./bg-img-black.png');
}

组件中我们希望这样使用:

.your-comp{
  background: var(--bg-img) top no-repeat;
}

问题

通过测试发现,iOS 14 以下的系统只支持 base64格式的css 变量,也就是如果图片过大没有生成base64格式,这段代码不会生效: background: var(--bg-img) top no-repeat;

解决方案1

修改图片生成base64 的规则,在vue-cli3 中,默认10kb 以下的图片才会生成base64格式,我们可以将这个规则改写,比如改为100kb:

// vue.config.js

module.exports = {
    chainWebpack: config => {
        // 设置打包图片转换成base64 大小限制(100kb 内为base64)
        config.module
            .rule("images")
            .use("url-loader")
            .loader("url-loader")
            .tap(options => Object.assign(options, { limit: 1000 * 100 }));
    }
};

如果项目中图片大小都小于100kb 那么我们的目的就达到了。但是打包后你会发现,你的js 文件已经增大了很多,图片越大base64 字符串就越长,占用的空间越大。这可能也是为什么默认小于10kb 的图片才会生成base64 的原因。所以使用这种方案你要权衡项目中图片是否过多,最简单的方式就是打包之后比较输出文件大小。

解决方案2

你也可以像图片切换那样,使用js 实现。这种方式简单粗暴,但是没有使用css var,维护麻烦点。以 vue 代码为例

<template>
    <div
        :style="{
            'background-image': 'url(' + bgImage + ')'
        }"
    >
        other content
    </div>
</template>

<script>
export default {
    props: {
        theme: {
            type: String,
            default: "white"
        }
    },
    data() {
        return {
            bgImage: ""
        };
    },

    mounted() {
        if (this.theme === "black") {
            this.bgImage = require("../../../img/bg-black.png");
        } else {
            this.bgImage = require("../../../img/bg.png");
        }
    }
};
</script>
<style lang="less" scoped></style>

--完--

huangshuwei avatar Jul 23 '21 02:07 huangshuwei