31 lines
2.0 KiB
Markdown
31 lines
2.0 KiB
Markdown
---
|
||
title: Streamlit st.html 注入全局 CSS 的坑:内容含 '<' 会被 DOMPurify 整段丢弃
|
||
type: experience
|
||
permalink: main/projects/8e229c96-a83b-4a02-ac40-10a0a9da444e/streamlit-st.html-注入全局-css-的坑内容含-会被-dompurify-整段丢弃
|
||
stable_id: 30702060-b113-4e9e-b1f0-2553e8b35046
|
||
scope: project
|
||
project_id: 8e229c96-a83b-4a02-ac40-10a0a9da444e
|
||
memory_type: experience
|
||
status: active
|
||
revision: 1
|
||
restored_from_commit: 6a6a895eafcca6052e81a14fca103a42635dd1c2
|
||
created_at: '2026-09-23T15:01:37.094752+00:00'
|
||
updated_at: '2026-09-23T15:01:37.094807+00:00'
|
||
tags:
|
||
- streamlit
|
||
- css
|
||
- st.html
|
||
- dompurify
|
||
- ui
|
||
---
|
||
|
||
问题:在 ui/layout.py 的 COMPACT_CSS 中加入内联 SVG data URL(含 `<svg ...>`)后,界面所有紧凑布局、隐藏 Enter 提示等全局样式同时失效;DOM 中 stEvent 容器的元素为空。
|
||
|
||
原因:Streamlit 1.64 的 `st.html` 对内容做 DOMPurify 清洗,纯 `<style>` 内容会送到 event 容器;样式文本里出现 `<` 会让整个 `<style>` 被清洗掉,而且不报错。
|
||
|
||
解决:CSS 里不写任何 `<`(图标改用 Streamlit 自带控件或 mask 以外的方式);`apply_compact_layout` 加了 `assert "<" not in COMPACT_CSS`,tests/test_toolbox.py 增加 `test_global_css_survives_streamlit_sanitizer` 守护。
|
||
|
||
附带结论:
|
||
- 隐藏所有输入框右下角 “Press Enter to submit form/apply” 提示:`[data-testid="InputInstructions"]{display:none !important}`,全局生效(app.py 在 st.navigation 前调用 apply_compact_layout)。
|
||
- 输入框内右侧 ✕ 清除按钮:`st.text_input(type="search")` 自带(stTextInputClearButton),不需要自定义 CSS;只需隐藏左侧放大镜 `[data-testid=stTextInputRootElement]:has(input[type=search]) [data-testid=stTextInputIcon]` 并把根元素 padding-left 置 0;placeholder 为空时会显示默认 “Search”,需显式传 placeholder。
|
||
- 排查手段:浏览器 CDP 查 `[data-testid=stEvent]` innerHTML 是否含样式文本、`.block-container` paddingTop(紧凑时≈13.6px,未生效为 96px)。 |