I needed a component that would provide the following:
- Native
position: sticky
, if supported position: sticky
fallback for older browsers, like IE11- Support for
children
to be passed down as props
So I came up with the following:
import React from 'react';
import PropTypes from 'prop-types';
import { StickyContainer, Sticky } from 'react-sticky';
import positionsticky from 'modernizr-esm/feature/css/positionsticky';
const stylesStickyWrapper = {
position: 'relative',
height: '100%',
};
const stylesSticky = {
position: 'sticky',
top: '0',
height: 'auto',
};
const PositionSticky = props => {
const { children } = props;
return (
<>
{positionsticky ? (
<div style={stylesStickyWrapper}>
<div style={stylesSticky}>
{children}
</div>
</div>
) : (
<StickyContainer style={{ position: 'relative', height: '100%' }}>
<Sticky>
{({ style }) => (
<div style={style}>
{children}
</div>
)}
</Sticky>
</StickyContainer>
)}
</>
);
};
PositionSticky.propTypes = {
children: PropTypes.node.isRequired,
};
export default PositionSticky;
Simple:
<PositionSticky>
<p>Your content here</p>
</PositionSticky>
Real world scenario:
<div className="row">
<div className="col-12 col-md-6">
<PositionSticky>
<p>Blah.</p>
</PositionSticky>
</div>
<div className="col-12 col-md-6">
<PositionSticky>
<p>Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah.</p>
</PositionSticky>
</div>
</div>
In the example above, which was the one I ended up with, the length of the content for each colum can vary, causing only the one with less content to trigger its "stickyness", because its parent's height is set by the taller column.
The Gotchas of `position: sticky has all the gotchas one should take into consideration.
TLDR;
- The immediate parent should have a taller
height
, or the effect won't be observed. - If you intend to get position sticky relative to the viewport, make shure that all ancestors relative to the element getting
position: sticky
don't haveoverflow
set.
<div class="overflow-auto"> <!-- overflow: auto -->
<div>
<div>
<div>
<div class="sticky-parent"> <!-- position: relative; height: 100% -->
<div class="sticky"> <!-- position: sticky, top: 0 -->
<p><em>This container won't get sticky at all because it has an ancestor with overflow property set to 'auto'.</em></p>
</div>
</div>
</div>
</div>
</div>
</div>