Skip to main content

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.

Browser Support

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:

  1. ancestor (lowest specificity)
  2. descendant
  3. anySibling
  4. siblingBefore
  5. siblingAfter (highest specificity)