JS 动态注入 CSS 样式:setStyle 函数

在油猴脚本或 Chrome 扩展里需要动态修改页面样式时,直接写 element.style.xxx 只能改行内样式,无法用 CSS 选择器批量设置。更好的方案是动态创建 <style> 标签。

setStyle 函数

function setStyle(id, css) {
    let style = document.getElementById(id);
    if (!style) {
        style = document.createElement("style");
        style.id = id;
        document.head.appendChild(style);
    }
    style.textContent = css;
}

id 做唯一标识——如果该 id 的 <style> 已存在就直接更新内容,不会重复插入。

使用示例

// 隐藏广告
setStyle("ad-blocker", `
    .ad-banner, .sidebar-ad, [class*="advertisement"] {
        display: none !important;
    }
`);

// 强制暗色模式
setStyle("dark-mode", `
    body {
        background: #1a1a1a !important;
        color: #e0e0e0 !important;
    }
    a { color: #7eb8f7 !important; }
`);

// 动态更新(复用同一个 style 元素)
setStyle("custom-theme", `body { font-size: ${fontSize}px; }`);

为什么不用 innerHTML

// ❌ 安全风险:可能被 XSS 利用
style.innerHTML = css;

// ✅ 推荐:textContent 不会解析 HTML
style.textContent = css;

textContent 只设置文本内容,不会解析 HTML 标签,比 innerHTML 更安全。

移除样式

function removeStyle(id) {
    const el = document.getElementById(id);
    if (el) el.remove();
}

removeStyle("dark-mode");

油猴脚本中的注意事项

油猴脚本默认在 document-end 注入,此时 document.head 已存在。如果设置了 @run-at document-start,需要等待 head 可用:

// @run-at document-start
function setStyle(id, css) {
    const target = document.head || document.documentElement;
    let style = document.getElementById(id);
    if (!style) {
        style = document.createElement("style");
        style.id = id;
        target.appendChild(style);
    }
    style.textContent = css;
}

document.documentElement(即 <html>)在 document-start 阶段就已存在,可以作为 fallback。

GM_addStyle(油猴内置 API)

Tampermonkey 提供了 GM_addStyle 作为快捷方式:

// @grant GM_addStyle
GM_addStyle(`
    .target-element { color: red; }
`);

不需要去重处理,但无法动态更新——每次调用都会新增一个 <style> 标签。频繁更新时还是用自定义的 setStyle