用几行css编写一个连续的格子状背景

195 阅读2分钟

开发过程中会碰到各种各样的ui样式,除了普通的长条状进度条,还有各种各样的进度条中,比如我就碰到了一个格子状的进度条,下面简单介绍一下(实际还有一个环形渐变进度条,下一篇在介绍😂)

如果让你编写下面连续的格子效果,你会怎么编呢

QQ_1727251889079.png

如下所示,我们通过 backgroundImage + linear-gradient 渐变 + 固定大小背景 + 重复铺满即可实现该效果(就没必要编写那么多的div了)

//只需要控制其长度就可以控制实际格子长度了,这里使用的是tailwindcss,不多解释了
 <div className="w-[458px] h-[23px] bg-[rgba(4,124,255,0.11)] flex items-center rounded-[5px]">
    <div
        className="h-[14px] w-[80%]"
        style={{
            //设置背景
            backgroundImage:
                "linear-gradient(90deg,transparent 50%, #20A6FF 0)",
            //设置大小这样才可以利用其大小填充不满的特性通过重复填充达成连续格子状视图了
            backgroundSize: "10px 14px",
            backgroundRepeat: "repeat",
        }}
    />
</div>

QQ_1727251693987.png

我们在配合css变量做一个初始动画

@keyframes gezi_perc_keyframes
{
    from {width: 0}
    to {width: var(--perc);}
}

const getPercStyles = (perc: number) => ({
    "--perc": `${perc}%`,
});

style={{
    ...getPercStyles(item.perc),
    width: `${item.perc}%`,
    animationName: "gezi_perc_keyframes",
    animationDuration: "1s",
    animationTimingFunction: "linear",
    transition: "width 1s",
}}

为了保证不最大的不占慢整个进度条(显得夸张一般会有一些留白),我们可以自己设置占用百分比不到100%即可,或者右侧设置一个间距,这个最大值还是按照100%,本案例按照右侧留白方式编写

实际实现如下所示

...jsx
const GeziPercView = (props: {
    title: string,
    info: any[] //实际是name、value也可以自己调整
}) => {
    let max = 0;

    info.forEach((item) => {
        if (item.value > max) {
            max = item.value;
        }
    });
    info.forEach((item) => {
        item.perc = (item.value / max) * 100;
        if (item.perc < 0.1) item.perc = 0.1;
    });

    const getPercStyles = (perc: number) => ({
        "--ydqdperc": `${perc}%`,
    });

    return (
        <div className="h-[430px] w-full">
            <CardTitle title={props.title} />
            <div className="flex flex-col">
                {props.info.map((item, index) => (
                    <div
                        key={index}
                        className={`flex items-center ${
                            index < 1 ? "mt-[36px]" : "mt-[18px]"
                        }`}
                    >
                        <span className="text-[14px] font-thin w-[108px] text-right mr-[20px]">
                            {item.name}
                        </span>
                        <div className="w-[458px] h-[24px] bg-[rgba(4,124,255,0.11)] flex items-center rounded-[5px]">
                            <div
                                className="h-[14px] ml-2 mr-8"
                                style={{
                                    ...getPercStyles(item.perc),
                                    width: `${item.perc}%`,
                                    backgroundImage:
                                        "linear-gradient(90deg, #20A6FF 50%, transparent 0)",
                                    backgroundSize: "10px 100%",
                                    backgroundRepeat: "repeat",
                                    animationName: "gezi_perc_keyframes",
                                    animationDuration: "1s",
                                    animationTimingFunction: "linear",
                                    transition: "width 1s",
                                }}
                            />
                        </div>
                        <span className="text-[14px] font-thin ml-[14px] hover:scale-[150%]">
                            {item.value}
                        </span>
                    </div>
                ))}
            </div>
        </div>
    );
};

...css
@keyframes gezi_perc_keyframes
{
    from {width: 0}
    to {width: var(--ydqdperc);}
}