By default, properties passed to a styled component are passed on as attributes to the native HTML element created. A regular property must be a valid HTML element attribute, or there will be an error in the console saying the property is not a valid HTML attribute. (Side note: It seems to accept all valid HTML attributes even if they're not valid for the specific HTML element. E.g., it will accept the "size" attribute for a div, even though that's not a valid DIV attribute.)

To pass custom properties to the styled component that are consumed by the component instead of being passed on to the HTML element, use Transient Properties. Transient Properties are prefixed with $ and are accessed within the styled component through the props object.

In the example below, the title is passed directly through to the div, and the other 3 properties are consumed by the styled div via the "props" object, e.g.: props => props.$sampleFontSize. The $size property (type BootstrapSize) is here to demonstrate the ability to reference one of multiple CSS objects, each containing various styles, stored in a Record object. The typical Bootstrap size is received as a prop and retrieves the Record containing the CSS object with the matching key.

Note: The example below is a bit much for a single styled component. Usually you would layer the styled components with each one adding additional functionality, such as a styled div called SizedDiv that manages size, then one that called BackColorDiv that contains SizedDiv and adds a background color. Something like that.

The styled div:

const SizeWrapper = styled.div<{ title: string, $size: BootstrapSize, $isInlineEditorInBsModal: boolean, $sampleFontSize: number }>`
    font-size: ${props => (props.$sampleFontSize)}px;
    ${props => (props.$isInlineEditorInBsModal ? "position: relative;" : "")}
    .mce-content-body {
        ${props => (BootstrapStyles[props.$size])};
    }
    & .custom-toolbar-wrapper {
        position: absolute;
    }
`;

The Bootstrap Record:

const BootstrapStyles: Record<BootstrapSize, CSSObject> = {
    sm: {
        fontSize: "0.875rem",
        padding: "0.25rem 0.5rem",
        minHeight: "calc(1.5em + 0.5rem + 2px)",
        borderRadius: "0.25rem",
    },
    md: {
        fontSize: "1rem",
        padding: "0.375rem 0.75rem",
        minHeight: "unset" /* No value for this, so use unset to get inherited/initial value */,
        borderRadius: "0.375rem",
    },
    lg: {
        fontSize: "1.25rem",
        padding: "0.5rem 1rem",
        minHeight: "calc(1.5em + 1rem + 2px)",
        borderRadius: "0.5rem",
    },
};

And to actually use the styled div:

<SizeWrapper 
  title={"my custom title"} 
  $size={props.size ?? "sm"} 
  $isInlineEditorInBsModal={props.isInlineEditorInBsModal ?? false} 
  $sampleFontSize={50}
>
  {/* amazing div content here */}
</SizeWrapper>
Published On: March 15, 2024Categories: ReactTags: , ,