if statement inside styled component
Asked Answered
Z

8

8
export enum SizeEnum {
    Small,
    Large
}

export interface ICheckbox {
    Size: SizeEnum;
}

const Box = styled.div`
    height: 20px;
    width: 20px;
`

In the above code I want to be able to conditionally change the height and width value of <Box> based on the prop. How do I do this?

Zirkle answered 10/4, 2018 at 5:0 Comment(0)
U
24

Another way to do this, if you want to add several css styles.

import css from "styled-jsx/css";


const Box = styled.div`
    height:100px;
    width:100px;
    ${props => props.Size === 'Small' && css`
         height:20px;
         width:20px;
    `}
`
Uncinariasis answered 14/4, 2020 at 8:35 Comment(1)
These are all good answers, I wanted to give you a vote since there's no best way to do this as far as the three examples I see hereDredger
B
15

See Logical Operators and Adapting based on props for more info.

// Box.
const Box = styled.div`

  height: ${({Size}) => 
    Size === 'Small' && '25px' ||
    Size === 'Large' && '100px' || 
    '50px'
  };

  width: ${({Size}) => 
    Size === 'Small' && '25px' || 
    Size === 'Large' && '100px' || 
    '50px'
  };

`

// Render.
<Box/> // 50px - Normal.
<Box Size="Small"/> // 25px - Small.
<Box Size="Large"/> // 100px - Large.
Bounce answered 10/4, 2018 at 5:25 Comment(2)
when i do that i get a typescript error [ts] Property 'Size' does not exist on type 'ThemedStyledProps<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, any>'.Zirkle
That's a TypeScript issue. This link might help.Bounce
Z
6

You can use the ternary operator

const Box = styled.div`
height: ${props => props.Size === 'Small' ? '20px' : '40px'}
width: ${props => props.Size === 'Small' ? '20px' : '40px'}
`

Reference: https://www.styled-components.com/docs/basics

Zygotene answered 10/4, 2018 at 5:28 Comment(3)
Throws error in TypeScript [ts] Property 'Size' does not exist on type 'ThemedStyledProps<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, any>'Zirkle
I don't know much about typescript but you can try by changing attribute name size --> deviceSize/ device-sizeZygotene
ZeroDarkThirty, to solve this you should create an prop interface. interface Props { Size: string } and you should use on element const Box = styled.div<Props>` height: ${props => props.Size === 'Small' ? '20px' : '40px'} width: ${props => props.Size === 'Small' ? '20px' : '40px'} `Previdi
C
3

You can use the elvis operator in something like this:

${(props) => props.someValue ? css` width: 20px;` : css` width: 100px; `}

Hope this helps someone looking into how to use logical operators in React styled components.

Clinquant answered 16/11, 2020 at 12:19 Comment(0)
M
2

We can add the if-checks just like jsx

const Box = styled.div`
    height:100px;
    width:100px;
    ${props => props.Size === 'Small' && `
         height:20px;
         width:20px;
    `}
` 

Note: No need to include the word css

Melisamelisande answered 2/10, 2020 at 5:39 Comment(2)
You want the css`` for syntax highlight :|Reiterate
In the official docs, they are not mentioning the css``. styled-components.com/docs/basics#adapting-based-on-propsMelisamelisande
N
1

You can add interface in TypeScript and use booleans for default, small and large boxes. This example is for those who has more than two choices. In case of two choices, I would use arrow function and ? : operators.

interface Sizes { 
  small?: boolean, 
  large?: boolean 
}

// Box.
const Box = styled.div<Sizes>`
  // p in this case means parameter which can have small and large booleans
  height: ${p => 
    (p.small && '25px') ||
    (large && '100px') || 
    '50px'
  };

  width: ${({Size}) => 
    (small && '25px') || 
    (large && '100px') || 
    '50px'
  };

`

// Render.
<Box/> // 50px - Normal.
<Box small/> // 25px - Small.
<Box large/> // 100px - Large.
Neotropical answered 21/9, 2021 at 17:14 Comment(0)
P
1

Actual if/else syntax may be used as well, what matters is, the returned value should be a string:

const DrawerItemTitle = styled.div<{isExpanded: boolean}>(props => {
    const baseStyles = `
        white-space: nowrap;
    `;
    const expandedStyles = baseStyles + `
        opacity: 1;
        transition: opacity 0.4s;
        text-align: center;
        flex-grow: 1;`
    const notExpandedStyles = baseStyles + `
        opacity: 0;
        transition: opacity 0s;
        position: absolute;
        width: 100%;
    `;

    if(props.isExpanded) {
        return expandedStyles; 
    }
    else { 
        return notExpandedStyles;
    }
);
Plumbago answered 15/2, 2023 at 20:27 Comment(0)
U
0

Get rid of all IFs

I know that this question is pretty old but I would like to contribute with one suggestion

Lately I've come up with a pattern to compute the value using an object, I think this ended up being pretty interesting!

// types.ts
export type CheckboxSize: 'Small' | 'Large'

export interface ICheckbox {
    Size: CheckboxSize;
}


// styles.ts
import styled, { css } from 'styled-components'
import type { CheckboxSize } from './types.ts' 

interface GetBoxSizeProps { 
  size: CheckboxSize
}

function getBoxSize ({ size }: GetBoxSizeProps) => ({
  'Small': css`
    height: 16px;
    width: 16px;
  `,
  'Large': css`
    height: 20px;
    width: 20px;    
  `,
}[size])

interface BoxProps {
  size: CheckboxSize
}

/*
  Just by placing the function here, it will be automatically 
  called by styled components and computed
*/
const Box = styled.div<BoxProps>`
  ${getBoxSize}

  //other styles...
`

// usage

<Box size="Small" />
<Box size="Large" />

My problem with the old "if" and "switch" styles was that after some props, the styles logic often times grow up into something that's quite verbose and hard to mantain

I'm not clamming this pattern as my invention, but I wasn't able to find something similar anywhere!

Hope this help someone :)

Ps: if you use themes, is possible to pass the property to the function and keep it pure!

Unforgettable answered 14/8, 2023 at 21:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.