Change the container background when a Radiobutton is clicked - html

i just wanted to know if i got a container and inside the container there is a radio button so for styling i want the container to change its background color whenever i click on the radio button.
<div className='team'>
<div className="team__first-row">
<svg>{image}</svg>
<input type="radio" name="Monitor" id="Monitor" />
</div>
<p className="team__name">{teamName}</p>
</div>
.team {
border: var(--basic-border-color);
width: 19em;
height: 7em;
border-radius: 1rem;
display: flex;
flex-direction: column;
justify-content: center;
}
.team__first-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: .3rem .6rem;
margin-bottom: 2em;
}
input[type="radio"] {
appearance: none;
border-radius: 50%;
border: var(--basic-border-color);
width: 1.2rem;
height: 1.2rem;
cursor: pointer;
position: relative;
}
input[type="radio"]:focus {
border: none;
background: var(--container-bg);
}
input[type="radio"]::before {
content: "";
width: 0.2em;
height: 0.2em;
border-radius: 50%;
transform: scale(0);
transition: 120ms transform ease-in-out;
}
input[type="radio"]:focus::after {
content: url(../imgs/vuesax/bulk/Vector.svg);
position: absolute;
top: .12em;
left: .3em;
}
enter image description here
I tried to use the selectors between the parent container and the input but it seems like there is something missing !

Use :has selector
A recent addition to CSS language, :has() pseudo-class enables selecting a parent or sibling element. According to MDN documentation page
The functional :has() CSS pseudo-class represents an element if any of the relative selectors that are passed as an argument match at least one element when anchored against this element. This pseudo-class presents a way of selecting a parent element or a previous sibling element with respect to a reference element by taking a relative selector list as an argument.
In a sample code snippet below, I used :has() selector to target "any .fruit div that has an input:checked" and updated its background color.
.container {
display: flex;
justify-content: center;
flex-wrap: wrap;
border: 1px solid #333;
padding: 20px;
width: 540px;
}
.fruit {
width: 120px;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
border: 1px solid #333;
padding: 20px;
margin: 0 15px 15px 0;
}
.fruit img {
border-radius: 50px;
}
label {
margin-top: 20px;
width: 100%;
}
input, label {
cursor: pointer;
}
.fruit:has(input:checked) {
background: yellow;
}
<div class="container">
<div class="fruit">
<img src="https://picsum.photos/30" alt="">
<input type="radio" name="team" id="Mango" value="Mango" />
<label for="Mango">Mango</label>
</div>
<div class="fruit">
<img src="https://picsum.photos/30" alt="">
<input type="radio" name="team" id="Pineapple" value="Pineapple" />
<label for="Pineapple">Pine Apple</label>
</div>
<div class="fruit">
<img src="https://picsum.photos/30" alt="">
<input type="radio" name="team" id="Dragonfruit" value="Dragonfruit" />
<label for="Dragonfruit">Dragonfruit</label>
</div>
</div>

Related

Have :focus Toggle Items Including If You Click The Parent Item Again

