I am using a checkbox as a way to modify the other element's style. Is it possible for a checkbox to affect other classes/elements of the website.
I have a sample html code below, instead of changing label element, is it possible to change the styling of the first div instead.
ul li {
display: inline-block;
}
ul li input[type="checkbox"]:checked+label {
border: 2px solid gray;
background-color: gray;
color: #fff;
transition: all .2s;
}
ul li {
padding: 20px;
margin: 20px;
}
ul li input[type="checkbox"] {
display: absolute;
}
ul li input[type="checkbox"] {
position: absolute;
opacity: 0;
}
ul li label {
padding: 20px;
cursor: pointer;
}
<div class="modify-box">
BOX TO CHANGED
</div>
<ul>
<li>
<input type="checkbox" id="vehicle1" name="vehicle1" value="Bike">
<label for="vehicle1"> Bike</label><br>
</li>
<li>
<input type="checkbox" id="vehicle2" name="vehicle2" value="Car">
<label for="vehicle2"> Car</label><br>
</li>
<li>
<input type="checkbox" id="vehicle3" name="vehicle3" value="Boat">
<label for="vehicle3"> Boat</label><br>
</li>
</ul>
There is a way to make this happen, but it's to use exactly the same "trick" with which you style the <label> elements, specifically by moving the <input> elements ahead of the element you wish to style.
With that in mind, if the <input> elements are preceding siblings of the <div>, then checking, and unchecking, the <input> can have an effect on the <div>, and also the original <label> elements as well.
As a crude example:
input[type="checkbox"][name^="vehicle"] {
display: absolute;
position: absolute;
opacity: 0;
}
/* styles the <div> based on the checked/unchecked state
of the <input> (this example assumes that the same
highlight colour should be used regardless of which
<input> is checked: */
input[type="checkbox"][name^="vehicle"]:checked ~ div {
background-color: #ccc;
}
/* this is where it becomes obvious that JavaScript (or,
ideally, a CSS selector that can refer to an attribute-
variable) makes more sense; though with a CSS
pre-processor this can be written effectively enough.
Here when the #vehicle1 element is checked the <label>
descendents with a "for" attribute equal to "vehicle1" of
later-sibling <ul> elements are selected and styled: */
#vehicle1:checked~ul label[for=vehicle1] {
background-color: gray;
}
/* as above, for the "vehicle2" id and for attributes: */
#vehicle2:checked~ul label[for=vehicle2] {
background-color: gray;
}
#vehicle3:checked~ul label[for=vehicle3] {
background-color: gray;
}
ul li {
display: inline-block;
padding: 20px;
margin: 20px;
}
ul li label {
padding: 20px;
cursor: pointer;
}
<input type="checkbox" id="vehicle1" name="vehicle1" value="Bike">
<input type="checkbox" id="vehicle2" name="vehicle2" value="Car">
<input type="checkbox" id="vehicle3" name="vehicle3" value="Boat">
<div class="modify-box">
BOX TO CHANGED
</div>
<ul>
<li>
<label for="vehicle1"> Bike</label><br>
</li>
<li>
<label for="vehicle2"> Car</label><br>
</li>
<li>
<label for="vehicle3"> Boat</label><br>
</li>
</ul>
With only CSS this won't be possible. You are restricted by the current selectors and there are no parent selectors in CSS. You can use a bit of JS to target the element you want.
What would you like to happen in the box surrounding the checkboxes? Maybe there would be another solution with a :before or :after on the label?
I think you need JavaScript for that. You could listen for the change event and style if no checkbox is checked.
First you need to select the containing list element and attach an event listener to it:
document.querySelector('ul').addEventListener('change', function(e) {...});
In the handler function of the listener you have to check if there is a checked checkbox and depending on that check style your .modify.box (or toggle a class, for example .checked):
if (document.querySelector('input:checked')) {
modify_box.classList.add('checked');
}
else {
modify_box.classList.remove('checked');
}
If you decide to toggle a class you need to add that class to your CSS-definition. For example:
ul li input[type="checkbox"]:checked+label,
.checked {...}
Working example:
const modify_box = document.querySelector('.modify-box');
document.querySelector('ul').addEventListener('change', function(e) {
if (document.querySelector('input:checked')) {
modify_box.classList.add('checked');
}
else {
modify_box.classList.remove('checked');
}
});
ul li {
display: inline-block;
}
ul li input[type="checkbox"]:checked+label,
.checked {
border: 2px solid gray;
background-color: gray;
color: #fff;
transition: all .2s;
}
ul li {
padding: 20px;
margin: 20px;
}
ul li input[type="checkbox"] {
display: absolute;
}
ul li input[type="checkbox"] {
position: absolute;
opacity: 0;
}
ul li label {
padding: 20px;
cursor: pointer;
}
<div class="modify-box">
BOX TO CHANGED
</div>
<ul>
<li>
<input type="checkbox" id="vehicle1" name="vehicle1" value="Bike">
<label for="vehicle1"> Bike</label><br>
</li>
<li>
<input type="checkbox" id="vehicle2" name="vehicle2" value="Car">
<label for="vehicle2"> Car</label><br>
</li>
<li>
<input type="checkbox" id="vehicle3" name="vehicle3" value="Boat">
<label for="vehicle3"> Boat</label><br>
</li>
</ul>
Related
hello how do i prevent the content from collapsing/hiding when i click on Content 1 or 2
.details,
.show,
.hide:target {
display: none;
color: black;
}
.hide:target+.show,
.hide:target~.details {
display: block;
color: black;
}
<a id="hide1" href="#hide1" class="hide">+ Content</a>
<a id="show1" href="#show1" class="show">- Content</a>
<div class="details">
<ul>
<li>Content1</li>
<li>Content2</li>
</ul>
</div>
.hide {
cursor: pointer;
}
.hide::before {
content: '+ Content';
display: block;
}
.hide::after {
content: '- Content';
display: none;
}
.details {
display: none;
transition:all 0.4s linear;
}
input:checked ~ .details,
input:checked + .hide::after {
display: block;
}
input:checked + .hide::before {
display: none;
}
<input id="toggle" type="checkbox" style="visibility:hidden">
<label for="toggle" class="hide"></label>
<div class="details">
<ul>
<li>Content1</li>
<li>Content2</li>
</ul>
</div>
Anchor tags reload the pages and thus the main div is collapsing.
You can either use this.
<li>Content1</li>
<li>Content2</li>
Or if you still want to use href then return false on click which will prevent it from reloading the page.
<li>Content1</li>
<li>Content2</li>
The problem with target is that it disappears from the content +/- when the user clicks on something else.
To remember whether the content + or - has been clicked you can use a checkbox.
If you make the +/- content into labels instead of divs then they can be associated with the checkbox (using for=) and you can hide the actual checkbox.
#showhide {
position: absolute;
opacity: 0;
}
#showhide~#show {
display: block;
}
#showhide:checked~#show {
display: none;
}
#showhide~#hide {
display: none;
}
#showhide:checked~#hide {
display: block;
}
#showhide~.details {
display: none;
}
#showhide:checked~.details {
display: block;
}
<input id="showhide" type="checkbox">
<label for="showhide" id="show">+ Content</label>
<label for="showhide" id="hide">- Content</label>
<div class="details">
<ul>
<li>Content1</li>
<li>Content2</li>
</ul>
</div>
This question already has answers here:
Can I have an onclick effect in CSS?
(14 answers)
Closed 3 years ago.
I tried many ways to change the color of the border of my image when the checkbox is checked and I didn't find a solution. I start wondering if it's possible.
.thumbs {
list-style:none;
margin:0;
padding:0.3em 0;
text-align:center;
color:#fff;
}
.thumbs li {
position:relative;
display:inline-block;
margin:0.2em;
border:0.30em solid #000000 ;
border-radius:0.3em;
}
.thumbs li:hover { border-color: #59b359; }
input[type=checkbox]:checked + .thumbs li { border-color: #ff0000; }
<form id="formdelete">
<ul class="thumbs">
<li class="img">
<label for="SNAP_CH01.jpg">
<img src="SNAP_CH01.jpg" title="CH1">
<input type="checkbox" name="todelete[]" value="SNAP_CH01" id="SNAP_CH01.jpg">
</li>
<li class="img">
<label for="SNAP_CH02.jpg">
<img src="SNAP_CH02.jpg" title="CH2">
</label>
<input type="checkbox" name="todelete[]" value="SNAP_CH02" id="SNAP_CH02.jpg">
</li>
<li class="img">
<label for="SNAP_CH03.jpg">
<img src="SNAP_CH03.jpg" title="CH3">
</label>
<input type="checkbox" name="todelete[]" value="SNAP_CH03" id="SNAP_CH03.jpg">
</li>
</form>
The border should be red when the checkbox is checked
EDIT :
I find a solution using the link :
I have to change the order of the checkbox but it's work fine :
<ul class="thumbs">
<li class="img">
<input type="checkbox" name="todelete[]" value="SNAP_CH01" id="SNAP_CH01.jpg">
<label for="SNAP_CH01.jpg">
<img src="SNAP_CH01.jpg" title="CH1">
</label>
</li>
label > img {
display: block;
border: 3px solid #000000 ;
}
input[type=checkbox]:checked + label > img { border: 3px #FF0000 solid ;}
So, the adjacent sibling selector + https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator will target the element immediately AFTER the element being referenced.
In your code, input[type=checkbox]:checked + .thumbs li it is looking for a class for thumbs immediately after the checkbox. In this case, .thumbs is the name of the (grand) parent UL item.
The most important letter in CSS is the C -- Cascading. The styles move down the DOM tree, you will need creative ways to affect something above.
I am trying to create a responsive navbar, so when you click a hidden checkbox the content unhides.
The problem is, I can't get the "checked" css to actually pick up and do anything.
Example to run here: http://codepen.io/anon/pen/KNvvZy
CSS:
#nav-hidden{background: red; display: none;}
#navigation-mobile{display:none;}
/* DESKTOP */
#media only screen and (max-width: 1200px) {
#navigation-mobile {display: block;}
#menu-toggle:checked ~ #nav-hidden {
opacity: 1;
height: 100vh;
visibility: visible;
}
.label-toggle {
cursor: pointer;
display: block;
float: right;
}
}
HTML:
<div id="navigation-mobile">
<input type="checkbox" id="menu-toggle">
<label for="menu-toggle" class="label-toggle"></label>
</input>
<div id="nav-hidden">
<ul>
<li>test</li>
<li>test</li>
</ul>
</div>
</div>
In your example, on the original state you have:
#nav-hidden{display:none;}
So, you'll need to reset it on :checked state:
#menu-toggle:checked ~ #nav-hidden {display:block;}
Also want to point out that, you can animate height, opacity, visibility etc., but you can't animate display property.
The <input> element is a self-closing tag, you can do <input> or <input />, but you can't do <input></input>.
#nav-hidden {
display: none;
}
#menu-toggle:checked ~ #nav-hidden {
display: block;
}
<div id="navigation-mobile">
<input type="checkbox" id="menu-toggle">
<label for="menu-toggle" class="label-toggle"></label>
<div id="nav-hidden">
<ul>
<li>test</li>
<li>test</li>
</ul>
</div>
</div>
What I'm trying to accomplish:
Removing the bottom border on the nested list-item element, but keeping the bottom border of its parent list-item element.
I'm trying to figure out if I can use a "universal selector", like ">*" to say: "For everything element that lives in this parent, make the border 0".
Question:
Is this possible?
See the fiddle: http://jsfiddle.net/VnLZH/
HTML:
<aside>
<b>What I'm trying to accomplish: </b><br>
1.) Removing the bottom border on the nested list-item element, but keeping the bottom border of its parent list-item element. <br>
2.) I'm trying to figure out if I can use a "universal selector", like ">*" to say: "For everything element that lives in this parent, make the border 0". <br><br>
<b>Question</b><br>
Is this possible?
</aside>
<h1>This works</h1>
<div class="option1">
<ul>
<li>Category</li>
<li>Category</li>
<li>Category</li>
<li>Category
<div>
<ul>
<li><input type="radio" name="radio" /> Option 1</li>
<li><input type="radio" name="radio" /> Option 2</li>
<li><input type="radio" name="radio" /> Option 3</li>
</ul>
</div>
</li>
<li>Category</li>
<li>Category</li>
</ul>
</div>
<h1>What I want to work</h1>
<div class="option2">
<ul>
<li>Category</li>
<li>Category</li>
<li>Category</li>
<li>Category
<div>
<ul>
<li><input type="radio" name="radio" /> Option 1</li>
<li><input type="radio" name="radio" /> Option 2</li>
<li><input type="radio" name="radio" /> Option 3</li>
</ul>
</div>
</li>
<li>Category</li>
<li>Category</li>
</ul>
</div>
CSS:
aside { background: #f2f2f2; margin: 1em 0; padding: .5em; }
h1 { margin: 1em 0 0; }
/* This works */
.option1 { }
.option1 ul { }
.option1 ul li { border-bottom: 1px solid black; }
.option1 ul li div ul li { border: none; }
/* What I want to work */
.option2 { }
.option2 ul { }
.option2 ul li { border-bottom: 1px solid black; }
.option2 ul li div >* { border: none; }
Your code (.option2 ul li div > *) doesn't work because the lists themselves have no borders, but the list items do. Thus, .option2 ul li div ul > * would work, but moreover, even specifying .option2 ul li * would target any element nested within a list item of the option2 list.
.option2 ul li { border-bottom: 1px solid black; }
.option2 ul li * { border: none; } //removes border on nested elements of any kind
I misunderstood
Just remove the ">" and you should be fine
http://jsfiddle.net/VnLZH/9/
.option2 ul li div * { border: none; }
I have got a menu list:
<ul>
<li class="marked">First item</li>
<li>Second much longer than first item</li>
</ul>
I would like to have an image marker on top of item.marked which width will be 100% of text width. The image must stretch so it will be completely visible. Height is constant.
Can this be done with CSS and IE compatibility?
<style type="text/css">
.selected {
background:url("example.png") no-repeat 0 100%;
}
</style>
Solutions for changing background of list item (can be adapted to change an image):
1. CSS-only, persistent, works for current versions of browsers (doesn't work for IE8 and older) - DEMO.
HTML:
<ul>
<li>
<input type="radio" name="s" id="o1" checked>
<label for="o1">First item</label>
</li>
<li>
<input type="radio" name="s" id="o2">
<label for="o2">Second much longer than first item</label>
</li>
</ul>
Relevant CSS:
ul input[type=radio] {
display: none;
}
input[type=radio]:checked + label {
background: lightblue;
}
If you want to have an image (with img tag) above the selected items, then you can adapt it like in this demo.
HTML:
<ul>
<li>
<input type="radio" name="s" id="o1" checked>
<label for="o1">First item
<img src="http://upload.wikimedia.org/wikipedia/commons/5/5b/Supernumerary_rainbow_03_contrast.jpg">
</label>
</li>
<li>
<input type="radio" name="s" id="o2">
<label for="o2">Second much longer than first item
<img src="http://upload.wikimedia.org/wikipedia/commons/5/5b/Supernumerary_rainbow_03_contrast.jpg">
</label>
</li>
</ul>
And add the following CSS:
label img {
top: 0;
width: 100%;
height: 100%;
display: none;
position: absolute;
}
input[type=radio]:checked + label img {
display: block;
}
If you don't want to do it with an img tag, then you can use a background-image on a pseudo-element and set the background-size to 100% 100%, like in this demo. The HTML is the same as in the first demo and you need to also have this in the CSS:
label {
position: relative;
}
input[type=radio]:checked + label:after {
top: 0;
right: 0;
bottom: 0;
left: 0;
position: absolute;
background: url(http://upload.wikimedia.org/wikipedia/commons/5/5b/Supernumerary_rainbow_03_contrast.jpg);
background-size: 100% 100%;
content: '';
}
2. CSS-only, not persistent (list item does not stay selected when you click somewhere else on the page), works for IE8 (and also IE7, but you have to hover off the text to see the change) - DEMO.
HTML:
<ul>
<li>First item</li>
<li>Second much longer than first item</li>
</ul>
Relevant CSS:
a:active, a:focus {
outline: none;
background: lightblue;
}