I have the following code which I found on codepen and works and looks great!
.switch-field {
display: flex;
margin-bottom: 36px;
overflow: hidden;
}
.switch-field input {
position: absolute !important;
clip: rect(0, 0, 0, 0);
height: 1px;
width: 1px;
border: 0;
overflow: hidden;
}
.switch-field label {
background-color: #e4e4e4;
color: rgba(0, 0, 0, 0.6);
font-size: 14px;
line-height: 1;
text-align: center;
padding: 8px 16px;
margin-right: -1px;
border: 1px solid rgba(0, 0, 0, 0.2);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3), 0 1px rgba(255, 255, 255, 0.1);
transition: all 0.1s ease-in-out;
}
.switch-field label:hover {
cursor: pointer;
}
.switch-field input:checked label {
background-color: #a5dc86;
box-shadow: none;
}
.switch-field label:first-of-type {
border-radius: 4px 0 0 4px;
}
.switch-field label:last-of-type {
border-radius: 0 4px 4px 0;
}
<form >
<div >
<input type="radio" id="radio-three" name="switch-two" value="yes" checked/>
<label for="radio-three">One</label>
<input type="radio" id="radio-four" name="switch-two" value="maybe" />
<label for="radio-four">Two</label>
<input type="radio" id="radio-five" name="switch-two" value="no" />
<label for="radio-five">Three</label>
</div>
</form>
But unfortunately my generated HTML is laid out as follows (with the input inside the label):
<form >
<div >
<label for="radio-three">
<input type="radio" id="radio-three" name="switch-two" value="yes" checked/>
One</label>
<label for="radio-four">
<input type="radio" id="radio-four" name="switch-two" value="maybe" />
Two</label>
<label for="radio-five">
<input type="radio" id="radio-five" name="switch-two" value="no" />
Three</label>
</div>
</form>
I am wondering if its possible just with CSS to adapt this class to make it work or if JS is necessary.
.switch-field input:checked label {
background-color: #a5dc86;
box-shadow: none;
}
Many thanks in advance!
CodePudding user response:
You should use JS.
When input element is inside the label then we do not need id on the element and 'for' attribute on the label, but when it is outside we need it.
<label>
Foo
<input name="foo" type="checkbox" />
</label>
Based on your HTML Code, To alter the styling of the label, would require a selector that affected the parent, which currently isn't possible. Why? https://css-tricks.com/parent-selectors-in-css/
<input id="foo" name="foo" type="checkbox" />
<label for="foo">Foo</label>
So, to select the label of the :checked input, we need the label to be adjacent, not the parent.
But in your code, HTML's label and input is implicit connecting. So I think the solution is to use JS.
let form = document.querySelector("form");
form.addEventListener("change", (event) => {
let target = event.target;
let targetParent = target.parentElement;
if (
target.type === "radio" &&
targetParent &&
targetParent.tagName.toLowerCase() === "label"
) {
let prior = form.querySelector('label.checked input[name="' target.name '"]');
if (prior) {
prior.parentElement.classList.remove("checked");
}
targetParent.classList.add("checked");
}
}, false);
.switch-field {
display: flex;
margin-bottom: 36px;
overflow: hidden;
}
.switch-field input {
position: absolute !important;
clip: rect(0, 0, 0, 0);
height: 1px;
width: 1px;
border: 0;
overflow: hidden;
}
.switch-field label {
background-color: #e4e4e4;
color: rgba(0, 0, 0, 0.6);
font-size: 14px;
line-height: 1;
text-align: center;
padding: 8px 16px;
margin-right: -1px;
border: 1px solid rgba(0, 0, 0, 0.2);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3), 0 1px rgba(255, 255, 255, 0.1);
transition: all 0.1s ease-in-out;
}
.switch-field label:hover {
cursor: pointer;
}
.switch-field label.checked {
background-color: #a5dc86;
box-shadow: none;
}
.switch-field label:first-of-type {
border-radius: 4px 0 0 4px;
}
.switch-field label:last-of-type {
border-radius: 0 4px 4px 0;
}
<form >
<div >
<label >
<input type="radio" name="switch-two" value="yes" checked />
One
</label>
<label>
<input type="radio" name="switch-two" value="maybe" />
Two
</label>
<label>
<input type="radio" name="switch-two" value="no" />
Three
</label>
</div>
</form>
CodePudding user response:
Here is example of how you can achieve desired functionality through javascript
var checkboxes = document.querySelectorAll("input[type=radio]");
var labels = document.querySelectorAll("label");
labels[0].classList.add("checkedLabel");
checkboxes.forEach(function(checkbox) {
checkbox.addEventListener('change', function(e) {
Array.from(labels).forEach(function(el) {
el.classList.remove('checkedLabel');
});
this.parentElement.classList.add("checkedLabel");
})
})
.checkedLabel {
background-color: #a5dc86;
box-shadow: none;
}
<form >
<div >
<label for="radio-three">
<input type="radio" id="radio-three" name="switch-two" value="yes" checked/>
One</label>
<label for="radio-four">
<input type="radio" id="radio-four" name="switch-two" value="maybe" />
Two</label>
<label for="radio-five">
<input type="radio" id="radio-five" name="switch-two" value="no" />
Three</label>
</div>
</form>
CodePudding user response:
The Only CSS Solution Possible
The pseudo-selector :focus-within
. Should an element have any children element that has focus, that parent will have styles applied to it. So a radio button that the user checks will trigger a focus event and in doing so activate the CSS ruleset that has :focus-within
which is the label in the following example.
.switch-field label:focus-within {
background-color: #a5dc86;
box-shadow: none;
}
<form >
<div >
<label for="radio-three">
<input type="radio" id="radio-three" name="switch-two" value="yes" checked/>
One</label>
<label for="radio-four">
<input type="radio" id="radio-four" name="switch-two" value="maybe" />
Two</label>
<label for="radio-five">
<input type="radio" id="radio-five" name="switch-two" value="no" />
Three</label>
</div>
</form>
CodePudding user response:
Yes, replace .switch-field input
with .switch-field label input
.
A selector of the form x1 x2 x3 ... xn—1 xn
(space separated) means xn
which is a descendent of xn−1
and so on.