ProNextJS
    Professional Next.js Course
    Loading price
    30-Day Money-Back Guarantee
    lesson

    Finish Styling with StyleX

    Jack HerringtonJack Herrington

    Let's apply the classes we defined in our StyleXCreate to our card:

    export default function Home() {
      return (
        <main {...stylex.props(s.main)}>
          {PRODUCTS.map((product) => (
            <div key={product.id} {...stylex.props(s.card)}>
              <ProductCard product={product} />
            </div>
          ))}
        </main>
      );
    }
    

    After making these changes, our layout is starting to take shape with a nice 3-card Monty layout.

    Three card layout

    Styling the Product Card

    Now let's tackle the styling of our ProductCard component. As before, we'll import the StyleX library and define our container queries for both vertical and horizontal orientations:

    // inside ProductCard.tsx
    import * as stylex from "@stylexjs/stylex";
    
    // ... at the bottom of the file:
    
    const SMALL = "@container (max-width: 450px)";
    const LARGE = "@container (min-width: 450px)";
    

    Then, we'll create all the necessary classes for our product card. You might notice that many of these classes look similar to what we've seen before, but as your styling becomes more complex, the amount of CSS required increases.

    One unique aspect of StyleX is that it doesn't allow the use of handy helpers like you might be used to for properties like border. Instead of using shorthand like border: 1px solid, StyleX requires granular control over each part of the style. This means you'll need to define the borderBottomWidth, borderBottomColor, and borderBottomStyle separately.

    Here's the full set of styles:

    const s = stylex.create({
      card: {
        containerType: "inline-size",
        width: "100%",
      },
      cardContainer: {
        display: "flex",
        width: "100%",
        flexDirection: {
          default: "row",
          [SMALL]: "column",
        },
      },
      imageContainer: {
        width: {
          default: "25%",
          [SMALL]: "100%",
        },
      },
      imageContainerImg: {
        width: "100%",
        height: "auto",
        borderTopRightRadius: {
          default: 0,
          [SMALL]: "1rem",
        },
        borderTopLeftRadius: "1rem",
        borderBottomLeftRadius: {
          default: 0,
          [LARGE]: "1rem",
        },
      },
      infoContainer: {
        width: {
          default: "75%",
          [SMALL]: "100%",
        },
    
        paddingLeft: "1rem",
    
        borderBottomWidth: 1,
        borderBottomColor: "#666",
        borderBottomStyle: "solid",
    
        borderRightWidth: 1,
        borderRightColor: "#666",
        borderRightStyle: "solid",
    
        borderBottomRightRadius: "1rem",
        borderBottomLeftRadius: {
          default: 0,
          [SMALL]: "1rem",
        },
        borderTopRightRadius: {
          default: 0,
          [LARGE]: "1rem",
        },
    
        borderTopWidth: {
          default: "inherit",
          [LARGE]: 1,
        },
        borderTopColor: {
          default: "inherit",
          [LARGE]: "#666",
        },
        borderTopStyle: {
          default: "inherit",
          [LARGE]: "solid",
        },
    
        borderLeftWidth: {
          default: "inherit",
          [SMALL]: 1,
        },
        borderLeftColor: {
          default: "inherit",
          [SMALL]: "#666",
        },
        borderLeftStyle: {
          default: "inherit",
          [SMALL]: "solid",
        },
      },
      title: {
        fontSize: "1.5rem",
        margin: "0",
        marginTop: "1rem",
      },
      price: {
        fontSize: "1rem",
        marginBottom: "1rem",
        fontStyle: "italic",
      },
    });
    
    const styles = StyleXCreate({
      card: {
        // ...
        borderBottomWidth: '1px',
        borderBottomColor: 'var(--border-color)',
        borderBottomStyle: 'solid',
        // ...
      },
    });
    

    This level of control can lead to more verbose CSS definitions, but it's part of what makes StyleX unique.

    Applying the Styles

    With our classes defined, let's apply them to the corresponding tags in our JSX:

    export const ProductCard = ({ product }: Props) => {
      return (
        <div {...stylex.props(s.card)}>
          <div {...stylex.props(s.cardContainer)}>
            <div {...stylex.props(s.imageContainer)}>
              <Image
                src={product.image}
                alt={product.title}
                width={300}
                height={300}
                {...stylex.props(s.imageContainerImg)}
              />
            </div>
            <div {...stylex.props(s.infoContainer)}>
              <h1 {...stylex.props(s.title)}>{product.title}</h1>
              <p {...stylex.props(s.price)}>{product.price}</p>
            </div>
          </div>
        </div>
      );
    };
    

    After hitting save, we'll see the styled set of cards as expected.

    When to Use StyleX

    Looking back at the code for this example project, it's important to note that this example isn't necessarily showcasing StyleX at its best. StyleX is designed for creating precisely controlled design systems, which is particularly useful for large companies like Meta.

    In those environments, you want a reliable design system with constraints. You might want to limit the modifications users can make to specific parts of a design element, like a button. StyleX allows you to define exactly which attributes of a button can be changed, which is a unique feature not found in other CSS libraries.

    If you're working on a design infrastructure team at a large company or on an open-source project where you want to define a controlled design system for third-party contributors, StyleX is definitely worth considering.

    However, developers coming from a CSS Modules or Tailwind background might find StyleX to be overly restrictive, like a "CSS straitjacket." But in larger environments, that level of control is often necessary.

    Transcript

    Picking up where we left off, we're going to go and take the main class that we defined down here in our StyleXCreate and apply it to our main tag. To do that, we use that prompts function that we got from StyleX and just apply the main class. Let's do the same thing for our div, but apply in that case the

    card class and we'll see what we get. All right, looking pretty good. We got our 3 card Monty layout. Fantastic. Okay, let's go and finish up by doing the same thing to our product card. Again, we're going to bring in the StyleX library. Then down below, we're going to define our container queries, vertical and horizontal, and then we're going to create all of our classes. Now, a lot of

    these look pretty similar to what we've seen before, but I got to say, as you go on, The styling is larger and larger and larger. And 1 thing in particular that's unique about StyleX, can't use those handy helpers like you would normally for something like, for example, Border. You can say

    Border 1PX solid like that. You can't use those. It wants complete controls. You need to literally granularly set each part of that. So that's why you get, for example, the border bottom with the border color, the border bottom color, the border bottom style as separate callouts. But it does

    kind of bulk out the CSS definition. All right, now let's go and apply these to the actual tags. Hit save. There we go. Now looking back at the code, I got to say I'm not really showing StyleX at its best.

    What StyleX is really designed for is to create design systems that are very precisely controlled. If you're working at a company at the size of Meta, you want to have a reliable design system that is constrained. You want your users only to be able to change the parts and the pieces of

    that design element, say a button, that you want them to actually change. So if you only want them to change the button, background color, or some other attribute, you can do that in the style. X is a unique feature of style X that no other CSS library

    that I know has. But that ability and that specificity I think makes it a bit harder to imagine using this on a smaller project. That's why I think in general, StyleX if you're working in the design infrastructure team of a large company,

    StyleX is something you want to take a look at. Or if you're working on an open source project where you want to define a design system for that open source project, where you're going to have third-party contributors come in and use it, and you want that to be very precisely controlled, I think that's another excellent use case for StyleX. But I do

    understand that a lot of folks who come out of, for example, the CSS module world or the Tailwind world look at Stylex and think it's the equivalent of a CSS straightjacket because it it kind of honestly is and that's the kind of thing you would need in larger environments.