React - Is there a way to change the background color of a parent element when a radio button is clicked without jquery?

The code structure looks somewhat like this

     function RenderOptions() {
      return allOptions.map((val) => {
        return (
          <>
            <label htmlFor={val}>
              <input
                type="radio"
                name="options"
                id={val}
                value={val}
                className="check-btn"
              />{" "}
              <span className="text-inner">{val}</span>
            </label>{" "}
            &nbsp; &nbsp;
          </>
        );
      });
    }

Didnt put a div since I didnt want to spend some time finding how to align the buttons in rows.

CSS

.check-btn {
  opacity: 0;
  position: relative;
  top: 2px;
}

label {
  border-radius: 10px;
  font-family: Inter;
  font-style: normal;
  font-weight: 600;
  font-size: 12px;
  line-height: 12px;
  text-align: center;
  width: 100%;
  transition: 0.3s ease;

  background: #f5f7fb;
  border: 0.794239px solid #4d5b9e;
  box-sizing: border-box;
  border-radius: 7.94239px;

  padding-top: 5px;
  padding-bottom: 5px;
  padding: 5px 10px 5px 10px;
}

label:hover {
  background-color: #d6dbf5;
  cursor: pointer;
}

.text-inner {
  position: relative;
  right: 10px;
}

im trying to change the background color of the parent label when the radio button is checked. Can do it the css way or react way provided, only 1 button from each sets color changes .

and if another option is clicked →

Thanks!

Common approach is to make them siblings: https://codepen.io/jenovs/pen/ExbpBYV

You can also lift up state to the parent, use context, or a state management tool like Redux. Don’t use jQ. Never mix React with another DOM manipulation library.

There shouldn’t be any need to include jQuery in a React project ever, those are conflicting things tbh. But anyway, just use CSS if all you want to do is colour the background of a label when its child input is clicked:

label:focus-within {
  background-color: pink:
}

Example: https://codepen.io/sutor/pen/KKyBjVY

If you have multiple sets of inputs, so you need it to stay coloured on the page (ie you can’t just click submit and the above is unmounted and disappears offscreen), then you do this:

<div>
  <input id=foo type=radio />
  <label for=foo>Foo</foo>

And hide the input (display:none would be fine but there are better ways to hide things and keep them accessible).

Then

input:checked ~ label {
  background-color: pink;
}

Exactly same way as now?? Anyway, you’re basically just making lots of work for yourself by avoiding doing this, though if you’re mapping over the inputs and the value is state, you know which one is selected anyway so can just add a class.

1 Like

I was stupid, I should have send the full source code . The RenderOptions was just one of the child components of a huge Quiz component which is yet a child of the App component… I thought there was some way to fix the problem with the RenderOptions component. I did try to make them child elements but that failed to work.

I did try this but it doesnt seem to work. Maybe its a problem on my end.

Oops… didnt really learn Redux, yet. The project im doing now is the final do-it-yourself project of a freecodecamp youtube react couse.

Here is the full source code =>
replit.com
github

Well, Dan’s approach sounds interesting. A solution like that would be simpler than what I am suggesting.

I’m not saying you need Redux - it is one option. And if you are just trying to affect the parent, then there are easier ways. I mentioned lifting up state. I once wrote this pen as an example of how a child can change the state of a parent.

But Dan’s solution is cleaner with less work. I don’t work with “real” CSS much anymore (React Native isn’t quite the same), but that looks good.

You know that all of your radio buttons have the same name attribute, meaning that they’ll be a part of the same group?

The focus-within won’t work unfortunately, because as soon as it switches focus to something else it’ll lose the colour :pensive:

Second option though, (a label & an input as siblings), that doesn’t have that issue & that’s the standard way and requires minimal styling.

But re raising the state up: that should be fairly simple regardless because unless every single thing is hardcoded, should be mapping over some state anyway, and must need to know which option is selected, so just set a class on that one. It shouldn’t matter what the rest of the structure is @Exotic, because there must be something in your state that records which option is selected, so just take that and add a class to it

Thanks! This worked. I replaced the existing code from that part and re did it with the format you gave.

Yes. Using display: none; will remove the functionality. Using opacity: 0; does the trick : )

I was actually looking for a way to do this the easier way without using state, i.e, with css . Initially setting up state is harder than using just a few lines of css.
But yes, state can do the trick.

No it won’t remove functionality, you only care about the label. With opacity you have an element in the page flow that takes up space, so need to use abs positioning and shift it off the screen/give it no height/etc. Anyway, example:

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.