I have a simple submenu that is toggled into visibility using the :focus CSS selector.
It shows the submenu by turning the submenu from display: none to display: block with the following CSS:
.menu-item:focus > .submenu {
display: block;
}
This all works, and if I click on a different menu item (or anywhere else on the page) the submenu then disappears.
Is it possible however with CSS (and I'm guessing :focus) to have it so when I click on the initial menu-item again (i.e. for a 2nd time) it also toggles away? At the moment this isn't happening - it is only happening when I click anywhere else (which is clearly when the element loses focus).
Many thanks
Codepen: https://codepen.io/emilychews/pen/RwVVmjm
body {
display: flex;
justify-content: center;
margin: 0;
height: 100vh;
width: 100%;
}
header {
margin-top: 2rem;
display: flex;
width: 50%;
justify-content: space-evenly;
align-items: center;
padding: 1rem;
background: red;
height: 2rem;
}
.menu-item {
position: relative;
padding: 1rem;
background: yellow;
cursor: pointer;
}
/* select the focused menu-item's child elements (the submenu) */
.menu-item:focus > .submenu {
display: block;
}
.submenu {
display: none; /* changes to 'block' with focus */
padding: 1rem;
background: lightblue;
position: absolute;
top: 4rem;
left: 0;
width: 6rem;
}
<header>
<div id="item-1" class="menu-item menu-item-1" tabindex="0">ITEM 1
<div id="sub-item-1" class="submenu submenu-1">SUB-ITEM-1</div>
</div>
<div id="item-2" class="menu-item menu-item-2" tabindex="0">ITEM 2
<div id="sub-item-2" class="submenu submenu-2">SUB-ITEM-2</div>
</div>
</header>
The best way for my opinion is to use JavaScript.
However you can use checkbox and changing the wrapper div to label for only CSS solution :
body {
display: flex;
justify-content: center;
margin: 0;
height: 100vh;
width: 100%;
}
header {
margin-top: 2rem;
display: flex;
width: 50%;
justify-content: space-evenly;
align-items: center;
padding: 1rem;
background: red;
height: 2rem;
}
.menu-item {
position: relative;
padding: 1rem;
background: yellow;
cursor: pointer;
}
/* select the element after the checked checkbox (the submenu) */
.dis:checked ~ .submenu {
display: block;
}
.dis{ /*reset default checkbox style*/
display: none
}
.submenu {
display: none; /* changes to 'block' with focus */
padding: 1rem;
background: lightblue;
position: absolute;
top: 4rem;
left: 0;
width: 6rem;
}
<header>
<label id="item-1" class="menu-item menu-item-1" tabindex="0">ITEM 1
<input type="checkbox" class="dis">
<div id="sub-item-1" class="submenu submenu-1">SUB-ITEM-1</div>
</label>
<label id="item-2" class="menu-item menu-item-2" tabindex="0">ITEM 2
<input type="checkbox" class="dis">
<div id="sub-item-2" class="submenu submenu-2">SUB-ITEM-2</div>
</label>
</header>

Folder tabs radio-button's labels' z-index doesn't work on click

I am trying to write code for folder tabs
what I am trying to archive is that when each folder tab is clicked, it should be shown the top most of other tabs while the others are positioned behind it.
I tried to work with z-index:-1 for all tabs yet the clicked tab gain z-index:3 but it doesn't work.
One strange thing is that when I remove the line of z-index : -1; in label style which will make the default z-index of the label to be auto (z-index : auto;) it works. My question is that why z-index: -1 doesn't work while z-index:auto works for label style?
section {
padding: 2rem;
height: 100vh;
display: flex;
flex-flow: column nowrap;
}
section .header {
display: flex;
flex-flow: row nowrap;
justify-content: flex-end;
}
section .header input {
display: none;
}
section .header label {
margin-left: -1rem;
padding: 0.5rem 1rem;
display: inline-block;
position: relative;
z-index: -1;
border-radius: 27px 0 0 0;
}
section .header input:checked~label {
z-index: 3;
background-color: grey;
}
section .header .weather label {
background-color: greenyellow;
}
section .header .others label {
background-color: indianred;
}
section .header .about-us label {
background-color: indigo;
}
section .main {
flex: 1;
border: 1px solid black;
}
<section>
<div class="header">
<div class="weather">
<input type="radio" name="tab" id="weather">
<label for="weather">weather</label>
</div>
<div class="others">
<input type="radio" name="tab" id="others">
<label for="others">others</label>
</div>
<div class="about-us">
<input type="radio" name="tab" id="about-us" checked>
<label for="about-us">about-us</label>
</div>
</div>
<div class="main">
This is main
</div>
</section>
scss:
section {
padding: 2rem;
height: 100vh;
display: flex;
flex-flow: column nowrap;
.header {
display: flex;
flex-flow: row nowrap;
justify-content: flex-end;
input {
display: none;
}
label {
margin-left: -1rem;
padding: .5rem 1rem;
display: inline-block;
position: relative;
z-index: -1; // while (z-index : auto;) works. why?
border-radius: 27px 0 0 0;
}
input:checked~label {
z-index: 3;
background-color: grey;
}
.weather {
label {
background-color: greenyellow;
}
}
.others {
label {
background-color: indianred;
}
}
.about-us {
label {
background-color: indigo;
}
}
}
.main {
flex: 1;
border: 1px solid black;
}
}
When you use z-index: -1 you should also add z-index: 0; to its parent - section .header div in your case, in order to put the element behind the desired element(s) in the same div. Otherwise it puts it behind the root element of the page. But in your case, the problem is that you hide the radio inputs. Apply the following css: position: absolute; width: 100%; height: 100%; opacity: 0; to your section .header input instead of the display:none; and it will work

Is it possible to align one flex child above another flex child in a line below?

I am struggling with a flexbox tag here. I have a page header, that consists from two parts: smaller text "A comprehensive manual:" and "How to take a dog from UK to SOME OTHER COUNTRY".
So the problem is, according to design document, "How to take a dog from UK to SOME OTHER COUNTRY" should be centred, but "A comprehensive manual" line shouldn't, it should start right above letter "H" in the second line, "How to take...", as shown on a picture below:
here
Obviously, when I resize a window, flexbox starts doing it thing and wars text around, changing the position of the "How", however "A comprehensive manual" should also move to keep along.
Is it possible with a flexbox, or I should use ::after pseudoelement to achieve it? Or maybe there is better solution?
Code is below, there is also a link to the codepen with an example.
Many thanks!
<div class="take-where-box">
<div class="flex">
<div class="take-where-box__text-block large" id="take-where-box__text-block-intro"><p class="take-where-box__small-text">A Comperhensive Manual:</p></div>
<div class="take-where-box__text-block" id="take-where-box__text-block-1"><p>How to take a dog</p></div>
<div class="take-where-box__text-block" id="take-where-box__text-block-2"><p>from UK</p></div>
<div class="take-where-box__text-block" id="take-where-box__text-block-3">
<div class="select-box">
/*code for select box*/
</div> <!-- end of select-box-->
</div>
</div>
</div> <!-- take-where-box-->
Full codepen is here:
https://codepen.io/abby97/pen/oNYjrpV
Perhaps the layout can be achieved with a minor adjustment to the align-items property and a pseudo element.
.flex {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: flex-end; /* changed from baseline */
}
#take-where-box__text-block-1::before {
font-size: 70%;
content: "A Comprehensive Manual:";
}
#take-where-box__text-block-1::before {
font-size: 70%;
content: "A Comprehensive Manual:";
}
body,
html {
margin: 0;
padding: 0;
font-family: 'Calibri', serif;
font-size: 100%;
color: black;
background-color: var(--cyan-superdark);
}
.container {
background-color: var(--main_color);
margin: 0 auto;
width: 80%;
}
.header,
.content {
margin: 0;
display: flex;
flex-direction: column;
align-items: center;
}
.header {
background-color: var(--yellow-main);
}
.content {
background-color: var(--cyan-superdark);
}
.take-where-box {
font-size: 3rem;
justify-content: center;
align-items: center;
font-weight: bold;
width: 90%;
border: 0.4rem solid black;
padding: 1.5rem;
}
.flex {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: flex-end;
}
.take-where-box__small-text {
font-size: 70%;
margin: 0;
}
.take-where-box__text-block {
flex-basis: 1;
/* flex-shrink: 0; */
/* min-width: min-content; */
padding: 0 0.5rem;
}
.large {
flex-basis: 100%;
}
.take-where-box__text-block>p {
margin: 0;
}
/*select-box - a custom select box, taken from https://www.youtube.com/watch?v=k4gzE80FKb0 */
.select-box {
display: flex;
flex-direction: column;
position: relative;
width: 22rem;
}
.select-box__selected-option,
.select-box__options-container {
border: 0.4rem solid black;
}
.select-box .select-box__options-container {
max-height: 0;
opacity: 0;
transition: all 0.3s;
/* what are other options? */
order: 1;
}
.select-box__selected-option {
margin-bottom: 8px;
position: relative;
order: 0;
}
.select-box__options-container {
position: absolute;
box-sizing: border-box;
/*otherwise border will add up to the witdh of this element making it bigger than parent, BAD!*/
width: 100%;
top: 7.5rem;
background-color: white
}
.select-box__selected-option::after {
content: "";
background: url("assets/arrow-down.svg");
background-size: contain;
background-repeat: no-repeat;
position: absolute;
height: 100%;
width: 3.0rem;
/* height: 4rem; */
right: 1rem;
top: 1rem;
transition: all 0.4s;
}
.select-box .select-box__options-container.active+.select-box__selected-option::after {
transform: rotateX(180deg);
top: -1rem;
}
.select-box .select-box__options-container.active {
max-height: min-content;
opacity: 1;
}
.select-box .select-box__option,
.select-box__selected-option {
padding: 0.5rem 1rem;
cursor: pointer;
}
.select-box .select-box__option:hover {
background-color: blue;
}
.select-box label {
cursor: pointer;
}
.select-box .select-box__option .radio {
display: none;
}
<div class="container">
<div class="take-where-box">
<div class="flex">
<div class="take-where-box__text-block large" id="take-where-box__text-block-intro">
<!--<p class="take-where-box__small-text">A Comperhensive Manual: </p>-->
</div>
<div class="take-where-box__text-block" id="take-where-box__text-block-1">
<p>How to take a dog</p>
</div>
<div class="take-where-box__text-block" id="take-where-box__text-block-2">
<p>from UK</p>
</div>
<div class="take-where-box__text-block" id="take-where-box__text-block-3">
<div class="select-box">
<div class="select-box__options-container">
<div class="select-box__option">
<input type="radio" class="radio" id="US" name="category">
<label for="US">to US</label>
</div>
<div class="select-box__option">
<input type="radio" class="radio" id="EU" name="category">
<label for="EU">to EU</label>
</div>
</div>
<!-- end of select-boxoptions-container-->
<div class="select-box__selected-option">
to US
</div>
</div>
<!-- end of select-box-->
</div>
</div>
</div>
<!-- take-where-box-->
</div>
revised codepen
i believe your code is unnecessery overcomplicated.
element positioning like in image you can achieve with this piece of code. please note that css is inline, because this is just a guidline, you can adapt it by your needs:
<div style="display:flex; align-items:center; flex-direction:column">
<div>
<div>
<p>A Comperhensive Manual:</p>
</div>
<div style="display:flex">
<p>How to take a dog from UK</p>
<p>selectbox</p>
</div>
</div>
</div>

