如何创建一个跨越非同级 DOM 节点的元素?
你不能。有效的 HTML 需要只有一个直接父级的层次结构(在您的假设示例中,第一个 section 将有两个:main 和带有渐变的新的)。
如果你想达到这个效果,你有几个选择:
改变你的层次结构
您可以将层次结构扁平化为
<div class="gradient-wrapper">
<header>header</header>
<section>section 1</section>
</div>
<section>section 2</section>
<section>section 3</section>
<section>section 4</section>
并将 main 的原始样式强加到使用的部分
section {
max-width: 80vw;
margin: 0 auto;
}
.gradient-wrapper {
background: linear-gradient(...);
}
这是最简单的方法,因为它设计为垂直响应:渐变将自动拉伸以包含其子项。
使用 CSS 的恒定高度
如果您的第一个 section 的高度和距离已知且恒定,您可以部署 CSS hack 以使您的 header 的背景与您的 section 的高度完全相同(无需更改原始层次结构)。
header {
position: relative;
}
header::before {
display: block;
width: 100%;
content: "";
position: absolute;
z-index: -1;
--first-section-height: (1px + 30vh + 2px);
height: calc(100% + var(--first-section-height));
background: linear-gradient(...);
}
为了清楚起见,我创建了--first-section-height 变量,它表示从header 底部到section 底部的总高度。
1px 是header 的border-bottom,
30vh 是section 的恒定高度,
2px 是它的border-top 和border-bottom .
Javascript
如果您希望保留原始层次结构并需要 section 可变大小或间隔,您可以诉诸 javascript 来监听窗口大小的变化并将 div 放置在两个要素。该行为的最小工作示例:
window.addEventListener("load", updateGradientBox);
window.addEventListener("resize", updateGradientBox);
updateGradientBox();
function updateGradientBox() {
let header = document.querySelector("header");
let section = document.querySelector("main section:first-child");
let gradient = document.querySelector("#gradient");
if (header === null || section === null || gradient === null) return;
let rects = [header, section].map((el) => el.getBoundingClientRect());
let rect = getCombinedBoundingRect(rects);
gradient.style.top = `${rect.top}px`;
gradient.style.left = `${rect.left}px`;
gradient.style.width = `${rect.width}px`;
gradient.style.height = `${rect.height}px`;
}
function getCombinedBoundingRect(rects) {
const r = {
top: Math.min(...rects.map((r) => r.top)),
left: Math.min(...rects.map((r) => r.left)),
bottom: Math.max(...rects.map((r) => r.bottom)),
right: Math.max(...rects.map((r) => r.right))
};
return {
...r,
width: r.right - r.left,
height: r.bottom - r.top
};
}
#gradient {
position: absolute;
display: block;
z-index: -1;
background: linear-gradient(rgba(217, 217, 217, 1) 0%, rgba(85, 85, 85, 1) 100%);
}
<div id="gradient"></div>
<header>header</header>
<main>
<section>section 1</section>
<section>section 2</section>
<section>section 3</section>
<section>section 4</section>
</main>
<footer>footer</footer>
这种方法的优点是它可以适应每个可以想到的尺寸和位置(正如我的最小示例所证明的那样,它根本不代表您建议的布局)。
一个完整的工作示例可以在
上找到
(请记住,我在示例中使用的是最新的 javascript 语法和 API;根据您对旧浏览器的所需支持,您可能需要使用 Babel 进行 polyfill 或编译)