最推荐构建阶段处理,如用11ty将header抽为_includes/header.njk并用{% include 'header.njk' %}注入,生成纯静态html;若只能用客户端方案,需domcontentloaded后fetch加载并手动初始化交互,注意资源路径和csp限制。

HTML 中怎么复用同一个 <header></header>
不能直接在多个 HTML 文件里写死同一段 header 代码,否则改一次得同步改几十个文件。最简单靠谱的做法是服务端包含(SSI)或构建时处理,但如果你只有纯静态页面、没服务器权限,就得靠客户端方案兜底。
- 用
fetch()+innerHTML动态加载:适合现代浏览器,但 SEO 不友好,首屏有白屏延迟 - 用
<iframe></iframe>嵌入:兼容性最好,但样式隔离、高度自适应、SEO 同样差,还可能被 CSP 拦截 - 真正推荐的是构建阶段处理:用
html-webpack-plugin(Webpack)、eleventy(11ty)或甚至 shell 脚本把公共header.html注入到每个页面中——生成的是纯静态 HTML,无运行时依赖
用 JavaScript 动态插入 header 的典型写法
不是所有项目都能上构建工具,临时方案就得靠 JS。关键不是“能不能加”,而是“加完样式和交互是否正常”。
- 必须等
DOMContentLoaded触发后再操作 DOM,否则document.querySelector('header')找不到目标位置 - 插入后记得手动初始化 header 里的 JS 行为,比如导航菜单的点击事件——动态插入的元素不会自动绑定原有事件监听器
- 如果 header 含
<link rel="stylesheet">或<script></script>,要确保路径是相对当前 HTML 的,不是相对于被加载的header.html文件 - 示例:
fetch('components/header.html')<br> .then(r => r.text())<br> .then(html => {<br> document.getElementById('header-placeholder').innerHTML = html;<br> initHeaderNav(); // 手动触发初始化<br> });
为什么 <include></include> 或 @include 在原生 HTML 里不生效
因为浏览器根本不认识这些语法——它们是 SSI、PHP、Jinja、EJS 等服务端或模板引擎的指令,不是 HTML 标准。直接写进 .html 文件,浏览器会当普通文本渲染,甚至可能报解析错误。
网页中拖动 DIV 是很常见的操作,今天就分享给大家一个 jQuery 多列网格拖动布局插件,和其它的插件不太一样的地方在于你处理拖放的元素支持不同大小,并且支持多列的网格布局,它们会自动的根据位置自己排序和调整。非常适合你开发具有创意的应用。这个插件可以帮助你将任何的 HTML 元素转换为网格组件
-
<!--#include file="header.html"-->只在启用 SSI 的 Apache/Nginx 上有效,且需配置Includes选项 -
是 EJS 语法,必须经 EJS 引擎编译,不能直接双击打开 .html - 本地用
file://协议打开时,fetch()会因跨域限制失败(CORS),必须起一个本地服务,比如npx serve或python3 -m http.server
构建时复用 header 的最小可行配置(以 11ty 为例)
比手写 JS 更稳,比配 Webpack 更轻量。核心是把 header 抽成单独文件,用模板语法引用。
立即学习“前端免费学习笔记(深入)”;
- 把公共头存为
_includes/header.njk(Nunjucks 格式)或_includes/header.liquid - 在页面模板里写
{% include 'header.njk' %},11ty 构建时自动合并 - 支持传参:比如
{% include 'header.njk' navItems=navItems %},让 header 根据页面动态变化 - 注意路径:11ty 默认只处理
_includes和_data目录,放错位置不会报错,但内容不会出现
logo.png、main.css)。它们在独立文件里看着正常,一旦被注入到不同层级的页面(如 /about/index.html vs /index.html),路径就全乱了。统一用根对齐路径(/assets/logo.png)或者构建时用 posthtml 插件重写,别指望浏览器自动猜。









