BWiki CSS 编写与调试指南
1. 方法选择策略
决策流程图
根据使用场景选择最合适的 CSS 实现方式:
- 小块安全样式 / 快速验证(需要即时生效)→ 使用
#css(内联方式,绕过 URL 缓存) - 需要高级功能(
url()/var()/filter()/calc())→ 使用<bstyle>(内联方式,支持完整语法) - 一次性微调 → 临时使用
style="..."(后续迁移到 1 或 2) - 多页面复用结构组件 → 使用 Widget(配合哨兵变量防止重复)
- 稳定全站规范 → 使用 Common.css / 皮肤 CSS(URL 缓存约30分钟,不宜频繁修改)
常见错误与改进方案
| 错误做法 | 问题 | 解决方案 |
|---|---|---|
重复粘贴 <bstyle> | 代码重复、难维护 | 模板化 + 哨兵机制 |
大量内联 style | 不可搜索、难复用 | 合并到 #css/<bstyle> |
| 频繁改 Common.css | 缓存30分钟,效果慢 | 先内联验证再合并 |
| 全站差异写 Common.css | 污染全局 | 用页面/模板级样式 |
滥用 !important | 调试困难 | 提高选择器层级 |
2. 四种实现方式详解
2.1 #css 解析函数(推荐默认方式)
安全性最高:经过 Sanitizer::checkCss() 安全检测,不支持被标记为”不安全”的函数和属性。采用内联注入方式,修改后刷新页面立即生效,无需等待 URL 缓存。
语法示例:
{{#css: .my-box { padding:8px; background:#f6f6f6; }}}
{{#css: 模板:MyStyles/main.css}}处理流程:
- 检查参数是否为存在的页面标题 → 如果是,按页面原始内容(
action=raw)加载 - 如果以
/开头 → 按服务器相对路径加载 - 否则视为内联 CSS 代码 → 安全检测 → Base64 编码 → 注入到
<head>中的data:text/css
受限功能(会被替换为 /* insecure input */):
url()、var()、filter()、calc()、image()、expression()- 特殊前缀属性(如
-o-link) 需要这些功能时请使用<bstyle>
适用场景:轻量级、局部样式、无需 CSS 变量;快速验证,避开全局30分钟缓存
2.2 <bstyle>(功能完整的块级样式)
完整语法支持:支持 CSS 变量、背景图片、calc() 计算等高级功能。同样是内联方式,更新即时生效,但需要自行控制安全性和代码体积。
语法示例:
<bstyle>/*<pre>*/
.hero-section {
--primary-color: #3b82f6;
background: url(https://example.com/bg.jpg) center/cover no-repeat;
color: var(--primary-color);
}
/*</pre>*/</bstyle>重要提示:必须保留 /*<pre>*/ ... /*</pre>*/ 注释包装,避免解析器插入 P 标签或破坏代码缩进。
2.3 内联 style 属性(仅限临时实验使用)
示例:
<div style="border:1px solid #ccc; padding:6px; font-size:90%">提示内容</div>使用风险:样式代码分散,难以检索和维护 → 建议最终迁移到集中管理的样式表中
2.4 Widget 扩展(结构复用 + 样式封装)
调用方式:
{{#widget:CustomInfobox}}Widget 内部结构示例:
<div class="infobox-template">
<style>
.infobox-template {
background: #f8f9fa;
border-left: 4px solid #3b82f6;
padding: 16px;
margin: 16px 0;
}
</style>
说明文本内容
</div>适用场景:信息卡片、标签集合、交互式容器等可复用组件。需要管理员权限创建和维护。
3. 模板 CSS 去重机制
问题背景
当同一模板在页面中被多次调用时,会导致 CSS 样式重复注入,造成:
- 代码体积膨胀:相同的样式被多次加载
- 覆盖链混乱:重复的样式可能相互干扰
- 性能低下:内联重复样式不受缓存合并优化
统一解决方案:变量哨兵机制
使用变量作为标志位,确保样式只注入一次:
#css 方式去重:
{{#if:{{#varexists:CSS:MyTemplate}} ||
{{#vardefine:CSS:MyTemplate|1}}
{{#css:
.my-template-styles {
/* 样式定义 */
}
}}
}}<bstyle> 方式等价实现:
{{#if:{{#varexists:模板样式CSS}} ||
{{#vardefine:模板样式CSS|1}}
<bstyle>/*<pre>*/
/* 组件独占样式 */
/*</pre>*/</bstyle>
}}命名规范建议
- 变量命名:使用
CSS:模板名格式,避免命名冲突 - 单一职责:一个模板对应一个哨兵变量
- 清晰标识:变量名应明确标识对应的模板和样式用途
4. CSS 优先级与加载顺序
级联层次(从低到高)
- 核心样式(MediaWiki Core)
- 扩展样式(Bootstrap、BWiki平台样式等)
- 站点公共样式:
MediaWiki:Common.css - 皮肤样式:
MediaWiki:Vector.css - 页面级样式:
#css/<bstyle> - 标签内联样式:
style="..."
策略建议
- 保持”越局部越后置”:局部样式应该放在更后的位置
- 减少
!important使用:优先通过提高选择器特异性来解决问题 - 实验优先内联:先使用局部内联方式验证,稳定后再合并到全局(需要考虑缓存等待时间)
5. 调试标准流程
系统化调试步骤
| 步骤 | 目标 | 操作 | 预期结果 |
|---|---|---|---|
| 0. 缓存检查 | 确认文件版本 | 无效时用 ?action=purge | 刷新后生效 |
| 1. 元素定位 | 锁定目标元素 | 右键检查或 F12 | 选中 DOM 节点 |
| 2. 选择器验证 | 确认匹配 | hover CSS 规则 | 元素高亮命中 |
| 3. 覆盖分析 | 确定覆盖关系 | 看 Styles 面板划线 | 找到更高规则 |
| 4. 临时验证 | 验证思路 | DevTools 改值 | 期望效果出现 |
| 5. 修改归档 | 固化修改 | 写回模板/片段 | 命名一致 |
| 6. 缓存清理 | 确保更新 | ?action=purge | 新内容显示 |
快速问题诊断:五类常见根因
当样式”没有生效”时,优先检查以下五类原因:
- URL 缓存未过期:全局样式有约30分钟缓存
- 加载失败:样式文件或资源加载错误
- 语法被过滤:使用了被安全机制拦截的语法
- 选择器未命中:选择器无法匹配目标元素
- 被其他规则覆盖:被更高特异性或后置的规则覆盖
6. 常见问题与解决方案
| 现象 | 原因 | 解决方案 |
|---|---|---|
| Common.css 无变化 | URL 缓存未过期 | 等待或用内联验证 |
| CSS 被注释掉 | 触发安全过滤 | 用 <bstyle> 或移除禁用指令 |
<bstyle> 含 HTML | 缺失 /*<pre>*/ 注释 | 补充注释包装 |
| 样式顺序混乱 | 模板重复注入 | 使用哨兵去重 |
| 移动端错位 | 无响应式断点 | 补 @media 查询 |
| 样式不生效 | 特异性低/被覆盖 | 增加父级限定 |
滥用 !important | 层次设计差 | 重构结构 |
7. 最佳实践指南
7.1 命名规范(语义化 + 作用域 + 角色)
推荐命名示例:
infobox-character(信息框-角色)card--featured(卡片-特色样式)btn-primary(按钮-主要样式)
避免的命名:
content、header、box1(过于通用,缺乏语义)
7.2 与 Bootstrap 3.7 协同工作
充分利用现有能力:
- 栅格系统:
.row+.col-md-* - 按钮组件:
.btn及相关变体 - 辅助工具类:
.text-center、.mt-3等
扩展策略:不要直接覆盖核心类
/* 正确:使用前缀容器限定作用域 */
.my-widget .btn { border-width: 2px; }
.my-layout .col-md-6 { padding: 20px; }
/* 响应式适配 */
@media (max-width: 768px) {
.my-card { margin-bottom: 12px; }
}7.3 性能优化要点
- 选择器深度:避免超过3层的深层选择器,酌情重构
- 避免通配符:不要使用
*选择器,影响性能 - 变量管理:CSS 变量集中在
<bstyle>或全局样式表中 - 去重机制:使用哨兵变量防止重复注入
- 迭代策略:实验阶段使用内联方式,稳定后合并到全局(减少缓存等待)
7.4 可访问性(A11y)考虑
/* 类链接样式 */
.link-like {
color: #0a63c9;
text-decoration: underline;
}
.link-like:focus {
outline: 2px solid #0a63c9;
outline-offset: 2px;
}
/* 视觉隐藏但保持可访问性 */
.is-hidden-visually {
position: absolute;
clip: rect(1px, 1px, 1px, 1px);
width: 1px;
height: 1px;
overflow: hidden;
}7.5 CSS 变量集中管理
/* 在根元素或全局样式中定义变量 */
:root {
--color-accent: #3b82f6;
--radius-sm: 4px;
}
/* 使用变量保持一致性 */
.panel {
border-radius: var(--radius-sm);
border: 1px solid var(--color-accent);
}8. 反模式与改进方案
| 反模式 | 问题 | 替代方案 |
|---|---|---|
| CSS 写业务逻辑 | 不稳定、难维护 | 用语义 class 表示状态 |
复制粘贴 <bstyle> | 维护困难 | 模板 + 哨兵去重 |
| 全局覆盖核心类 | 破坏其他模块 | 父容器限定作用域 |
| 滥用绝对定位 | 响应式失效 | 用 Flex/Grid 布局 |
| 透明图片占位 | 过时技术 | 用 min-height/空容器 |
9. 学习资源与工具推荐
精选学习资源
| 资源分类 | 链接 | 简介 |
|---|---|---|
| MDN CSS 指南 | https://developer.mozilla.org/zh-CN/docs/Web/CSS | 全面参考文档 |
| CSS 选择器 | https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Selectors | 选择器语法详解 |
| CSS 变量 | https://developer.mozilla.org/zh-CN/docs/Web/CSS/Using_CSS_custom_properties | 变量使用指南 |
| Flexbox | https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Flexible_Box_Layout | 弹性布局教程 |
| Grid | https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Grid_Layout | 网格布局系统 |
| 响应式设计 | https://developer.mozilla.org/zh-CN/docs/Learn/CSS/CSS_layout/Responsive_Design | 响应式原理实践 |
| BEM 方法论 | http://getbem.com/ | 命名方法论 |
| CSS 性能 | https://developer.mozilla.org/zh-CN/docs/Web/Performance/CSS | 性能最佳实践 |
| W3C 验证器 | https://jigsaw.w3.org/css-validator/ | 代码验证工具 |
| CodePen | https://codepen.io/ | 在线编辑平台 |
| CSS-Tricks | https://css-tricks.com/ | 技巧教程网站 |
| Stack Overflow | https://stackoverflow.com/questions/tagged/css | 技术问答社区 |
10. 缓存机制速览
| 类型 | 形态 | 缓存时间 | 用途 |
|---|---|---|---|
| Common.css/皮肤CSS | URL 资源 | ~30min | 全站规范 |
#css 代码块 | 内联 | 即时 | 小块/快速验证 |
<bstyle> 块 | 内联 | 即时 | 完整语法组件 |
| 模板 raw CSS | URL 资源 | ~30min | 复用低改动样式 |
Widget <style> | 内联 | 即时 | 结构+样式复用 |
附录:常用代码片段
轻量卡片样式
{{#css:
.card-lite {
background: #fff;
border: 1px solid #e3e5e8;
padding: 12px;
border-radius: 4px;
}
}}CSS 变量定义和使用
<bstyle>/*<pre>*/
:root {
--accent-color: #3b82f6;
}
.accent-text {
color: var(--accent-color);
}
/*</pre>*/</bstyle>调试辅助样式
/* 突出显示待检查区块 */
.debug-outline * {
outline: 1px dashed rgba(0, 0, 0, 0.25);
}总结
遵循系统化的 CSS 开发流程:
- 根据缓存特性选择合适的方式
- 使用内联方式进行快速验证
- 通过模板化和哨兵机制实现去重
- 稳定后再合并到全局样式
- 控制选择器特异性和性能
- 采用统一的命名规范
- 建立可观测的调试流程
最终目标:实现稳定、可维护、可迭代的 CSS 架构。
每一次修改都应遵循:明确意图 → 局部验证 → 归档整合 → 预估缓存影响