纯HTML+CSS可实现无障碍、打印友好、移动端友好的食材清单页:用语义化关联唯一id的,分组,@media print隐藏未勾选项,扩大点击区域提升触控体验。

用纯 HTML + CSS 实现可勾选的食材清单页
不需要 JavaScript 就能做出带复选框、分类分组、打印友好的食材购物清单页——关键在语义化结构和 <input type="checkbox"> 的合理使用。
常见错误是直接用 <div> 模拟勾选状态,结果无法被屏幕阅读器识别、不能用空格键切换、打印时也不显示勾选状态。正确做法是让每个食材项都包裹在 <code><label></label> 里,关联原生 input:
<li> <input type="checkbox" id="item-1"> <label for="item-1">鸡蛋(6个)</label> </li>
-
id和for必须严格匹配,否则点击文字不会触发勾选 - 不要省略
id—— 没有它,for就失效 - 避免把整个
<li>当作<label></label>(HTML5 不允许嵌套交互元素)
按菜系或餐次分组食材,用 <fieldset></fieldset> + <legend></legend>
超市采购常需按“早餐”“炒菜”“汤料”等逻辑分块,<fieldset></fieldset> 是语义最准确、兼容性最好的方案,比单纯用 <h3></h3> 或 <div class="group"> 更可靠:
<pre class="brush:php;toolbar:false;"><fieldset>
<legend>早餐食材</legend>
<ul>
<li><input type="checkbox" id="breakfast-1"><label for="breakfast-1">牛奶</label></li>
<li><input type="checkbox" id="breakfast-2"><label for="breakfast-2">吐司</label></li>
</ul>
</fieldset></pre>
<ul>
<li>
<code><legend></legend> 会自动成为该组的可访问标题,读屏软件能正确播报
<fieldset></fieldset> 的默认边框样式较重,可用 border: none 覆盖,但别删 <legend></legend>
<details><summary></summary></details> 替代——它本质是折叠控件,语义不符,且无法批量操作本组所有复选框打印时保留勾选状态并隐藏未勾选项(可选)
很多人希望打印前只留下已勾选的条目,或至少让勾选状态清晰可见。纯前端可实现,无需后端:
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
立即学习“前端免费学习笔记(深入)”;
- 勾选状态本身就能被打印(现代浏览器默认保留
input[type=checkbox]的 checked 状态) - 如需「只打印已勾选项」,加一段简易 CSS:
@media print { li input:not(:checked) + label, li input:not(:checked) { display: none; } } - 注意:
:not(:checked)在 IE 中不支持,若需兼容 IE,得用 JS 动态增删 class - 打印预览中测试真实效果,Chrome 和 Edge 的「背景图形」选项默认关闭,会导致复选框勾痕不显示——务必勾选「背景图形」
移动端点按区域太小?用 CSS 扩大可点击范围
手机上手指点 <input> 原生控件容易误触,直接放大 input 元素会破坏布局。安全做法是扩大其关联 label 的点击热区:
label {
padding: 8px 0;
display: block;
}
input[type="checkbox"] {
margin-right: 8px;
}
- 不要给
input设width/height—— 它会失真,且不同系统渲染差异大 -
padding加在label上,既扩大热区又不影响语义结构 - 如果想自定义勾选图标(比如用 ✅ 替代原生方框),必须保留原生
input并用position: absolute隐藏它,再用::before伪元素模拟,否则可访问性全丢
id,导致多个同名 for 指向同一个 input,或者漏写 for 让点击失效。这类问题在开发时看不出,到打印或用读屏软件时才暴露。


















