2

I am facing a weird CSS issue in my React project. A particular part of the JSX <div> has a class applied to it and added some style properties in the main .css file of the project. In local development, everything works fine but as soon as the build is created and uploaded to the production server, that particular part of the JSX <div> CSS class changes and the styling gets distorted.

Example:

Original JSX

import React, { useEffect, useState, useContext } from "react";
import Tooltip from "@material-ui/core/Tooltip";
import { withStyles, makeStyles } from "@material-ui/core/styles";
import Slider from "@material-ui/core/Slider";

const useStyles = makeStyles((theme) => ({
  root: {
    width: 450,
  },
  margin: {
    height: 100,
  },
}));

const PrettoSlider = withStyles({
  root: {
    color: "red",
    height: 8,
  },
  thumb: {
    height: 24,
    width: 24,
    backgroundColor: "#fff",
    border: "2px solid currentColor",
    marginTop: -8,
    marginLeft: -12,
    "&:focus,&:hover,&$active": {
      boxShadow: "inherit",
      border: "2px solid #fff407 !important",
    },
  },
  active: {
    backgroundColor: "#fff407",
  },
})(Slider);

const CustomizedSlider = ({
  id,
  abbr,
  type,
  minElig,
  maxElig,
}) => {

  useEffect(() => {
    setValue(sliderPreviousValue);
  }, [sliderPreviousValue]);


  const classes = useStyles();
  return (
    <>
      <div className={classes.root}>
        {type === "intervention" ? (
          <ProgressBar max={maxElig} value={sliderValue} />
        ) : null}

        {renderSlider}
      </div>
    </>
  );
};

Original DOM:

<div class="diabMetr clearfix">
   <span class="diabLabl">Diabetes</span>
   <div class="makeStyles-root-1">
      <span class="MuiSlider-root WithStyles(ForwardRef(Slider))-root-3 MuiSlider-colorPrimary"><span class="MuiSlider-rail WithStyles(ForwardRef(Slider))-rail-8"></span><span class="MuiSlider-track WithStyles(ForwardRef(Slider))-track-7" style="left: 0%; width: 83.3333%;"></span><input type="hidden" value="200"><span class="MuiSlider-thumb WithStyles(ForwardRef(Slider))-thumb-4 MuiSlider-thumbColorPrimary PrivateValueLabel-open-12 PrivateValueLabel-thumb-11" tabindex="0" role="slider" data-index="0" aria-label="pretto slider" aria-orientation="horizontal" aria-valuemax="240" aria-valuemin="0" aria-valuenow="200" style="left: 83.3333%;"><span class="PrivateValueLabel-offset-13 MuiSlider-valueLabel WithStyles(ForwardRef(Slider))-valueLabel-6"><span class="PrivateValueLabel-circle-14"><span class="PrivateValueLabel-label-15">200</span></span></span></span></span>
      <div class="valueOuter clearfix"><label class="valueLeft">0</label><label class="valueRight">240</label></div>
   </div>
</div>

The CSS for this JSX is:

.diabMetr {
        padding-top: 10px;
        span.diabLabl {
          display: inline-block;
          width: 200px;
          text-align: left;
          font-size: 12px;
          line-height: 30px;
          text-align: right;
          @include respond-to(media-xl) {
            width: 120px;
          }
        }
        span.MuiSlider-root {
          width: 100%;
          padding: 0;
          height: 0px;

          .MuiSlider-rail {
            height: 30px;
            border-radius: 15px;
            background: #e8e8e8;
            opacity: 1;
          }
          .MuiSlider-track {
            height: 30px;
            background: #88d479;
            border-radius: 15px;
          }
          .MuiSlider-thumb {
            z-index: 12;
            width: 35px;
            height: 35px;
            border-radius: 50%;
            margin-left: -17px;
            border: #88d479 solid 2px;
            margin-top: -3px;
          }
          .MuiSlider-markLabel.MuiSlider-markLabelActive:last-child() {
            right: 0 !important;
          }
        }
      }

.makeStyles-root-1 {
  width: calc(100% - 220px) !important;
  float: right;
  margin-top: -22px;
}

The DOM changes after build and uploaded to the server:

<div class="diabMetr clearfix">
   <span class="diabLabl">Diabetes</span>
   <div class="jss16">
      <span class="MuiSlider-root jss18 MuiSlider-colorPrimary"><span class="MuiSlider-rail jss23"></span><span class="MuiSlider-track jss22" style="left: 0%; width: 83.3333%;"></span><input type="hidden" value="200"><span class="MuiSlider-thumb jss19 MuiSlider-thumbColorPrimary jss27 jss26" tabindex="0" role="slider" data-index="0" aria-label="pretto slider" aria-orientation="horizontal" aria-valuemax="240" aria-valuemin="0" aria-valuenow="200" style="left: 83.3333%;"><span class="jss28 MuiSlider-valueLabel jss21"><span class="jss29"><span class="jss30">200</span></span></span></span></span>
      <div class="valueOuter clearfix"><label class="valueLeft">0</label><label class="valueRight">240</label></div>
   </div>
