LogoLogo
HomeGitHubPlayground
v4
v4
  • ๐Ÿ”งSetup
  • ๐Ÿ”API References
    • tss - the Modern API
    • keyframes
    • <GlobalStyles />
    • makeStyles -> useStyles
    • withStyles
  • โšกSSR
    • Next.js
    • Gatsby
    • Other backends
  • ๐ŸŽฏIncrease specificity
  • ๐Ÿฆฑclasses overrides
  • ๐ŸงนDetecting unused classes
  • ๐Ÿ’ฝEmotion Cache
  • ๐Ÿ’ซNested selectors (ex $ syntax)
  • ๐ŸญMUI Global styleOverrides
  • ๐Ÿ“ฆPublish a module that uses TSS
  • ๐ŸฉณMUI sx syntax
  • ๐Ÿ“ฒReact Native
  • ๐Ÿ†˜Fix broken styles after upgrading to MUI v5 with TSS
  • โฌ†๏ธMigration v3 -> v4
Powered by GitBook
On this page
  • With the Modern API and makeStyles API
  • withStyles
  • SSR

Was this helpful?

Edit on GitHub

Nested selectors (ex $ syntax)

tss-react unlike jss-react doesn't support the $ syntax but is a better alternative.

With the Modern API and makeStyles API

In JSS you can do:

//WARNING: This is legacy JSS code!
{
  parent: {
      padding: 30,
      "&:hover $child": { // <- This do not work in TSS
          backgroundColor: "red"
      },
  },
  child: {
      backgroundColor: "blue"
  }
}
//...
<div className={classes.parent}>
    <div className={classes.child}>
        Background turns red when the mouse is hovering over the parent
    </div>
</div>

This is how you would achieve the same result with tss-react

export function MyComponent() {
    const { classes } = useStyles();

    return (
        <div className={classes.parent}>
            <div className={classes.child}>
                Background turns red when the mouse is hovering over the parent.
            </div>
        </div>
    );
}

const useStyles = tss
    .withName("MyComponent") // It's important to set a name in SSR setups
    .withNestedSelectors<"child">()
    .create(({ classes }) => ({
        parent: {
            padding: 30,
            [`&:hover .${classes.child}`]: {
                backgroundColor: "red"
            }
        },
        child: {
            backgroundColor: "blue"
        },
    }));

Another example:

export function MyComponent() {
    const { classes, cx } = useStyles({ color: "primary" });

    return (
        <div className={classes.root}>
            <div className={classes.child}>
                The Background takes the primary theme color when the mouse is
                hovering over the parent.
            </div>
            <div className={cx(classes.child, classes.small)}>
                The Background takes the primary theme color when the mouse is
                hovering over the parent. I am smaller than the other child.
            </div>
        </div>
    );
}

const useStyles = tss
    .withName("MyComponent") 
    .withNestedSelectors<"child" | "small">()
    .withParams<{ color: "primary" | "secondary" }>()
    .create(({ theme, color, classes })=> ({
        root: {
            padding: 30,
            [`&:hover .${classes.child}`]: {
                backgroundColor: theme.palette[color].main
            }
        },
        small: {},
        child: {
            border: "1px solid black",
            height: 50,
            [`&.${classes.small}`]: {
                height: 30
            }
        }
    }));
export function App() {
    const { classes } = useStyles();

    return (
        <div className={classes.parent}>
            <div className={classes.child}>
                Background turns red when the mouse is hovering over the parent.
            </div>
        </div>
    );
}

const useStyles = makeStyles<void, "child">({
  uniqId: "QnWmDL" // In SSR setups, you must give an unique id to all
                   // your useStyles that uses nested selectors.
                   // See below for mor infos.  
})(
    (_theme, _params, classes) => ({
        "parent": {
            "padding": 30,
            [`&:hover .${classes.child}`]: {
                "backgroundColor": "red"
            }
        },
        "child": {
            "backgroundColor": "blue"
        },
    })
);

Another example:

export function App() {
    const { classes, cx } = useStyles({ "color": "primary" });

    return (
        <div className={classes.root}>
            <div className={classes.child}>
                The Background takes the primary theme color when the mouse is
                hovering over the parent.
            </div>
            <div className={cx(classes.child, classes.small)}>
                The Background takes the primary theme color when the mouse is
                hovering over the parent. I am smaller than the other child.
            </div>
        </div>
    );
}

const useStyles = makeStyles<
    { color: "primary" | "secondary" },
    "child" | "small"
>({
  uniqId: "GnWmDK"
})((theme, { color }, classes) => ({
    "root": {
        "padding": 30,
        [`&:hover .${classes.child}`]: {
            "backgroundColor": theme.palette[color].main
        }
    },
    "small": {},
    "child": {
        "border": "1px solid black",
        "height": 50,
        [`&.${classes.small}`]: {
            "height": 30
        }
    }
}));

withStyles

SSR

NOTE: This does not apply to the Modern API, only for makeStyles and withStyles

In SSR setups, on stylesheets using nested selectors, you could end up with warnings like:

Warning: Prop className did not match. Server: "tss-XXX-root-ref" Client: "tss-YYY-root-ref".

You can fix this error by providing a unique id when calling makeStyles or withStyles (It will set XXX and YYY).

 const useStyles = makeStyles<
     { color: "primary" | "secondary" },
     "child" | "small"
 >({
     name: "MyComponent"
+    uniqId: "QnWmDL"
 })((theme, { color }, classes) => ({
     "root": {
         "padding": 30,
         [`&:hover .${classes.child}`]: {
             "backgroundColor": theme.palette[color].main
         }
     },
     "small": {},
     "child": {
         "border": "1px solid black",
         "height": 50,
         [`&.${classes.small}`]: {
             "height": 30
         }
     }
 }));
 
  const MyBreadcrumbs = withStyles(
     Breadcrumbs,
     (theme, _props, classes) => ({
         "ol": {
             [`& .${classes.separator}`]: {
                 "color": theme.palette.primary.main
             }
         }
     }), 
     {
          name: "MyBreadcrumbs",
+         uniqId: "vZHt3n" 
     }
 );

withStyles:

 const MyDiv = withStyles("div", {
   "root": {
     /* ... */
   }
 }, { 
   name: "MyDiv",
+  uniqId: "xDTt4n"
 });
PreviousEmotion CacheNextMUI Global styleOverrides

Last updated 8 months ago

Was this helpful?

WARNING: Nested selectors requires support which . It can't be polyfilled ( will not work) but don't worry, if Proxy is not available on a particular browser, no error will be thrown and TSS will still do its work. Only nested selectors won't work.

Short unique identifiers can be generated with .

๐Ÿ’ซ
ES6 Proxy
IE doesn't support
this
this website
The render of the above code
Example of error you may run against with Next.js