You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过CSS ::before与ID选择器调用多图标SVG文件中的单个图标

问题:CSS伪元素调用SVG图标集中的单个图标失败

核心场景

  • 使用第三方库,仅支持设置纯文本作为标签,需在文本前添加SVG图标集中的单个图标
  • 项目基于Vue 3 + Vite开发

尝试与疑问

  • 尝试通过::before伪元素结合url()调用SVG,但选择器未生效,反而显示所有图标
  • 疑问:CSS的url()能否通过ID选择SVG中的单个图标?是写法错误还是SVG文件结构问题?

代码详情

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Add an icon via ::before</title>
    <link rel="stylesheet" href="lib/lib.css">
    <link rel="stylesheet" href="lib/style.css">
</head>
<body>
<div class="container">
    <div class="lib_label_col">
        <div class="label_row row_folder" style="top:0px;height:90px;line-height:89px;"
                data-row-index="0" data-row-id="1">
            <div class="scell folder opened" style="width:305px; height:48px;">
                <div class="scell_level0">
                    <div class="scell_expand"></div>
                    <div class="scell_name">Label 1</div>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
</html>

lib/icons.svg

<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg">
    <svg id="chevron-down" height="24" width="24" viewBox="0 0 24 24" fill="none">
<!--        <rect width="24" height="24" fill="white"/>-->
        <path d="M17 9.5L12 14.5L7 9.5" stroke="#000000" stroke-linecap="round" stroke-linejoin="round"/>
    </svg>
    <svg id="chevron-right" height="24" width="24" viewBox="0 0 24 24" fill="none">
<!--        <rect width="24" height="24" fill="white"/>-->
        <path d="M9.5 7L14.5 12L9.5 17" stroke="#000000" stroke-linecap="round" stroke-linejoin="round"/>
    </svg>
    <svg id="invalid" height="24" width="24" viewBox="0 0 24 24" fill="none">
<!--        <rect width="24" height="24" fill="white"/>-->
        <path d="M17 9.5L12 14.5L7 9.5" stroke="#000000" stroke-linecap="round" stroke-linejoin="round"/>
    </svg>
</svg>

lib/lib.css

.scell {
    overflow: hidden;
    text-align: center;
    vertical-align: middle;
    border-bottom: 1px solid rgba(0, 0, 255, 0.5);
    border-right: 1px solid rgba(0, 0, 255, 0.5);
}

.lib_data .lib_wrapper div {
    box-sizing: border-box;
}

.scell .scell_level0 {
    padding-left: 5px;
    padding-top: 16px;
    color: grey;
}

.scell.folder .scell_expand {
    float: left;
    width: auto;
}

.scell.folder .scell_name {
    float: left;
    width: 237px;
    color: grey;
    font-size: 14px;
    font: normal normal 600 14px/18px "Open Sans", sans-serif;;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: left;
}

.scell.folder .scell_expand {
    margin: -4px 4px
}

.scell.folder {
    border-right: 1px solid transparent;
}

.row_folder .scell {
    border-right-color: grey;
    border-bottom-color: grey;
}

lib/style.css

.container {
    height: 100vh;
    width: 100vw;
}

.lib_container, .lib_data {
    width: 100%;
    height: 100%;
}

.scell {
    display: flex;
    flex-direction: row;
}

.scell::before {
    height: 24px;
    margin: 0 auto;
    max-height: 24px;
    max-width: 24px;
    min-height: 24px;
    min-width: 24px;
    padding-top: 12px;
    width: 24px;
}

.opened::before {
    content: url('icons.svg#chevron-down');
}

.closed::before {
    content: url('icons.svg#chevron-right');
}

.invalid::before {
    content: url('icons.svg#invalid');
}

.scell:not(.invalid):not(.opened):not(.closed)::before {
    content: "";
}

解决方案

1. 修正SVG文件结构

原SVG采用嵌套<svg>标签的方式,无法通过#ID精准定位单个图标,需改为符号(symbol)+ use的标准图标集格式:

修改后的icons.svg:

<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" style="display:none;">
    <symbol id="chevron-down" viewBox="0 0 24 24" fill="none">
        <path d="M17 9.5L12 14.5L7 9.5" stroke="#000000" stroke-linecap="round" stroke-linejoin="round"/>
    </symbol>
    <symbol id="chevron-right" viewBox="0 0 24 24" fill="none">
        <path d="M9.5 7L14.5 12L9.5 17" stroke="#000000" stroke-linecap="round" stroke-linejoin="round"/>
    </symbol>
    <symbol id="invalid" viewBox="0 0 24 24" fill="none">
        <path d="M17 9.5L12 14.5L7 9.5" stroke="#000000" stroke-linecap="round" stroke-linejoin="round"/>
    </symbol>
</svg>
  • 外层<svg>添加display:none隐藏整体,避免渲染冗余内容
  • 每个图标用<symbol>包裹,保留原ID和viewBox属性

2. 调整CSS调用方式

url()无法直接通过ID引用symbol,推荐使用background-image结合SVG的use语法实现:

修改style.css中的伪元素样式:

.opened::before {
    content: "";
    background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><use href="icons.svg#chevron-down"/></svg>');
    background-size: 24px 24px;
    background-repeat: no-repeat;
}

.closed::before {
    content: "";
    background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><use href="icons.svg#chevron-right"/></svg>');
    background-size: 24px 24px;
    background-repeat: no-repeat;
}

.invalid::before {
    content: "";
    background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><use href="icons.svg#invalid"/></svg>');
    background-size: 24px 24px;
    background-repeat: no-repeat;
}

3. Vue3 + Vite环境优化

在Vue3项目中,可借助vite-svg-loader插件简化SVG图标管理:

  1. 安装插件:
npm install vite-svg-loader --save-dev
  1. 在vite.config.js中配置:
import svgLoader from 'vite-svg-loader'

export default {
  plugins: [svgLoader()]
}
  1. 可直接将单个SVG图标作为组件导入,或通过插件生成的资源路径,结合CSS伪元素实现图标插入,适配第三方库的文本标签场景。

关键原因说明

  • 原SVG嵌套结构不符合图标集标准,浏览器无法通过#ID定位内部<svg>标签,会加载整个文件并显示所有内容
  • <symbol>+<use>是SVG图标集的标准写法,支持浏览器精准定位单个图标,且可通过CSS复用

内容的提问来源于stack exchange,提问作者sth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 04:08:11