1 | # CSS Has Pseudo [<img src="http://jonathantneal.github.io/js-logo.svg" alt="" width="90" height="90" align="right">][CSS Has Pseudo]
|
---|
2 |
|
---|
3 | [![NPM Version][npm-img]][npm-url]
|
---|
4 | [![Build Status][cli-img]][cli-url]
|
---|
5 | [![Support Chat][git-img]][git-url]
|
---|
6 |
|
---|
7 | [CSS Has Pseudo] lets you style elements relative to other elements in CSS,
|
---|
8 | following the [Selectors Level 4] specification.
|
---|
9 |
|
---|
10 | ```css
|
---|
11 | a:has(> img) {
|
---|
12 | /* style links that contain an image */
|
---|
13 | }
|
---|
14 |
|
---|
15 | h1:has(+ p) {
|
---|
16 | /* style level 1 headings that are followed by a paragraph */
|
---|
17 | }
|
---|
18 |
|
---|
19 | section:not(:has(h1, h2, h3, h4, h5, h6)) {
|
---|
20 | /* style sections that don’t contain any heading elements */
|
---|
21 | }
|
---|
22 |
|
---|
23 | body:has(:focus) {
|
---|
24 | /* style the body if it contains a focused element */
|
---|
25 | }
|
---|
26 | ```
|
---|
27 |
|
---|
28 | ## Usage
|
---|
29 |
|
---|
30 | From the command line, transform CSS files that use `:has` selectors:
|
---|
31 |
|
---|
32 | ```bash
|
---|
33 | npx css-has-pseudo SOURCE.css TRANSFORMED.css
|
---|
34 | ```
|
---|
35 |
|
---|
36 | Next, use your transformed CSS with this script:
|
---|
37 |
|
---|
38 | ```html
|
---|
39 | <link rel="stylesheet" href="TRANSFORMED.css">
|
---|
40 | <script src="https://unpkg.com/css-has-pseudo/browser"></script>
|
---|
41 | <script>cssHasPseudo(document)</script>
|
---|
42 | ```
|
---|
43 |
|
---|
44 | That’s it. The script is 765 bytes and works in all browsers, including
|
---|
45 | Internet Explorer 11. With a [Mutation Observer polyfill], the script will work
|
---|
46 | down to Internet Explorer 9.
|
---|
47 |
|
---|
48 | ## How it works
|
---|
49 |
|
---|
50 | The [PostCSS plugin](README-POSTCSS.md) clones rules containing `:has`,
|
---|
51 | replacing them with an alternative `[:has]` selector.
|
---|
52 |
|
---|
53 | ```css
|
---|
54 | body:has(:focus) {
|
---|
55 | background-color: yellow;
|
---|
56 | }
|
---|
57 |
|
---|
58 | section:not(:has(h1, h2, h3, h4, h5, h6)) {
|
---|
59 | background-color: gray;
|
---|
60 | }
|
---|
61 |
|
---|
62 | /* becomes */
|
---|
63 |
|
---|
64 | body[\:has\(\:focus\)] {
|
---|
65 | background-color: yellow;
|
---|
66 | }
|
---|
67 |
|
---|
68 | body:has(:focus) {
|
---|
69 | background-color: yellow;
|
---|
70 | }
|
---|
71 |
|
---|
72 | section[\:not-has\(h1\,\%20h2\,\%20h3\,\%20h4\,\%20h5\,\%20h6\)] {
|
---|
73 | background-color: gray;
|
---|
74 | }
|
---|
75 |
|
---|
76 | section:not(:has(h1, h2, h3, h4, h5, h6)) {
|
---|
77 | background-color: gray;
|
---|
78 | }
|
---|
79 | ```
|
---|
80 |
|
---|
81 | Next, the [JavaScript library](README-BROWSER.md) adds a `[:has]` attribute to
|
---|
82 | elements otherwise matching `:has` natively.
|
---|
83 |
|
---|
84 | ```html
|
---|
85 | <body :has(:focus)>
|
---|
86 | <input value="This element is focused">
|
---|
87 | </body>
|
---|
88 | ```
|
---|
89 |
|
---|
90 | [cli-img]: https://img.shields.io/travis/csstools/css-has-pseudo/master.svg
|
---|
91 | [cli-url]: https://travis-ci.org/csstools/css-has-pseudo
|
---|
92 | [git-img]: https://img.shields.io/badge/support-chat-blue.svg
|
---|
93 | [git-url]: https://gitter.im/postcss/postcss
|
---|
94 | [npm-img]: https://img.shields.io/npm/v/css-has-pseudo.svg
|
---|
95 | [npm-url]: https://www.npmjs.com/package/css-has-pseudo
|
---|
96 |
|
---|
97 | [CSS Has Pseudo]: https://github.com/csstools/css-has-pseudo
|
---|
98 | [Mutation Observer polyfill]: https://github.com/webmodules/mutation-observer
|
---|
99 | [Selectors Level 4]: https://drafts.csswg.org/selectors-4/#has-pseudo
|
---|