Gap between border and child element with border radius

I'm trying to implement radio buttons which kind of work like segmented controls:
* {
margin: 0;
padding: 0;
}
.container {
background-color: brown;
width: 80vw;
}
.box {
display: flex;
flex-direction: row;
border: 2rem solid skyblue;
border-radius: 999px;
}
label {
flex: 1;
padding: 2rem;
border-radius: 999px;
text-align: center;
}
input {
display: none;
}
input:checked + label {
background-color: skyblue;
}
<div class="container">
<div class="box">
<input type="radio" id="hello" name="test" checked />
<label for="hello">Hello</label>
<input type="radio" id="world" name="test" />
<label for="world">World</label>
</div>
</div>
However, there's an annoying gap of about 1px between the nested label and the parent div:
This issue is similar to this question, but the workarounds suggested don't really work for my use case since I can't change the background color. I'm also curious if this is a browser bug or some kind of anti-aliasing issue.
just add box shadow to the input:check + label
input:checked + label {
background-color: skyblue;
box-shadow: 0px 0px 0 1px skyblue;
}
Link to Jsfiddle
I don't know the reason why you are getting that 1 px gap but you can add "transform: translateX(-1px);" to shift it left by 1px. This can work as a temp solution.
label {
flex: 1;
padding: 2rem;
border-radius: 200px;
text-align: center;
transform: translateX(-1px);
}
Change label border-radius 999px to 35px
label {
flex: 1;
padding: 2rem;
border-radius: 35px;
text-align: center;
}
* {
margin: 0;
padding: 0;
}
.container {
background-color: brown;
width: 80vw;
}
.box {
display: flex;
flex-direction: row;
border: 2rem solid skyblue;
border-radius: 999px;
}
label {
flex: 1;
padding: 2rem;
border-radius: 35px;
text-align: center;
}
input {
display: none;
}
input:checked + label {
background-color: skyblue;
}
<div class="container">
<div class="box">
<input type="radio" id="hello" name="test" checked />
<label for="hello">Hello</label>
<input type="radio" id="world" name="test" />
<label for="world">World</label>
</div>
</div>

