Mit position: sticky können wir nun endlich einen Container/Element ab einer bestimmten Position festsetzen.
Ein kurzer Reminder:
Bisher können Webworker folgende Positionen für Container/Elemente einer Seite zuweisen.
- position: static (default)
- position: relative (relative position in document order)
- position: absolute (absolute position in relative context)
- position: fixed (fixed in viewport)
Die Idee ein Container/Element ab einer bestimmten Position „sticky“ zu setzen, also zuerst mitscrollen zu lassen und dann ab einer bestimmten Position zu fixieren, gibt es im Webdesign schon länger. Ich erinnere mich noch als @rem auf jqueryfordesigners.com die Umsetzung mit jQuery erklärt hat.
Seit einiger Zeit gibt es aber eine neue CSS3-Eigenschaft, die das Verhalten nativ im Browser integriert. Diese ist bereits im Safari 6.1 und neuer (mit -webkit-Prefix) aktiviert, funktioniert also auch im Safari Mobile. Chrome und Firefox (auch auf Android) haben die Eigenschaft aktuell hinter einem Flag integriert, Microsoft denkt drüber nach.
position: sticky in Chrome/Firefox aktivieren
im Chrome in der Adresszeile chrome://flags/#enable-experimental-web-platform-features
eingeben und „Experimentelle Webplattformfunktionen” aktivieren
im Firefox in der Adresszeile about:config
eingeben, layout.css.sticky.enabled
suchen und auf true
setzen.
Verwendung in CSS
.sticky {
position: -webkit-sticky;
position: sticky;
}
Modernizr Feature Detection
Mit Modernizr kann ich mit einem zusätzlich eingebundenem Test prüfen ob der Browser ‚position: sticky‘ unterstützt. Auf der http://modernizr.com/download/ ist die Option unter „Non-core detects”, hier den Haken setzen und ein Custom-Build erstellen.
Wer grunt-modernizr verwendet, gibt als Option den zusätzlichen Test mit tests: ['css-positionsticky']
in der Grunt-Config (gruntfile.js) an:
// Build modernizr
modernizr: {
dist: {
devFile: 'path/to/source/modernizr.js',
outputFile: 'path/to/build/modernizr.min.js',
files: {
src: [
'js/{,*/}*.js',
'css/{,*/}*.scss',
'!js/vendor/*'
]
},
uglify: true,
parseFiles: true,
tests: ['css-positionsticky']
}
}
Dann kann anschließend die Eigenschaft mit Javascript abgefragt werden:
Modernizr.csspositionsticky; // true or false
Fallbacks und Polyfills
Ich tendiere ja immer dazu ein visuelles Verhalten nur für Browser zu aktivieren, die das bereits vollständig nativ unterstützen. Besonders bei Responsive Webdesign lässt sich ein Fallback zu position: fixed
schwieriger integrieren, da die dynamischen Positionen von Javascript immer neu berechnet werden müssten, das kann sich natürlich negativ auf die Performance auswirken.
Der mögliche Fallback sollte also immer getestet werden.
Aktuell empfehle ich die sticky Eigenschaften nur mit zusätzlicher (Detection-) Klasse zu nutzen. Die Position (top/bottom) also nur zusammen mit sticky setzen.
Beispiel
.sticky {
position: static;
}
.csspositionsticky .sticky {
position: sticky;
top: 20em;
}
Polyfill:
Die Filamentgroup hat einen Polyfill für position: sticky
veröffentlicht, der das Verhalten auch für Browser implementiert, die die Eigenschaft nicht unterstützen.
Den Polyfill bei Bedarf nachladen kann man über Modernizr.load
Modernizr.load({
test: Modernizr.csspositionsticky,
nope: 'fixedsticky.js'
});
Hinweis: in Modernizr 3.0 soll Modernizr.load (das unter der Haube ja yepnope ist) wieder herausgelöst werden, dann also yepnope verwenden
Demo: Sticky Header
See the Pen position: sticky header by Sven Wolfermann (@maddesigns) on CodePen.
Ich hoffe, dass Chrome und Firefox die Eigenschaft bald frei schalten – fehlt nur noch der IE…
Warum?
.sticky
{
position: static;
position: sticky;
top: 20em;
}
sollte dasselbe tun. Browser, die `position: sticky` nicht kennen, ignorieren die Deklaration und verwenden `position: static`. Da `top` dann nicht wirkt, sondern nur bei positionierten Elementen, stört die Angabe also nicht.
wenn das Element auf
position: relative
gesetzt ist, wird das schon komplizierter