Skip to content

style 内联样式

<style> 元素用于在 HTML 文档中直接嵌入 CSS 样式规则。与 <link> 外部引入相比,<style> 的样式代码直接写在 HTML 文件中,适合页面特定的样式或性能优化中的关键 CSS 内联。

前置知识

阅读本节前,建议先了解:script 标签与 JavaScript

基础概念

style 的作用

<style> 元素包含 CSS 样式规则,这些规则会直接应用到当前 HTML 文档。它是将样式与结构放在同一文件中的方式。

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>内联样式示例</title>
  <style>
    body {
      font-family: system-ui, sans-serif;
      margin: 0;
      padding: 20px;
      line-height: 1.6;
      color: #333;
    }
    h1 {
      color: #0066cc;
      border-bottom: 2px solid #0066cc;
      padding-bottom: 10px;
    }
  </style>
</head>
<body>
  <h1>页面标题</h1>
  <p>页面内容使用内联 CSS 样式。</p>
</body>
</html>
特性<style> 内联<link> 外部
样式位置HTML 文件内独立的 CSS 文件
可缓存否(随 HTML 缓存)是(单独缓存)
文件大小增大 HTML 文件减小 HTML 文件
维护性分散在多个 HTML 文件中集中在 CSS 文件中
复用性仅限当前页面多个页面共享
HTTP 请求无额外请求需要额外请求
适用场景关键 CSS、页面特定样式主要样式表

语法

基本语法

html
<style>
  /* CSS 样式规则 */
  选择器 {
    属性: 值;
    属性: 值;
  }
</style>

支持的属性

