8

I understand that styles can be conditionally rendered such as:

const HelloWorldLabel= styled("div")<{ centered?: boolean }>`
  display: ${({ centered }) => (centered ? "block" : "flex")};;
  margin: ${({ centered }) => (centered ? "auto 0" : "unset")};
  padding: ${({ centered }) => (centered ? "0 15px" : "unset")};
`;

This does not look DRY - How can I (is it possible) render an entire block of css styles based on props?

Something like:

const HelloWorldLabel= styled("div")<{ centered?: boolean }>`
   if (centered) {
    display: "block" ;
    margin: $"auto 0";
     padding: "0 15px" ;
   } else {
     ......
   }
`;
Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
Null isTrue
  • 1,882
  • 6
  • 26
  • 46

4 Answers4

6

With styled-component, or any CSS-in-JS, you can conditionally render a css block:

import styled, { css } from 'styled-components';

const light = css`
  background-color: white;
  color: black;
`;

const dark = css`
  background-color: black;
  color: white;
`;

const Box = styled.div`
  ${({ isDark }) => (isDark ? light : dark)}
`;

Full Example:

import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import styled, { css } from 'styled-components';

const light = css`
  background-color: white;
  border: 2px solid black;
  color: black;
`;

const dark = css`
  background-color: black;
  color: white;
`;

const FlexBox = styled.div`
  margin: 20px;
  padding: 20px;
  ${({ isDark }) => (isDark ? light : dark)}
`;

const App = () => {
  const [isDark, setIsDark] = useState(false);

  const toggle = () => setIsDark(b => !b);

  return (
    <FlexBox isDark={isDark}>
      <div>Some Text</div>
      <button onClick={toggle}>Change Block</button>
    </FlexBox>
  );
};

ReactDOM.render(<App />, document.getElementById('root'));

Edit zen-https-5bkm5

Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
2

A less verbose way that worked for me is

const SideMenu = styled.aside`
  width: 200px;
  ${({ isHidden }) => isHidden && `
      display: none;
    `}
  // another random prop you need here
  ${({ redBg }) => redBg && `
    background-color: red;
  `}
`;
vaskort
  • 2,591
  • 2
  • 20
  • 29
1

You can use a function and return the css based on prop:

const HelloWorldLabel= styled("div")`
  ${({centered}) => {
    if (centered) {
      return `
       display: "block" ;
       margin: "auto 0";
       padding: "0 15px";
      `
    } else {
      return `// Other styles here`
    }
   }}
`;
Clarity
  • 10,730
  • 2
  • 25
  • 35
0

The alternative is

let customCss = setCustomCss(position) => {
let positionCss = {
center: [ 'css: value;', 'css:value;'],
left: .....
right: ....
}

return   return positionCss[position];

}
  let HelloWorldLabel= styled('div')(customCss, {
    /* css common to all */
  })
dorriz
  • 1,927
  • 3
  • 12
  • 19