The parent selector is in Safari from March and in nothing else during 2022, so styling a container based on its contents is still JavaScript.
/* Safari 15.4+ only, in 2022 */
.field:has(input:invalid) { border-color: red; }
/* what everybody actually ships */
.field.is-invalid { border-color: red; }
/* plus the JavaScript that has to keep the class in sync,
which is the cost — a state that exists in the DOM and
in a class name, and can disagree */
Keeping a class in sync with a state that the DOM already knows is a genuine source of bugs, and it is the whole reason the selector was wanted. Progressive enhancement is possible — use :has() where supported and the class everywhere — and it means maintaining both, which is worse than picking one until support arrives.