How would I use CSS to style all elements that are not images? I tried using
body:not(img) {
filter: grayscale(1);
}
but this does not work.
A greyscale filter on any element will apply to all its contents. So your selector not only needs to exclude images, it also needs to exclude elements which have an image descendant. This is the selector you need:
:not(img, :has(img))
Here is a snippet to demonstrate this working. Images, whether they are children of the body or deeper in the document hierarchy, remain in colour, while the rest of the document becomes greyscale. Tested in Chrome, Safari and Firefox on Mac.
.p1 {
color: red;
}
.p2 {
background: linear-gradient(90deg, rgba(110,229,255,1) 0%, rgba(192,118,255,1) 100%);
}
:not(img, :has(img)) {
filter: grayscale(1);
}
a {
text-decoration: none;
}
<p>This is black</p>
<p class="p1">This is red</p>
<p class="p2">This has a blue gradient background</p>
<a href="https://this-page-intentionally-left-blank.org">
<img src="http://picsum.photos/id/840/120">
</a>
<img src="http://picsum.photos/id/845/120">
<div>
<a href="https://this-page-intentionally-left-blank.org">
<img src="http://picsum.photos/id/840/120">
</a>
<img src="http://picsum.photos/id/845/120">
</div>