0

I am building a web application in ReactJS. I have the following:

const MyComponent = (props: { array: Array<Data> }) => {
    const styles = mergeStyleSets({
        container: {
            backgroundColor: transparent,
        },
        item: {
            backgroundColor: "#ccc",
        },
        itemContent: {
            color: "#000",
        },
    });

    return (
        <div class={styles.container}>
            {props.array.map((x, i) => (
                <div key={i} class={styles.item}>
                    <div class={styles.itemContent}></div>
                </div>
            ))}
        </div>
    )
};

This will render a container with some items in it all with the same background and same text color.

More complex selectors

Now I want to have alternating backgrounds and colors, therefore I try to use nth-child(odd) and get a different backgroundColor and color for odd items:

const styles = mergeStyleSets({
    container: {
        backgroundColor: transparent,
    },
    item: {
        backgroundColor: #ccc,
        selectors: {
            ":nth-child(odd)": {
                backgroundColor: "#ddd",
                selectors: {
                    itemContent: {
                        color: "#fff",
                    },
                },
            },
        },
    },
    itemContent: {
        color: "#000",
    },
});

As you can see, I need to reference class itemContent inside the selector of item. But my solution is not working. How can I achieve this?

Andry
  • 16,172
  • 27
  • 138
  • 246

1 Answers1

0

Simple elegant solution

You can give each row default style and override the odd ones. The following snippet showcases it on color prop.

function App() {
  const styles = mergeStyleSets({
    item: {
      // Default styles.
      backgroundColor: '#ccc',
      color: "black",
      // Override odd rows.
      ":nth-child(odd)": {
        backgroundColor: "#ddd",
        color: "red",
      },
    },
  })

  return (
    <>
      {[1, 2, 3, 4, 5, 6, 7, 8, 9].map(x => (
        <div key={x} className={styles.item}>
          <div>{x}</div>
        </div>
      ))}
    </>
  )
}

Other (IMO less elegant) solutions

You need to decide whether you want to stick with CSS or JS part. If you want to go for CSS, it would look like this:

function App() {
  const styles = mergeStyleSets({
    item: {
      backgroundColor: '#ccc',
      ":nth-child(odd)": {
        backgroundColor: "#ddd",
        color: "red",
        '>div': { // Select all direct divs of odd items.
          color: "red",
        },
      },
    },
  })

  return (
    <>
      {[1, 2, 3, 4, 5, 6, 7, 8, 9].map(x => (
        <div key={x} className={styles.item}>
          <div>{x}</div>
        </div>
      ))}
    </>
  )
}

Going for JS solution would be manually checking if index is even or odd and applying CSS class accordingly.

function App() {
  const styles = mergeStyleSets({
    item: {
      backgroundColor: '#ccc',
      ":nth-child(odd)": {
        backgroundColor: "#ddd",
      },
    },
    odd: {
      color: "red",
    },
    even: {
      color: 'initial'
    }
  })

  return (
    <>
      {[1, 2, 3, 4, 5, 6, 7, 8, 9].map((x, i) => (
        <div key={x} className={styles.item}>
          <div className={i % 2 === 0 ? styles.odd : styles.even}>{x}</div>
        </div>
      ))}
    </>
  )
}

Note

Newer Fluent versions do not require using selectors keyword anymore.

MartinT
  • 590
  • 5
  • 21