[6a3a178] | 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
|
---|