如何通过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图标管理:
- 安装插件:
npm install vite-svg-loader --save-dev
- 在
vite.config.js中配置:
import svgLoader from 'vite-svg-loader' export default { plugins: [svgLoader()] }
- 可直接将单个SVG图标作为组件导入,或通过插件生成的资源路径,结合CSS伪元素实现图标插入,适配第三方库的文本标签场景。
关键原因说明
- 原SVG嵌套结构不符合图标集标准,浏览器无法通过
#ID定位内部<svg>标签,会加载整个文件并显示所有内容 <symbol>+<use>是SVG图标集的标准写法,支持浏览器精准定位单个图标,且可通过CSS复用
内容的提问来源于stack exchange,提问作者sth
相关产品推荐
相关产品推荐

