how to create an element that spans non-sibling DOM nodes?
You can't. Valid HTML requires a hierarchy with only one direct parent (in your hypothetical example the first section
would have two: main
and the new one with a gradient).
If you wish to achieve this effect you have several options:
Alter your hierarchy
You could flatten your hierarchy into
<div class="gradient-wrapper">
<header>header</header>
<section>section 1</section>
</div>
<section>section 2</section>
<section>section 3</section>
<section>section 4</section>
and impose the original style of main
onto the sections using
section {
max-width: 80vw;
margin: 0 auto;
}
.gradient-wrapper {
background: linear-gradient(...);
}
This is the easiest method as it is vertically responsive by design: the gradient will automatically stretch to encompass its children.
Constant height using CSS
If the height of, and distance to your first section
are known and constant, you can deploy a CSS hack to make the background of your header
stick out to exactly the height of your section
(without changing the original hierarchy).
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(...);
}
For clarity I have created the --first-section-height
variable which represents the total height from the bottom of your header
to the bottom of your section
.
1px
is the border-bottom
of header
,
30vh
is the constant height of your section
and
2px
is its border-top
and border-bottom
.
Javascript
If you wish to keep your original hierarchy and need your section
to be variable sized or spaced, you could resort to javascript to listen for changes in the window size and position a div
at the combined bounding boxes of the two elements. A minimal working example of that behaviour:
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>
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…