|
| 1 | +# GitHub Copilot Instructions for CSS if() Polyfill |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +This is a JavaScript polyfill and PostCSS plugin for [CSS if() functionality](https://developer.mozilla.org/en-US/docs/Web/CSS/if). The polyfill provides browser support for the CSS if() function with style(), media(), and supports() conditions as specified in the WCAG (Web Content Accessibility Guidelines). |
| 6 | + |
| 7 | +## Official WCAG CSS if() Function Specification |
| 8 | + |
| 9 | +8.3. Conditional Value Selection: the if() notation |
| 10 | +The if() function is an arbitrary substitution function that represents conditional values. Its argument consists of an ordered semi-colon–separated list of statements, each consisting of a condition followed by a colon followed by a value. An if() function represents the value corresponding to the first condition in its argument list to be true; if no condition matches, then the if() function represents an empty token stream. |
| 11 | + |
| 12 | +The if() function’s syntax is defined as follows: |
| 13 | + |
| 14 | +<if()> = if( [ <if-branch> ; ]\* <if-branch> ;? ) |
| 15 | +<if-branch> = <if-condition> : <declaration-value>? |
| 16 | +<if-condition> = <boolean-expr[ <if-test> ]> | else |
| 17 | +<if-test> = |
| 18 | +supports( [ <ident> : <declaration-value> ] | <supports-condition> ) | |
| 19 | +media( <media-feature> | <media-condition> ) | |
| 20 | +style( <style-query> ) |
| 21 | +The else keyword represents a condition that is always true. |
| 22 | + |
| 23 | +The if() function’s argument grammar is: |
| 24 | + |
| 25 | +<if-args> = if( [ <if-args-branch> ; ]\* <if-args-branch> ;? ) |
| 26 | +<if-args-branch> = <declaration-value> : <declaration-value>? |
| 27 | +To replace an if() function, given a list of arguments: |
| 28 | +For each <if-args-branch> branch in arguments: |
| 29 | + |
| 30 | +Substitute arbitrary substitution functions in the first <declaration-value> of branch, then parse the result as an <if-condition>. If parsing returns failure, continue; otherwise, let the result be condition. |
| 31 | + |
| 32 | +Evaluate condition. |
| 33 | + |
| 34 | +If a <style-query> in condition tests the value of a property, and guarding a substitution context «"property", referenced-property-name» would mark it as a cyclic substitution context, that query evaluates to false. |
| 35 | + |
| 36 | +For example, in --foo: if(style(--foo: bar): baz); the style() query is automatically false, since property replacement has already established a «"property", "--foo"» substitution context. |
| 37 | +If the result of condition is false, continue. |
| 38 | + |
| 39 | +Substitute arbitrary substitution functions in the second <declaration-value> of branch, and return the result. |
| 40 | + |
| 41 | +Return nothing (an empty sequence of component values). |
| 42 | + |
| 43 | +Note: Unlike using @media/@supports/@container rules, which just ignore their contents when they’re false and let the cascade determine what values otherwise apply, declarations with if() do not roll back the cascade if the conditions are false; any fallback values must be provided inline. However, see the revert-rule CSS-wide keyword. |
| 44 | + |
| 45 | +## Project Structure and Key Components |
| 46 | + |
| 47 | +### Core Packages |
| 48 | + |
| 49 | +- `packages/css-if-polyfill/` - Main JavaScript polyfill |
| 50 | +- `packages/postcss-if-function/` - PostCSS plugin for build-time transformation |
| 51 | + |
| 52 | +### Key Files |
| 53 | + |
| 54 | +- `packages/css-if-polyfill/src/index.js` - Main polyfill runtime |
| 55 | +- `packages/css-if-polyfill/src/transform.js` - CSS transformation logic |
| 56 | +- `test/fixtures/` - CSS test fixture pairs (_.input.css / _.expected.css) |
| 57 | +- `test/fixtures-validation/` - Playwright-based browser validation tests |
| 58 | + |
| 59 | +### Testing Infrastructure |
| 60 | + |
| 61 | +- Vitest for unit tests |
| 62 | +- Playwright for browser-based fixture validation |
| 63 | +- XO for linting (strict ESLint configuration) |
| 64 | + |
| 65 | +## Syntax Rules and Implementation Guidelines |
| 66 | + |
| 67 | +### CSS if() Function Syntax |
| 68 | + |
| 69 | +When working with CSS if() functions, always follow the official WCAG specification syntax as included in the previous section "Official WCAG CSS if() Function Specification". |
| 70 | + |
| 71 | +### Code Style Requirements |
| 72 | + |
| 73 | +- Use ES modules with modern JavaScript syntax |
| 74 | +- Follow XO linting rules (extends ESLint strict configuration) |
| 75 | +- Use `/* eslint-disable rule-name */` blocks only when necessary for browser automation |
| 76 | +- Prefer functional programming patterns |
| 77 | +- Use meaningful variable names and comprehensive JSDoc comments |
| 78 | + |
| 79 | +### Testing Requirements |
| 80 | + |
| 81 | +- All new CSS syntax must have corresponding fixture pairs in `test/fixtures/` |
| 82 | +- Fixture files must follow naming convention: `name.input.css` / `name.expected.css` |
| 83 | +- Browser validation tests must pass in Chromium, Firefox, and WebKit |
| 84 | +- Unit tests should cover edge cases and error conditions |
| 85 | + |
| 86 | +### Browser Compatibility |
| 87 | + |
| 88 | +- Support modern browsers with ES module capability |
| 89 | +- Graceful degradation for older browsers via UMD build |
| 90 | +- Auto-initialization in browser environments |
| 91 | +- Clean cleanup of event listeners and observers |
| 92 | + |
| 93 | +## Development Workflow |
| 94 | + |
| 95 | +1. **CSS Syntax Changes**: Update both polyfill logic and PostCSS plugin |
| 96 | +2. **New Features**: Add fixture tests first, then implement functionality |
| 97 | +3. **Bug Fixes**: Create minimal reproduction test case before fixing |
| 98 | +4. **Performance**: Profile with large CSS files and many DOM elements |
| 99 | + |
| 100 | +## Important Implementation Notes |
| 101 | + |
| 102 | +### Polyfill Behavior |
| 103 | + |
| 104 | +- Must evaluate conditions at runtime based on current browser state |
| 105 | +- Should handle dynamic viewport changes for media queries |
| 106 | +- Must respect CSS cascade and specificity rules |
| 107 | +- Should not interfere with native CSS if() support when available |
| 108 | + |
| 109 | +### Error Handling |
| 110 | + |
| 111 | +- Debug mode should provide helpful error messages |
| 112 | +- Should not break page rendering on malformed CSS |
| 113 | + |
| 114 | +### Performance Considerations |
| 115 | + |
| 116 | +- Minimize DOM queries and style recalculations |
| 117 | +- Cache compiled CSS transformations when possible |
| 118 | + |
| 119 | +## File Naming and Organization |
| 120 | + |
| 121 | +- Use kebab-case for files and directories |
| 122 | +- Suffix test files with `.test.js` |
| 123 | +- Suffix fixture files with `.input.css` / `.expected.css` |
| 124 | +- Group related functionality in dedicated directories |
| 125 | +- Keep configuration files at appropriate levels (root, package, or feature-specific) |
| 126 | + |
| 127 | +## When Making Changes |
| 128 | + |
| 129 | +1. **Always** check the WCAG specification above for syntax correctness |
| 130 | +2. **Always** add fixture tests for new CSS functionality |
| 131 | +3. **Always** run the full test suite including browser validation |
| 132 | +4. **Always** update documentation when changing public APIs |
| 133 | +5. **Consider** performance impact on large stylesheets and DOM trees |
| 134 | + |
| 135 | +This project aims to provide a complete, specification-compliant implementation of CSS if() functionality for browsers that don't yet support it natively. |
0 commit comments