How Can I Make the Clickable Area be Applied to Whole Div, not Just Label?

I have been banging my head against the wall on this one for a while and can't seem to find how to do this. I have a card with two rows (card-body) classes. each row represents a radio button (input) with a corresponding label. When the user clicks the radio button I want the background to change colors. Right now that is working, but the background is only working for the label and not the whole div that contains the card row. I'm looking for a HTML/CSS-only answer, as I think it's probably something simple that I'm doing wrong. Thanks!
CSS
.card {
position: relative;
display: flex;
flex-direction: column;
min-width: 0;
word-wrap: break-word;
background-color: #fff;
background-clip: border-box;
border: 1px solid rgba(0, 0, 0, 0.12);
border-radius: 0.25rem;
}
.card-body {
flex: 1 1 auto;
padding: 1.25rem;
}
.pick input[type="radio"] {
display: none;
/* comment this line to see the radio buttons */
}
.pick label {
display: inline-block;
background-color: red;
}
.pick input[type="radio"]:checked+label {
background-color: blue;
}
.card {
border-style: solid;
border-width: 5px;
}
label {
display: block;
width: 100%;
}
HTML
<div class="card">
<div class="card-body pick" for="i1">
<input type="radio" name="g1" id="i1" value="you" data-target="r65">
<label class="ben" for="i1" id="r1">you</label>
</div>
<div class="card-body pick" for="i2">
<input type="radio" name="g1" id="i2" value="me" data-target="r65">
<label class="ben" for="i2" id="r2">me</label>
</div>
</div>
JSFiddle: https://jsfiddle.net/j3mskfjv/11/
You need to set your labels to display: block with width of 100%, like so:
.card {
position: relative;
display: flex;
flex-direction: column;
min-width: 0;
word-wrap: break-word;
background-color: #fff;
background-clip: border-box;
border: 1px solid rgba(0, 0, 0, 0.12);
border-radius: 0.25rem;
}
.card-body {
flex: 1 1 auto;
}
.pick input[type="radio"] {
display: none;
/* comment this line to see the radio buttons */
}
.pick label {
display: inline-block;
background-color: red;
}
.pick input[type="radio"]:checked+label {
background-color: blue;
}
.card {
border-style: solid;
border-width: 5px;
}
.pick {
display: flex;
}
label {
display: block;
flex: 1;
padding: 1.25rem;
}
<div class="card">
<div class="card-body pick" for="i1">
<input type="radio" name="g1" id="i1" value="you" data-target="r65">
<label class="ben" for="i1" id="r1">you</label>
</div>
<div class="card-body pick" for="i2">
<input type="radio" name="g1" id="i2" value="me" data-target="r65">
<label class="ben" for="i2" id="r2">me</label>
</div>
</div>