:has() does not exist yet, and the class you add instead

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.