</div>

The CSS for the class .jss16 is:

.jss16 {
    width: 450px;
}

Issue to notice Only the class .makeStyles-root-1 gets replaced with some random class .jss16 when the build gets uploaded to the server and the CSS changes accordingly, the rest of the JSX remains unchanged. I tried searching for the class .jss16 everywhere in the code, but it's not found. Also, everything works fine on localhost.

I tried adding the CSS properties to the .jss16 like this:

.jss16 {
  width: 450px;
  width: calc(100% - 220px) !important;
  margin-top: -22px;
  float: right;
}

and then re-initiate the uploading process but then instead of .jss16, another class is replaced something like .jss42. This keeps on repeating and does not work on any new build created.

I also tried the following CSS:

.diabMetr + span + div {
  width: 450px;
  width: calc(100% - 220px) !important;
  margin-top: -22px;
  float: right;
},

but this also didn't help. The styling of the app still remains distorted (incorrect, not as on localhost).

I spent several hours searching for this but in vain. If anyone can assist me in understanding this error and resolve the same, will be highly appreciated. Thanks in advance!

program_bumble_bee
  • 439
  • 2
  • 25
  • 57

3 Answers3

2

there are quite a few issues with this code. First in jsx CSS class is given as className as @Max has mentioned in his/her answer.
Another issue is that @material-ui's makeStyle doesn't work in this way. The classNames inside the makeStyle change to random names in the build stage. This happens to keep the classNames uniques, this is @material-ui's feature. I'd suggest you to read this @matrial-ui's documentation about makeStyles. And here a code example is provided.

To use makeStyles classes you've to hook it into your component.

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';

const useStyles = makeStyles({
  root: {
    backgroundColor: 'red',
    color: props => props.color,
  },
});

export default function MyComponent(props) {
  const classes = useStyles(props);
  return (
    <div className={classes.root}>
      Lorem iosum poder
    </div>
  );
}

Update

According to your jsx code, add the styles which you've added in css class .makeStyles-root-1 in the useStyles object. It'll add the styles to the element.
After adding those CSS styles in useStyles this object will look like this:-


const useStyles = makeStyles((theme) => ({
  root: {
    width: 'calc(100% - 220px) !important',
    float: 'right',
    marginTop: '-22px'

  },
  margin: {
    height: 100,
  },
}));

The root class will contain those styles and it'll be applied without providing the styles separately from the CSS file.

Rajiv
  • 3,346
  • 2
  • 12
  • 27
  • I updated my code with JSX instead of the DOM. The `
    ` is what actually gets converted with the random className in the DOM.
    – program_bumble_bee Dec 30 '20 at 13:26
  • yes.. this happens behind the scene while build. Now the style which you've applied in class `.makeStyles-root-1`, now you can add those styles in the `useStyles ` object in `root` key. I'm updating the answer in few mins. – Rajiv Dec 30 '20 at 13:41
  • One more small help. If I pass the property `margin` from the CSS `root: { width: 'calc(100% - 220px) !important', float: 'right', marginTop: '-22px' }, margin: { height: 100, },` as prop to component ``, it creates a new class in the DOM like: `
    – program_bumble_bee Dec 30 '20 at 18:06
  • 1
    yes. This is how the `@material-ui` compilation works. It creates new and random class names so that the classes remain unique in each file. Suppose you've created a `root` class in `Component A` and also in `ComponentB` but you've given different styles to the root class in both components. If it doesn't create a new class then both styles will clash and the result will be not what expected. So, it creates a different and unique classNames for each file or better say for each `makeStyls` use. – Rajiv Dec 31 '20 at 06:09
0

Solution

I am not sure what component creates the div with "jss16" class, assume it is ExternalComponent.

You should add a custom className (assuming ExternalComponent handles this correctly):

<ExternalComponent className="myclass">
   ...
</ExternalComponent>

this will create a DOM like this:

<div class="jss16 myclass">
    ...
</div>

Sou you can create css for myclass:

.myclass {
  width: calc(100% - 220px) !important;
  float: right;
  margin-top: -22px;
}

Explanation

ExternalComponent uses jss to dynamically generate css classes, so you cant rely on the name of the dynamically generated class. In most of the cases, components with custom classes should append props.className to the generated jss like this:

return (
    <div className={jssClassname + props.className ? ' ' + props.className : ''}>
        {children}
    </div>
);
Mihályi Zoltán
  • 822
  • 6
  • 11
-1

I couldn't reproduce the error because I had some syntax issues, so I wonder if fixing these, the build will behave correctly:

  • Add closing / to input
  • Write style's using objects, example style={{left: '0%', width: '83.3333%'}}
  • Update class to className
  • Update tabindex to tabIndex

Lastly, if that doesn't help, to make your CSS work, ie .diabMetr + span + div, rewrite it to:

.diabMetr > span + div {}

or

.diabMetr > div {}

Right now, it's not selecting the child element.

Max
  • 109
  • 2