属性说明示例
media媒体查询条件media="(max-width: 768px)"
type样式类型(默认 text/csstype="text/css"
title样式表标题(用于可选样式表)title="蓝色主题"
disabled禁用样式表disabled
nonce内容安全策略 nonce 值nonce="abc123"
scoped作用域样式(已废弃)不再使用

详细说明

media 属性

<style>media 属性允许你为不同的设备或条件定义样式:

html
<!-- 所有设备 -->
<style>
  body { font-family: system-ui, sans-serif; }
</style>

<!-- 仅打印时 -->
<style media="print">
  body { font-family: serif; color: black; }
  nav, footer, .no-print { display: none; }
</style>

<!-- 仅小屏幕 -->
<style media="(max-width: 768px)">
  .sidebar { display: none; }
  .main-content { width: 100%; }
</style>

<!-- 暗色模式 -->
<style media="(prefers-color-scheme: dark)">
  body { background: #1a1a2e; color: #e0e0e0; }
</style>

<!-- 减少动画偏好 -->
<style media="(prefers-reduced-motion: reduce)">
  * { animation: none !important; transition: none !important; }
</style>

媒体查询不匹配时不加载

media 条件不匹配时,浏览器不会解析或应用该 <style> 中的 CSS 规则,也不会加载其内容。

type 属性

type 属性指定样式表的 MIME 类型,默认为 text/css

html
<!-- 默认值,可以省略 -->
<style type="text/css">
  body { color: #333; }
</style>

<!-- 不推荐:其他类型 -->
<!-- <style type="text/less"> -->
<!-- Less 样式,需要编译 -->

title 属性与可选样式表

title 属性可以为样式表命名,配合 JavaScript 实现样式表切换:

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>可选样式表</title>

  <!-- 默认启用的样式表 -->
  <style>
    body { font-family: system-ui, sans-serif; margin: 0; padding: 20px; transition: all 0.3s; }
  </style>

  <!-- 可选样式表(默认不启用) -->
  <style title="蓝色主题">
    body { background: #e3f2fd; color: #0d47a1; }
    h1 { color: #1565c0; }
  </style>

  <style title="绿色主题">
    body { background: #e8f5e9; color: #1b5e20; }
    h1 { color: #2e7d32; }
  </style>

  <style title="暗色主题">
    body { background: #1a1a2e; color: #e0e0e0; }
    h1 { color: #64b5f6; }
  </style>
</head>
<body>
  <h1>可选样式表演示</h1>
  <p>点击下方按钮切换主题:</p>
  <div>
    <button onclick="switchTheme('默认')">默认</button>
    <button onclick="switchTheme('蓝色主题')">蓝色</button>
    <button onclick="switchTheme('绿色主题')">绿色</button>
    <button onclick="switchTheme('暗色主题')">暗色</button>
  </div>

  <script>
    function switchTheme(themeName) {
      var sheets = document.querySelectorAll('style[title]');
      sheets.forEach(function(sheet) {
        sheet.disabled = (sheet.title !== themeName && themeName !== '默认');
      });
    }
  </script>
</body>
</html>

永久样式表 vs 可选样式表

没有 title 属性的 <style> 是"永久样式表",始终启用。有 title 属性的 <style> 是"可选样式表",默认也启用,但可以通过 JavaScript 切换。

disabled 属性

disabled 属性可以禁用样式表:

html
<style>
  body { color: #333; }
</style>

<style disabled>
  /* 这组样式被禁用,不会应用 */
  body { color: red; background: yellow; }
</style>

通过 JavaScript 动态切换:

javascript
var styleEl = document.querySelector('style#my-style');
styleEl.disabled = true;   // 禁用
styleEl.disabled = false;  // 启用

nonce 属性(安全)

nonce(Number Used Once)属性配合内容安全策略(CSP)使用,允许只执行带有特定 nonce 值的内联样式:

html
<meta http-equiv="Content-Security-Policy" content="style-src 'self' 'nonce-abc123'">

<style nonce="abc123">
  body { color: #333; }
</style>

<!-- 这个 style 没有 nonce,会被 CSP 阻止 -->
<!-- <style>body { color: red; }</style> -->

scoped 属性(已废弃)

scoped 属性曾用于限制样式的作用域只影响父元素内部:

html
<!-- 已废弃!不再推荐使用 -->
<section>
  <style scoped>
    h1 { color: red; }  /* 只影响当前 section 内的 h1 */
  </style>
  <h1>这个标题是红色的</h1>
</section>

已废弃

scoped 属性从未被主流浏览器广泛支持,现已被 HTML 规范移除。替代方案:使用 CSS 的 :where() 选择器或 CSS Modules / CSS-in-JS 等方案。

style 标签的位置

<head> 中(推荐)

html
<head>
  <style>
    body { margin: 0; }
  </style>
</head>
<body>
  <h1>页面内容</h1>
</body>

<body> 中(允许但不推荐作为主要样式)

html
<body>
  <h1>页面内容</h1>
  <style>
    /* body 中的 style 也是合法的 */
    .special { color: red; }
  </style>
  <p class="special">特殊样式</p>
</body>

<body> 中使用 <style> 的合理场景:

  • 组件化开发中,样式与组件放在一起
  • 动态注入的样式
  • 服务端渲染(SSR)中按需输出样式

实战示例

关键 CSS 内联(性能优化)

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>关键 CSS 内联</title>

  <!-- 关键 CSS:确保首屏快速渲染 -->
  <style>
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
    body { font-family: system-ui, -apple-system, sans-serif; line-height: 1.6; color: #333; background: #fff; }
    .header { display: flex; align-items: center; justify-content: space-between; padding: 16px 24px; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
    .logo { font-size: 20px; font-weight: bold; color: #0066cc; }
    .nav { display: flex; gap: 20px; }
    .nav a { text-decoration: none; color: #666; }
    .hero { text-align: center; padding: 60px 24px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; min-height: 400px; display: flex; flex-direction: column; align-items: center; justify-content: center; }
    .hero h1 { font-size: 2.5em; margin-bottom: 16px; }
    .hero p { font-size: 1.2em; opacity: 0.9; }
    .skeleton { background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%); background-size: 200% 100%; animation: shimmer 1.5s infinite; }
    @keyframes shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }
  </style>

  <!-- 非关键 CSS:延迟加载 -->
  <link rel="stylesheet" href="/css/main.css" media="print" onload="this.media='all'">
  <noscript><link rel="stylesheet" href="/css/main.css"></noscript>
</head>
<body>
  <header class="header">
    <div class="logo">MyApp</div>
    <nav class="nav">
      <a href="/">首页</a>
      <a href="/about">关于</a>
    </nav>
  </header>
  <main>
    <section class="hero">
      <h1>欢迎访问</h1>
      <p>这是首屏内容,使用内联关键 CSS 确保快速渲染。</p>
    </section>
    <!-- 非关键内容区域 -->
    <div class="content">
      <div class="skeleton" style="height:200px;margin:20px;"></div>
      <div class="skeleton" style="height:200px;margin:20px;"></div>
    </div>
  </main>
</body>
</html>

使用 JavaScript 动态创建和操作 style

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>动态 style 操作</title>
  <style>
    body { font-family: system-ui, sans-serif; max-width: 600px; margin: 40px auto; padding: 0 20px; }
    button { padding: 8px 16px; margin: 5px; cursor: pointer; background: #0066cc; color: white; border: none; border-radius: 4px; }
    .demo { padding: 20px; margin: 15px 0; border: 1px solid #ddd; border-radius: 4px; }
  </style>
</head>
<body>
  <h1>动态 Style 操作</h1>
  <div class="demo" id="demo-box">这是一个可样式化的盒子。</div>
  <div>
    <button id="btn-add">添加 style 标签</button>
    <button id="btn-css-text">修改 CSS 文本</button>
    <button id="btn-remove">移除 style 标签</button>
  </div>

  <script>
    var dynamicStyle = null;

    document.getElementById('btn-add').addEventListener('click', function() {
      if (dynamicStyle) return;
      dynamicStyle = document.createElement('style');
      dynamicStyle.id = 'dynamic-style';
      dynamicStyle.textContent =
        '#demo-box { background: #e3f2fd; border-color: #0066cc; color: #0066cc; padding: 30px; font-size: 18px; }';
      document.head.appendChild(dynamicStyle);
    });

    document.getElementById('btn-css-text').addEventListener('click', function() {
      if (!dynamicStyle) return;
      dynamicStyle.textContent =
        '#demo-box { background: #fce4ec; border-color: #e91e63; color: #c2185b; padding: 40px; font-size: 20px; border-radius: 12px; }';
    });

    document.getElementById('btn-remove').addEventListener('click', function() {
      if (dynamicStyle) {
        dynamicStyle.remove();
        dynamicStyle = null;
      }
    });
  </script>
</body>
</html>

注意事项

1. 多个 style 标签的优先级

html
<style>
  h1 { color: red; }
</style>

<!-- 后面的覆盖前面的 -->
<style>
  h1 { color: blue; }  /* h1 最终是蓝色 */
</style>

<!-- 与 link 的顺序也遵循"后声明覆盖先声明" -->
<link rel="stylesheet" href="external.css">  <!-- 如果 external.css 设置了 h1 颜色 -->
<style>
  h1 { color: green; }  /* 这个会覆盖 external.css 中的 h1 颜色 */
</style>

2. style 中的 @import 性能问题

html
<style>
  /* 不推荐:@import 在 style 中也是串行加载 */
  @import url('reset.css');
  @import url('theme.css');
</style>

3. 大量内联样式会影响 HTML 大小

html
<!-- 不推荐:几百行的内联 CSS -->
<style>
  /* 大量样式代码... */
  /* 这会显著增大 HTML 文件大小 */
  /* 且无法利用浏览器缓存 */
</style>

4. 内容安全策略(CSP)可能阻止内联样式

如果 CSP 设置了 style-src 'self'(不允许内联样式),<style> 标签会被阻止。需要添加 noncesha256- 哈希值。

最佳实践

1. 主要样式使用外部 CSS

html
<link rel="stylesheet" href="css/style.css">

2. 仅将关键 CSS 内联

html
<style>/* 首屏关键样式 */</style>
<link rel="stylesheet" href="css/main.css">

3. 为 style 标签添加 media 条件

html
<style media="(prefers-color-scheme: dark)">/* 暗色模式样式 */</style>

4. 使用 nonce 提升 CSP 安全性

html
<style nonce="SERVER_GENERATED_NONCE">body { color: #333; }</style>

5. 构建工具自动处理

现代构建工具(Vite、Webpack 等)会自动提取 <style> 中的 CSS 到外部文件中:

源码: HTML 中的 <style> → 构建后: 外部 .css 文件 + <link> 引入

下一节

继续学习:noscript 标签

参考链接