Skip to content

Back to Snippets

isCssContainingBlock()

Checks whether the specified DOM element is a CSS containing block for descendants of a certain position.

/*
	Checks whether a DOM Elementcan be the containing block for an element whose positioning is given by `position` (one of `static`, `relative`, `sticky`, `absolute`, `fixed`) and returns the reason why that's the case.
 */

function isCssContainingBlock(el, position = 'static') {

	const s = getComputedStyle(el);

	if (['static', 'relative', 'sticky'].includes(position)) {
		return ['block', 'inline-block', 'list-item', 'grid', 'inline-grid', 'flex', 'inline-flex', 'table', 'inline-table', 'flow-root'].includes(s.display) ? `display: ${s.display}` : false;
	}

	if (position === 'absolute' && s.position !== 'static') {
		return `position: ${s.position}`;
	}

	/* Code below applies to position: absolute, static */

	if (s.transform !== 'none') {
		return `transform: ${s.transform}`;
	}

	if (s.perspective !== 'none') {
		return `perspective: ${s.perspective}`;
	}

	const wc = s.willChange.split(',').map(it => it.trim());
	const wck = ['transform', 'perspective', 'filter'].find(k => wc.includes(k));
	if (wck) {
		return `will-change: ${wck}`;
	}

	if (s.filter !== 'none') {
		return `filter: ${s.filter}`;
	}

	if (CSS.supports('contain', 'none')) {
		if (s.contain.match(/\bpaint\b/)) {
			return `contain: paint`;
		}
	}

	if (s.backdropFilter !== 'none') {
		return `backdrop-filter: ${s.backdropFilter}`;
	}

	return false;
}