
本文介绍如何通过结构分离(将任务文本包裹在 中)和精准 CSS 选择器,确保 text-decoration: line-through 仅作用于任务文字,而不影响右侧的删除图标(X)。
本文介绍如何通过结构分离(将任务文本包裹在 `` 中)和精准 css 选择器,确保 `text-decoration: line-through` 仅作用于任务文字,而不影响右侧的删除图标(x)。
在构建 JavaScript 待办事项应用时,一个常见但易被忽视的样式问题:当为已完成任务添加 text-decoration: line-through 时,该装饰会“穿透”到同级子元素(如删除图标),导致图标也被划掉。根本原因在于 text-decoration 是继承性属性,且对行内元素(如 )生效时,会作用于其所在整行内容——尤其当图标与文字共处同一行盒(inline formatting context)且未明确隔离时。
✅ 正确解法是语义化结构 + 精准样式控制:
HTML 结构优化:不再直接将任务文本设为
- 的 innerHTML,而是创建独立的 包裹文字,并将删除图标 作为兄弟节点插入。这样两者在 DOM 层级上完全分离,样式可独立控制。
CSS 精准作用域:仅对 .checked .task-text 应用 line-through,彻底避开 .icon 元素:
.task-text {
flex-grow: 1; /* 占据剩余空间,保证图标右对齐 */
}
.checked .task-text {
text-decoration: line-through;
color: #555;
}
- JS 逻辑同步更新(关键修改):
function addTask() {
if (input.value.trim() === '') {
alert("You must write something!");
return;
}
const li = document.createElement("li");
li.classList.add("task");
// ✅ 创建独立文本容器
const taskText = document.createElement("span");
taskText.textContent = input.value; // 推荐用 textContent 而非 innerHTML,防 XSS
taskText.classList.add("task-text");
// ✅ 创建图标并绑定事件(更健壮的写法)
const icon = document.createElement("i");
icon.classList.add("icon", "fa-solid", "fa-x");
icon.addEventListener("click", (e) => {
e.stopPropagation(); // 阻止冒泡,避免触发父级 li 的 toggle 逻辑
li.remove();
});
// ✅ 按序追加:先文本,再图标
li.append(taskText, icon);
taskContainer.appendChild(li);
input.value = "";
}
⚠️ 注意事项:
- 事件冒泡处理:为图标添加 e.stopPropagation(),防止点击 X 时同时触发 li 的 checked 切换;
- 使用 textContent 替代 innerHTML:提升安全性,避免用户输入 HTML 标签引发意外渲染或脚本执行;
- .task 容器需保持 display: flex:确保 .task-text 的 flex-grow: 1 生效,使图标自然右对齐;
- 避免全局重置污染:当前 CSS 中 * { text-decoration: none } 无效,因 text-decoration 不继承自父级 *,必须显式声明目标元素。
最终效果:勾选任务后,仅文字显示删除线,红色 X 图标清晰完整、无任何装饰干扰——结构清晰、样式可控、逻辑健壮,符合现代前端开发最佳实践。











