I'm trying to create tabs with CSS using radio buttons and the ~. My tabs work if the radio buttons are before the content containers but not when after.
I want them to be after since one of the tab buttons gets hidden and replaced with an actual button while it's selected and its really tough to do this in a generalized way if I have to take the radio buttons out of the flow.
So in essence, if I have this:
#content { visibility:hidden }
#cb:checked ~ #content { visibility:visible }
<input type="checkbox" id="cb">
<div id="content">stuff</div>
Is there a way to flip the order of the input and the div and still have it work?
No, there is no "previous sibling" (nor "parent/ancestor") combinator.
In theory, if you are willing to use flexbox, then you could use the order property to swap the display order while retaining the DOM order. Here's the general idea (not tested):
#container { display: flex; }
#content { visibility:hidden; order: 1; }
#cb { order: 2; }
#cb:checked ~ #content { visibility:visible }
<div id="container">
<input type="checkbox" id="cb">
<div id="content">stuff</div>
</div>
Normal disclaimers apply to browser support for flexbox.
By the way, the name of the "tilde thingy" is "general sibling combinator".
Related
I know it's very easy to do it with JavaScript. For example, if I want to hide all children after 50th, I just need to do:
$("#container").find('div').each(function(){
if ($(this).index() > 50) $(this).hide();
})
But is it possible to do it with pure CSS?
Note:
The total children number is not a fixed one. It may change (by other JavaScript codes
I only need to support Chrome so no need to consider other browsers
I don't have access to the HTML DOM itself (because I am building a Chrome Extension)
Update:
Sorry that I want to hide from a to All the next (the last one) children. I have edited my question. It's NOT from a~b.
div are the only children. There are NO other children in this container.
.container div:nth-child(n+51) {
display:none;
}
n is the cycle number, 51 is the offset so will start on the 51st item, then repeat every 1 item.
Another idea is to use the ~ selector in order to hide all the element after a particular one:
.container div:nth-child(51) ~ * {
display:none;
}
Here is an example:
.container div:nth-child(5) ~ * {
display: none;
}
.container div {
height:20px;
width:20px;
display:inline-block;
border:1px solid;
background:red;
}
<div class="container">
<div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
</div>
I am trying to have a checkbox change the content of a div but if the content isn't together (in the same div), then it will not work.
HTML:
<div>
<input type="checkbox" id="check">
<label for="check">Hello</label>
</div>
<div class="check"></div>
CSS:
.check:before {
display: block;
width: 100px;
height: 100px;
background: red;
content:'';
}
input:checked ~ .check:before {
content:'Content';
}
JSFiddle: https://jsfiddle.net/pgkwn4j6/
In your example one thats working is using "input:checked ~ .check:before" which selects "check" class div that is preceeding right after the input that is checked(sibling elements).
When you the put the label and input in a different div tag you need to select parent`s sibling which is not possible through css.
You can do it through Jquery.
CSS: how to select parent's sibling
above question showcases very similar problem you are having.
It does not work because it is not in the same div, in css you can not manipulate any element outside the parent element. To be able to manipulate an element outside you have to use jquery. Here your JSfiddle correct link:
JSFiddle Correct
$(document).ready(function(e) {
$('input#check').click(function(){
$('.check').toggleClass('show-content');
});
});
I just came across the switch toggle button which is created only using css. It known as the checkbox hack.
For those who doesn't know what a checkbox css hack is, Please read it here
https://css-tricks.com/the-checkbox-hack/
I tried it out and it was working perfectly fine. But I didn't understand how this is working because we are not clicking on the checkbox.
So I have 2 questions
How is this working ?
Instead of absolute positioning I tried it with display: none;
It still worked. Does this method have any drawbacks?
The way it works is by using the <label> element. Any input element can (and usually should) have a label. You can tell the browser which label belongs to which label by using a for attribute, referring to the input's name:
<input name="myName" />
<label for="myName">Label</label>
Whenever you click the label, it focuses the input (or in case of checkboxes, toggles it).
The label and checkbox don't have to be near each other. You could add a few hidden checkboxes at the start or end of a document and place the labels anywhere on the page, and they'd still focus the input.
Hiding the checkbox through display: none could cause buggy behavior on certain browsers. Just hiding it from view by a position: absolute is safer.
You can bind labels to checkboxes/radios using the for= attribute. When this is set, clicking on the label toggles the checkbox. This is a standard HTML attribute.
You can hide the checkbox using display: none, but do test it to make sure that its value is still submitted with the form.
CSS is aware of the current checked state of a checkbox input
This awareness, in combination of siblings selectors such as + (immediate next sibling) and ~ (next sibling somewhere) allows styling different styles, for checked/unchecked states, to anything that comes after the input element. The key here is the word "after".
Basic example:
/* styles when checkbox is unchecked */
div{ border:2px solid blue; margin:10px }
div h3{ color:red; }
/* when checkbox is checked */
input:checked ~ div{ background:blue; }
input:checked ~ div h3{ color:gold; }
<input type=checkbox>
<div><h3>very<h3></div>
<div><h3>cool<h3></div>
As others have said (but is not a must) - HTML label element allows to interact with input elements, and in checkbox/radio types' case - it allows to toggle their checked state by clicking the label itself, which is "linked" to a specific input element by the for attribute:
<label for='x`>click</label>
and the id attribute no the linked input:
<input type='checkbox' id='x'>
For the method to work, the input element must to be placed before whatever element(s) it is intended to control via CSS.
In real-word use cases, one would often want to use the CSS-toggling features of a checkbox over next siblings, but to obscure the fact there is a checkbox involved. The best way is by applying the hidden attribute on the input, which only toggles off the rendering of the input, nothing else.
The example below showcase such use case for a simple accordion component:
Practical example: Accordion
.accordion{ width: 300px; border: 1px solid silver; }
.accordion label{ display:block; padding:1em; cursor:pointer; }
.accordion label:hover{ color:red; }
.accordion > div:not(:last-child){ border-bottom:1px solid silver; }
.accordion .more{ max-height:0; transition:.5s; color:green; padding:0 1em; overflow: hidden; }
/* checked toggled */
.accordion input:checked + .content{ background:#EEE; }
.accordion input:checked + .content .more{ max-height:200px; }
<div class='accordion'>
<div>
<input type='checkbox' id='checkbox_item_1' hidden>
<div class='content'>
<label for='checkbox_item_1'>Title 1</label>
<div class='more'>
<p>This is cool<p>
<p>Yes it is</p>
</div>
</div>
</div>
<div>
<input type='checkbox' id='checkbox_item_2' hidden>
<div class='content'>
<label for='checkbox_item_2'>Title 2</label>
<div class='more'>
<p>This is also cool</p>
<p>So much fun</p>
</div>
</div>
</div>
</div>
You can hide the checkbox with visibility: hidden; or opacity: 0; besides display: none; but i'm not sure which one is better.
I have twp elements inside my Div,both have same class name. I want to hide my first element with the class name .cart. I am using the below code.
.component-bottom .component-basket + .cart{
display:none;
}
<div class="component-bottom">
<div class="component-basket">
<div class="cart">
</div>
<div class="cart">
</div>
</div>
</div>
Am I using the correct code?
You can use a direct child selector for the .cart element:
.component-bottom .component-basket > .cart
{
display:none;
}
Now you only want the first element of this selector. There isn't an original selector for this, but you can make a overwrite selector for this.
You can overwrite all but the first one ElementA ~ ElementB:
.component-bottom .component-basket > .cart ~ .cart
{
display:block;
}
This search for all .cart elements inside .component-basket where ANY previous adjacent sibling is .cart. The first of the element doesn't have a previous sibling of this class, so it would not be selected.
This is called a general sibling selector.
jsFiddle
This should support IE7 and above:
Note Requires Windows Internet Explorer 7 or later.
source: http://msdn.microsoft.com/en-us/library/ie/aa358824(v=vs.85).aspx
an easier solution commented by #jrConway:
Make it display: block by default and use:
.component-bottom .component-basket > .cart:first-child
{
display: none;
}
Example
Note that this only work when you use ONLY .cart as child element. Whenever an other class is at the first 'place' it will not work.
Using adjacent sibling selector won't work here, as your element is nested inside .component-basket and hence it fails.. Simple way is to call a class on the element you want to hide, if you cannot change the DOM than you can use first-child or nth-of-type(1)
.component-bottom .component-basket div.cart:nth-of-type(1) {
display:none;
}
Demo
As #Vucko already commented, nth-of-type() is a CSS3 spec pseudo..
Hence if you want to support legacy browsers, you can use Selectivizr,
this will save you a lot of classes/ids.
Stick this in your CSS file:
.hide {
display: none;
}
Then add that class to whatever element you want hidden like so:
<div class="component-bottom">
<div class="component-basket">Foo</div>
<div class="component-basket cart hide">Foo</div>
</div>
The advantage of this method is that you get to re-use that "hide" class anywhere you want.
As understood, check this might help
CSS
.cart{
display:none;
}
.component-bottom .component-basket
{
//some common properties
}
HTML
<div class="component-bottom">
<div class="component-basket cart">component-basket Hidden div</div>
<div class="component-basket">component-basket visible div</div>
</div>
This will hide the div with the cart class (the First div)
Thanks,
Dhiraj
I have a checkbox which hides/shows a div. It works when I put the checkbox directly above the div. When I place the checkbox somewhere else in the page (for better usability) it doesnt't work. Is there a way to target a certain div to make the checkbox work from everywhere on the page?
Here is the HTML-code:
<input type="checkbox" id="toggle-result" checked="checked"> </input>
CSS:
input[type=checkbox]:checked ~ div {
display: none;
}
Using CSS, you can select child elements and adjacent elements, so what you are trying to do will work if div is placed right after the checkbox but if you want to make it work when div is somewhere else(above the checkbox), you need to use JavaScript, if it's after, you can use + to select adjacent element or nested adjacent element
Demo
<input type="checkbox" />
<div>Toggle Using CSS</div>
input[type=checkbox]:checked + div {
display: block;
}
div {
display: none;
}
Targetting div which is farther away somewhere (But not before the checkbox) like this
Demo 2
input[type=checkbox]:checked + a + .blah .target {
display: block;
}
.target {
display: none;
}
<input type="checkbox" />
Dummy Link
<div class="blah">
<div class="target">Complicated Selector, Isn't It?</div>
</div>
Explanation : input[type=checkbox]:checked + a + .blah .target Over
here we select the checkbox which is in a checked state, and than we
chain this by selecting the adjacent element which is an anchor tag,
and than we select another adjacent element which is adjacent to a
tag which is div with a class .blah, and than we select nested child element with a class .target
Using jQuery To Do (Doesn't matter where the target element is) Demo 3
<input type="checkbox" id="checkme" />
Dummy Link
<div id="show_on_check" style="display:none">
This content should appear when the checkbox is checked
</div>
$(document).ready(function() {
$('#checkme').change(function() {
$('#show_on_check').toggle();
});
});
input[type=checkbox]:checked ~ div {
display: none;
}
Will select every div element that is preceded by a input that is checked. The reason why it probably breaks is because the input is not preceding the div (Like you state in your question)
Use the element IDs in your selectors:
<input type="checkbox" id="toggle-result" checked="checked"/>
<div id="myDiv">showme</div>
<style>
#toggle-result:checked ~ #myDiv {
display: none;
}
</style>