stylex.when.*
A suite of APIs for creating descendant and sibling selectors. These APIs allow you to style an element based on the state of its ancestors, descendants, or siblings in the DOM tree. You can only observe a pseudo-class state (:hover, :focus, etc.) on an element that has been marked with a marker class.
Lookahead selectors (stylex.when.siblingAfter, stylex.when.anySibling, and stylex.when.descendant) rely on the CSS :has() selector, which does not yet have widespread browser support.
Using Markers
To use descendant and sibling selectors, you must mark the ancestor, sibling, or descendant node being observed by passing the stylex.defaultMarker() class name.
import * as stylex from '@stylexjs/stylex';
const styles = stylex.create({
foo: {
backgroundColor: {
default: 'blue',
[stylex.when.ancestor(':hover')]: 'red',
},
},
});
<div {...stylex.props(stylex.defaultMarker())}>
<div {...stylex.props(styles.foo)}> Some Content </div>
</div>
Available Selectors
stylex.when.ancestor
Styles an element based on the state of an ancestor element in the DOM tree.
function ancestor(pseudoSelector: string, marker?: Marker): string;
Example use:
import * as stylex from '@stylexjs/stylex';
const styles = stylex.create({
card: {
transform: {
default: 'translateX(0)',
[stylex.when.ancestor(':hover')]: 'translateX(10px)',
},
},
});
<div {...stylex.props(stylex.defaultMarker())}>
<div {...stylex.props(styles.card)}>Hover the parent to move me</div>
</div>
stylex.when.descendant
Styles an element based on the state of a descendant element in the DOM tree.
function descendant(pseudoSelector: string, marker?: Marker): string;
Example use:
import * as stylex from '@stylexjs/stylex';
const styles = stylex.create({
container: {
borderColor: {
default: 'gray',
[stylex.when.descendant(':focus')]: 'blue',
},
},
});
<div {...stylex.props(styles.container)}>
<input {...stylex.props(stylex.defaultMarker())} />
</div>
stylex.when.anySibling
Styles an element based on the state of any sibling element (before or after).
function anySibling(pseudoSelector: string, marker?: Marker): string;
Example use:
import * as stylex from '@stylexjs/stylex';
const styles = stylex.create({
tab: {
opacity: {
default: 1,
[stylex.when.anySibling(':hover')]: 0.7,
},
},
});
<>
<div {...stylex.props(styles.tab, stylex.defaultMarker())}>Tab 1</div>
<div {...stylex.props(styles.tab, stylex.defaultMarker())}>Tab 2</div>
<div {...stylex.props(styles.tab, stylex.defaultMarker())}>Tab 3</div>
</>
stylex.when.siblingBefore
Styles an element based on the state of a preceding sibling element.
function siblingBefore(pseudoSelector: string, marker?: Marker): string;
Example use:
import * as stylex from '@stylexjs/stylex';
const styles = stylex.create({
item: {
backgroundColor: {
default: 'white',
[stylex.when.siblingBefore(':focus')]: 'lightblue',
},
},
});
<>
<button {...stylex.props(stylex.defaultMarker())}>Focus me</button>
<div {...stylex.props(styles.item)}>I change when button is focused</div>
</>
stylex.when.siblingAfter
Styles an element based on the state of a following sibling element.
function siblingAfter(pseudoSelector: string, marker?: Marker): string;
Example use:
import * as stylex from '@stylexjs/stylex';
const styles = stylex.create({
label: {
color: {
default: 'black',
[stylex.when.siblingAfter(':focus')]: 'blue',
},
},
});
<>
<label {...stylex.props(styles.label)}>Name</label>
<input {...stylex.props(stylex.defaultMarker())} />
</>
Using Custom Markers
Support for custom markers created with stylex.defineMarker() allows you to have multiple independent sets of contextual selectors in the same component tree.
import * as stylex from '@stylexjs/stylex';
import { cardMarker, headingMarker } from './markers.stylex.js';
const styles = stylex.create({
heading: {
transform: {
default: 'translateX(0)',
[stylex.when.ancestor(':hover', cardMarker)]: 'translateX(10px)',
[stylex.when.ancestor(':hover', headingMarker)]: 'translateX(4px)',
},
},
});
<div {...stylex.props(cardMarker)}>
<h2 {...stylex.props(headingMarker)}>
<span {...stylex.props(styles.heading)}>Title</span>
</h2>
</div>
Specificity Ranking
stylex.when.* selectors have lower priority than regular pseudo-classes or media queries. When multiple stylex.when.* selectors apply to the same element, they are ordered by specificity. The sort-keys ESLint rule enforces this order:
ancestor(lowest specificity)descendantanySiblingsiblingBeforesiblingAfter(highest specificity)