Here you go...
For sticky first column (horizontal):
.ms-DetailsHeader-cell:first-child {
position: sticky;
inset: 0;
background-color: white;
z-index: 2;
}
.ms-DetailsRow-cell:first-child {
position: sticky;
inset: 0;
background-color: white;
z-index: 1;
}
For sticky column header (vertical):
const scrollClass = mergeStyleSets({
detailsListWrapper: {
height: '320px',
width: '100%',
position: 'relative'
},
});
<Stack horizontal className={scrollClass.detailsListWrapper}>
<Stack.Item>
<ScrollablePane scrollbarVisibility={ScrollbarVisibility.auto} >
<Shimmer customElementsGroup={getShimmerData(4)} width="300" height="400" isDataLoaded={!dataLoading}>
<DetailsList
items={entities}
compact={isCompactMode}
columns={columns}
selectionMode={SelectionMode.single}
getKey={this._getKey}
setKey="single"
layoutMode={DetailsListLayoutMode.justified}
constrainMode={ConstrainMode.unconstrained}
isHeaderVisible={true}
selection={this._selection}
selectionPreservedOnEmptyClick={true}
onItemInvoked={this._onItemInvoked}
enterModalSelectionOnTouch={true}
ariaLabelForSelectionColumn="Toggle selection"
ariaLabelForSelectAllCheckbox="Toggle selection for all items"
checkButtonAriaLabel="select row"
onRenderDetailsHeader={this._renderFixedDetailsHeader}
styles={{ contentWrapper: { cursor: "pointer", width: '100%' } }}
/>
</Shimmer>
</ScrollablePane>
</Stack.Item>
</Stack >
private _renderFixedDetailsHeader: IRenderFunction<IDetailsHeaderProps> = (props, defaultRender) => {
if (!props) {
return null;
}
const onRenderColumnHeaderTooltip: IRenderFunction<IDetailsColumnRenderTooltipProps> =
tooltipHostProps => (
<TooltipHost {...tooltipHostProps} />
);
return (
<Sticky stickyPosition={StickyPositionType.Header} isScrollSynced>
{defaultRender!({
...props,
onRenderColumnHeaderTooltip,
})}
</Sticky>
);
}