Einfaches Beispiel ein Header und drei Banner dessen Elemente eine Class isSticky bekommen. (657 Bytes) 08.12.2021 08:08
HTML:
<!DOCTYPE html >
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="sticky.css" />
</head>
<body>
<div class="banner top"></div>
<div class="banner left"></div>
<div class="banner right"></div>
<header class="sticky">
<ul class="language">
<li class="active">DE</li>
<li>EN</li>
<li>NL</li>
<li>FR</li>
</ul>
<div class="logo">Sticky Header</div>
<ul class="navi">
<li class="active">Programmierung</li>
<li>Projekte</li>
<li>Server</li>
<li>Privat</li>
</ul>
</header>
</body>
<main>Main</main>
<script src="sticky.js"></script>
</html>
Oder auch ohne banner: Beispiel (546 Bytes) 08.12.2021 08:09
<!DOCTYPE html >
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="sticky.css" />
</head>
<body>
<header class="sticky">
<ul class="language">
<li class="active">DE</li>
<li>EN</li>
<li>NL</li>
<li>FR</li>
</ul>
<div class="logo">Sticky Header</div>
<ul class="navi">
<li class="active">Programmierung</li>
<li>Projekte</li>
<li>Server</li>
<li>Privat</li>
</ul>
</header>
</body>
<main>Main</main>
<script src="sticky.js"></script>
</html>
JavaScript:
// coding: utf-8
/*! Created by: Udo Schmal | https://www.gocher.me/ */
(function () {
'use strict';
let stickyHeader = document.querySelector('header.sticky');
var clone = null;
let bannerLeft = document.querySelector('div.banner.left');
let bannerRight = document.querySelector('div.banner.right');
// for old browser that doesn't support position sticky
let positionSticky = 'sticky';
let intersectionObserver = new IntersectionObserver(
function (entries) {
if(entries[0]) {
if (entries[0].boundingClientRect.top < 0) {
// for old browser that doesn't support position sticky
if (positionSticky != "sticky") {
if (!clone) {
clone = stickyHeader.cloneNode(true);
clone.classList.add('clone');
clone.classList.add('isSticky');
stickyHeader.parentNode.insertBefore(clone, stickyHeader.nextSibling);
stickyHeader.style.position = 'relative';
stickyHeader.style.top = 'inherit';
}
clone.style.width = window.getComputedStyle(stickyHeader).getPropertyValue('width');
} else {
entries[0].target.classList.add('isSticky');
}
if (bannerLeft) {
bannerLeft.classList.add('isSticky');
}
if (bannerRight) {
bannerRight.classList.add('isSticky');
}
} else {
entries[0].target.classList.remove('isSticky');
if (bannerLeft) {
bannerLeft.classList.remove('isSticky');
}
if (bannerRight) {
bannerRight.classList.remove('isSticky');
}
// for old browser that doesn't support position sticky
if (positionSticky != "sticky") {
if (clone) {
stickyHeader.parentNode.removeChild(clone);
clone = null;
stickyHeader.style.position = '';
stickyHeader.style.top = '';
}
}
}
}
},
{threshold: [1]}
);
let resizeObserver = new ResizeObserver(
function (entries) {
if (positionSticky != "sticky") {
if (clone) {
let style = window.getComputedStyle(stickyHeader);
clone.style.width = style.getPropertyValue('width');
}
}
}
);
if (stickyHeader) {
let style = window.getComputedStyle(stickyHeader);
positionSticky = style.getPropertyValue("position");
stickyHeader.style.top = (parseInt(style.getPropertyValue('top'), 10) -1) + 'px';
stickyHeader.style.paddingTop = (parseInt(style.getPropertyValue('padding-top'), 10) +1) + 'px';
intersectionObserver.observe(stickyHeader);
resizeObserver.observe(stickyHeader);
}
})()
StyleSheet:
body{ height: 200vh; font-family: Arial, Helvetica, sans-serif; margin:0; padding:0;}
/* banner */
div.banner{
background: white repeating-linear-gradient( 45deg, #EEE, #EEE 5px, #FFF 5px, #FFF 10px );
margin: 0.5em auto;
padding: 0;
text-align: center;
}
div.banner.top {
width: 600px;
height: 120px;
}
@media screen and (min-width:1550px) {
div.banner.left, div.banner.right {
display: block;
position: absolute;
top: 130px;
height: 600px;
width: 160px;
}
div.banner.left {
left: 15px;
}
div.banner.right {
right: 15px;
}
div.banner.isSticky {
position: fixed;
top: 1px;
}
}
.banner.left, .banner.right {
display: none;
}
/* sticky header */
header{
position: sticky;
top: 0;
margin: 0 auto 0 auto;
max-width: 1150px;
padding: 1em;
background: #0065b3;
transition: all 500ms linear;
}
header ul.language {
position: absolute;
top: 0;
right: 20px;
margin: 0;
padding: 4px 2px;
background-color: #2d3c50;
color: white;
list-style: none;
}
header ul.language li{
float: left;
margin: 2px;
padding: 2px 6px;
border-left: 1px solid #fff;
}
header ul.language li:not(.active){
cursor: pointer;
}
header ul.language li.active{
background-color: #818a96;
}
header ul.language li:first-child {
border-left: 0;
}
header ul.navi {
position: absolute;
bottom: 15px;
left: 240px;
margin: 0;
list-style: none;
}
header ul.navi li{
float: left;
font-weight: bold;
padding: 2px 16px;
cursor: pointer;
}
header .logo {
padding: 15px;
font-weight: bold;
font-size: 25px;
position: relative;
transition: all 500ms linear;
}
/* styles for when the header is in sticky mode */
header.isSticky {
padding: .5em 1em;
}
header.isSticky .logo {
font-weight: normal;
font-size: 20px;
}
header.isSticky .logo::after {
content:" is sticky";
}
/* header clone old browser fix */
header.sticky.clone {
position: fixed;
left: 50%;
transform: translateX(-50%);
}
/* body text */
main {
text-align: center;
padding: 2em 1em;
margin: 0.5em auto;
max-width: 1150px;
height: 800px;
background: #e5e5e5;
}