Could someone explain how the last part of the code works? Specifically:
[type=radio]:checked {
}
[type=radio]:checked ~ .content {
z-index: 1;
}
I'm just starting with CSS as a newb and wanted to try to create some interactive CSS tabs; which lead me to look at some existing code out there. Needless to say it has left me quite confused.
Why is [type=radio]:checked needed? It had z-index: 2; inside the brackets but I took that out and the code still works just fine; although when I try and delete [type=radio]:checked all together the code breaks. Why? It has no properties currently.
[type=radio]:checked ~ .content used to be [type=radio]:checked ~ label ~ .content but I took out label and it still works fine. Why was it ever needed?
HTML:
<div class="tab">
<input type="radio" id="tab-1" name="tab-group-1" checked>
<label for="tab-1">Tab One</label>
<div class="content">
tab#1
</div>
</div>
<div class="tab">
<input type="radio" id="tab-2" name="tab-group-1">
<label for="tab-2">Tab Two</label>
<div class="content">
tab#2
</div>
</div>
<div class="tab">
<input type="radio" id="tab-3" name="tab-group-1">
<label for="tab-3">Tab Three</label>
<div class="content">
tab#3
</div>
</div>
</div>
</html>
CSS:
.tabs {
position: relative;
height: 200px; /* This part sucks */
clear: both;
margin: 25px 0;
}
.tab {
float: left;
}
.tab label {
background: #eee;
padding: 10px;
border: 1px solid #ccc;
margin-left: -1px;
position: relative;
left: 1px;
}
.tab [type=radio] {
display: none;
}
.content {
position: absolute;
top: 28px;
left: 0;
background: white;
right: 0;
bottom: 0;
padding: 20px;
border: 1px solid #ccc;
}
[type=radio]:checked {
}
[type=radio]:checked ~ .content {
z-index: 1;
}
The last part of your CSS:
[type=radio]:checked {
}
[type=radio]:checked ~ .content {
z-index: 1;
}
This is giving a z-index to the class content. Since only one tab is clicked it is giving a z-index to only one content class and that makes it display. (Since no others have a z-index)
If you want to see how it works then add a z-index to the content class, lets say 10, in your CSS and watch how it gets all screwy. Now since that code is only giving a z-index: 1; it doesn't display correctly since they all have 10 in this example. Now go to the above snidbit of code and put a z-index: 11; and watch how it works correctly. Since only one gets a high z-index: 11; it becomes the displaying one.
If you don't know what the [type=radio]:checked means, it is pertaining to an active state or clicked state for that radio input.
This part of code: [type=radio]:checked ~ label ~ .content is allowing a more distinguished and precise selection of a DOM element. It will work without it because .content is below the radio tag. It will only apply to an element that is 1. input radio > 2. label > 3. .content.
If you also don't know what z-index does then let me know and I'll brake that down.
Related
The background color in each todo-section does not cover the entire row when the checkbox is selected. The background color does not reach behind the checkbox. This is one of the todo-sections in my html from the form. It's one of 13 set up the exact same way. Please click the [enter image description here] link above for a visual of what I'm trying to convey.
Below is the associated CSS. The issue that I'm having is that when the box is checked, the line strikes through the text like it's supposed to and the associated color appears in the background as well. However, the color isn't reaching behind the checkbox. Screenshot provided above in link.
.todo-section [type=checkbox]:checked+label {
text-decoration: line-through;
background-color: #D7B99E;
}
.todo-section {
display: flex;
flex-direction: row;
border-bottom: 1px solid #000000;
}
<form>
<div class="todo-section">
<input type="checkbox" id="todo1" name="todo1" value="ID"><label for="todo1" class="checked"> Please bring picture ID and insurance card on the day of your
procedure.</label> </div>
</form>
There is no way to select a parent in CSS, however, there's still some "magic" to achieve this if you work with the positioning of the elements.
.todo-section [type=checkbox]:checked+label {
text-decoration: line-through;
background-color: #D7B99E;
}
input {
position: absolute;
z-index: 10;
}
label {
width: 100%;
position: absolute;
top: 0;
left: 0;
text-indent: 30px;
z-index: 1;
}
.todo-section {
display: flex;
flex-direction: row;
border-bottom: 1px solid #000000;
position: relative;
height: 20px;
}
<form>
<div class="todo-section">
<input type="checkbox" id="todo1" name="todo1" value="ID"><label for="todo1" class="checked"> Please bring picture ID and insurance card on the day of your
procedure.</label>
</div>
</form>
While support is lacking currently, in the future, the :has() pseudo-class does what you want.
In this case, it will target the entire .todo-section, rather than just the label as the original selector did.
Note that version 105+ of Chrome supports the selector, and I would expect other Chromium-based browsers to follow suit soon as well. In fact, my copy of Microsoft Edge (Version 103.0.1264.77 (Official build) (64-bit)) renders the following snippet correctly, even though technically it shouldn't be able to...
.todo-section:has([type=checkbox]:checked) {
text-decoration: line-through;
background-color: #D7B99E;
}
.todo-section {
display: flex;
flex-direction: row;
border-bottom: 1px solid #000000;
}
<form>
<div class="todo-section">
<input type="checkbox" id="todo1" name="todo1" value="ID"><label for="todo1" class="checked"> Please bring picture ID and insurance card on the day of your
procedure.</label> </div>
</form>
You may also use grid and set both elements inside the same cell (alike absolute but in the flow), padding and margin can be used to align elements and keep their content away from each others.
here is an example:
.todo-section [type=checkbox]:checked+label {
text-decoration: line-through;
background-color: #D7B99E;
}
.todo-section {
border-bottom: 1px solid #000000;
}
/* grid layout VS absolute */
/* base needed */
.todo-section {
display: grid;
}
.todo-section>* {
grid-row: 1;
grid-column: 1
}
/*demo makeup */
.todo-section {
margin:1em 5em;
background:#bee
}
input {
margin: auto;
margin-inline-start: 0.5em; /* will follow the document direction */
position: relative; /*To keep it on top
or use
transform:scale(1) ;
or any transform value that is set to defaut */
}
label {
padding-inline-start: 2em; /* will follow the document direction */
}
<form>
<div class="todo-section">
<input type="checkbox" id="todo1" name="todo1" value="ID">
<label for="todo1" class="checked"> Please bring picture ID and insurance card on the day of your
procedure.</label>
</div>
<div class="todo-section" dir="rtl">
<input type="checkbox" id="todo2" name="todo1" value="ID">
<label for="todo2" class="checked"> Please bring picture ID and insurance card on the day of your
procedure.</label>
</div>
</form>
I'm working on a site that needs to (a) work without JavaScript and (b) be keyboard-accessible.
I have used the label target trick to build a tab view (https://css-tricks.com/functional-css-tabs-revisited/), but I've noticed that it relies on the label being clicked. I can't figure out how to make it work with the keyboard. Is this possible?
.tabs {
background-color: #eee;
min-height: 400px;
}
.tabs__list {
border-bottom: 1px solid black;
display: flex;
flex-direction: row;
list-style: none;
margin: 0;
padding: 0;
position: relative;
}
.tabs__tab {
padding: 0.5rem;
}
.tabs__content {
display: none;
left: 0;
padding: 0.5rem;
position: absolute;
top: 100%;
}
.tabs__input {
display: none;
}
.tabs__input+label {
cursor: pointer;
}
.tabs__input:focus,
.tabs__input:hover {
color: red;
}
.tabs__input:checked+label {
color: red;
}
.tabs__input:checked~.tabs__content {
display: block;
}
<div class="tabs">
<ul class="tabs__list">
<li class="tabs__tab">
<input class="tabs__input" type="radio" id="tab-0" name="tab-group" checked>
<label for="tab-0" class="tabs__label" tabindex="0" role="button">Tab 0</label>
<div class="tabs__content">
Tab 0 content
</div>
</li>
<li class="tabs__tab">
<input class="tabs__input" type="radio" id="tab-1" name="tab-group">
<label for="tab-1" class="tabs__label" tabindex="0" role="button">Tab 1</label>
<div class="tabs__content">
Tab 1 content
</div>
</li>
</ul>
</div>
Accepted answer is not an accessible solution.
I have made some corrections and some observations here. Do not use the accepted answer in production if you stumble across this question in the future. It is an awful experience with a keyboard.
The answer below fixes some of the CSS issues to make it more accessible.
However I would recommend you reconsider the no JavaScript requirement.
I can understand having a good fall-back (which the example I give below with the fixes is) but there is no way you can make a fully accessible set of CSS only tabs.
Firstly you should use WAI-ARIA to complement your HTML to make things even more clear for screen readers. See the tabs examples on W3C to see what WAI-ARIA roles you should be using. This is NOT possible without JavaScript as states need to change (aria-hidden for example should change).
Secondly, you should be able to use certain shortcut keys. Press the home key for example in order to return to the first tab, something you can only do with a little JS help.
With that being said here are a few things I fixed with the accepted answer to at least give you a good starting point as your 'no JavaScript fallback'.
Problem 1 - tabindex on the label.
By adding this you are creating a focusable element that cannot be activated via keyboard (you cannot press space or Enter on the label to change selection, unless you use JavaScript).
In order to fix this I simply removed the tabindex from the labels.
Problem 2 - no focus indicators when navigating via keyboard.
In the example the tabs only work when you are focused on the radio buttons (which are hidden). However at this point there is no focus indicator as the styling is applying styling to the checkbox when it is focused and not to its label.
In order to fix this I adjusted the CSS with the following
/*make it so when the checkbox is focused we add a focus indicator to the label.*/
.tabs__input:focus + label {
outline: 2px solid #333;
}
Problem 3 - using the same state for :hover and :focus states.
This is another bad practice that needs to go away, always have a different way of showing hover and focus states. Some screen reader and screen magnifier users will use their mouse to check they have the correct item focused and orientate themselves on a page. Without a separate hover state it is difficult to check you are hovered over a focused item.
/*use a different colour background on hover, you should not use the same styling for hover and focus states*/
.tabs__label:hover{
background-color: #ccc;
}
Example
In the example I have added a hyperlink at the top so you can see where your focus indicator is when using a keyboard.
When your focus indicator is on one of the two tabs you can press the arrow keys to change tab (which is expected behaviour) and the focus indicator will adjust accordingly to make it clear which tab was selected.
.tabs {
background-color: #eee;
min-height: 400px;
}
.tabs__list {
border-bottom: 1px solid black;
display: flex;
flex-direction: row;
list-style: none;
margin: 0;
padding: 0;
position: relative;
}
.tabs__tab {
padding: 0.5rem;
}
.tabs__content {
display: none;
left: 0;
padding: 0.5rem;
position: absolute;
top: 100%;
}
.tabs__input {
position: fixed;
top:-100px;
}
.tabs__input+label {
cursor: pointer;
}
.tabs__label:hover{
background-color: #ccc;
}
.tabs__input:focus + label {
outline: 2px solid #333;
}
.tabs__input:checked+label {
color: red;
}
.tabs__input:checked~.tabs__content {
display: block;
}
A link so you can see where your focus indicator is
<div class="tabs">
<ul class="tabs__list">
<li class="tabs__tab">
<input class="tabs__input" type="radio" id="tab-0" name="tab-group" checked>
<label for="tab-0" class="tabs__label" role="button">Tab 0</label>
<div class="tabs__content">
Tab 0 content
</div>
</li>
<li class="tabs__tab">
<input class="tabs__input" type="radio" id="tab-1" name="tab-group">
<label for="tab-1" class="tabs__label" role="button">Tab 1</label>
<div class="tabs__content">
Tab 1 content
</div>
</li>
</ul>
</div>
It is just radio buttons... Keyboard can be used to navigate through them using tab and space bar to check them.
I'd use :focus to highlight the chosen tab and the tabindex property to make it work as I wanted.
Please provide more dept if you have problem with a SPECIFIC problem related to it, and provide a basic code example here, no linking.
Since hidden inputs cannot be selected through keyboard, make them visible...
.tabs {
background-color: #eee;
min-height: 400px;
}
.tabs__list {
border-bottom: 1px solid black;
display: flex;
flex-direction: row;
list-style: none;
margin: 0;
padding: 0;
position: relative;
}
.tabs__tab {
padding: 0.5rem;
}
.tabs__content {
display: none;
left: 0;
padding: 0.5rem;
position: absolute;
top: 100%;
}
.tabs__input {
position: fixed;
top:-100px;
}
.tabs__input+label {
cursor: pointer;
}
.tabs__input:focus
.tabs__input:hover {
color: red;
}
.tabs__input:checked+label {
color: red;
}
.tabs__input:checked~.tabs__content {
display: block;
}
<div class="tabs">
<ul class="tabs__list">
<li class="tabs__tab">
<input class="tabs__input" type="radio" id="tab-0" name="tab-group" checked>
<label for="tab-0" class="tabs__label" tabindex="0" role="button">Tab 0</label>
<div class="tabs__content">
Tab 0 content
</div>
</li>
<li class="tabs__tab">
<input class="tabs__input" type="radio" id="tab-1" name="tab-group">
<label for="tab-1" class="tabs__label" tabindex="0" role="button">Tab 1</label>
<div class="tabs__content">
Tab 1 content
</div>
</li>
</ul>
</div>
Basically I have a div that I'm trying to figure out how to increase the width based on checkboxes selected, and add to that width as more become checked.
Example HTML (sorry if the syntax is a bit off I'm writing from memory):
<div class="barDiv"></div>
<label for="cb50"><h2>Click me to add 50!</h2></label>
<input type="checkbox" id="cb50">
<label for="cb30"><h2>Click me to add 30!</h2></label>
<input type="checkbox" id="cb30">
Example SCSS:
$add: 0px;
.barDiv {
width: $add;
height: 10px;
background-color: #444;
}
#cb50:checked {
~ .barDiv {
width: $add + 50px;
}
}
#cb30:checked {
~ .barDiv {
width: $add + 30px;
}
}
If I wrote it right then my setup works individually, but I want the width to be 80px when both are checked and instead it just switches between the two widths. I know I've seen this done with LESS and I'm hoping it's doable with SCSS as well. Thanks for any help!
For this to work you need the .barDiv to appear under both checkboxes in the DOM (the ~ selector is for next siblings, not prev).
You will also need to create the rule for when both checkboxes are checked.
Here is an example with pure css (note the sass is eventually compiled to css), I hope it is what you are looking for:
.barDiv {
width: 0;
height: 10px;
background-color: #444;
}
#cb50:checked ~ .barDiv {
width: 50px;
}
#cb30:checked ~ .barDiv {
width: 30px;
}
#cb50:checked ~ #cb30:checked ~ .barDiv {
width: 80px;
}
<label for="cb50"><h2>Click me to add 50!</h2></label>
<input type="checkbox" id="cb50">
<label for="cb30"><h2>Click me to add 30!</h2></label>
<input type="checkbox" id="cb30">
<div class="barDiv"></div>
I am playing around with this template. When incorporating the functionality into the sort of dashboard I am building, everything works fine except that I get an unwanted empty space of a few px above the tabs, when decreasing the font size. I have created a minimal working example:
HTML:
<div class="tab">
<input type="radio" id="tab-1" name="tab-group-1" checked>
<label for="tab-1">Tab One</label>
</div>
<div class="tab">
<input type="radio" id="tab-2" name="tab-group-1">
<label for="tab-2">Tab Two</label>
</div>
CSS:
* {
padding: 0;
margin: 0;
}
body {
background: #003399;
}
.tab {
float: left;
}
.tab label {
background: #eee;
position: relative;
font-size: 16px;
}
.tab [type=radio] {
display: none;
}
https://jsfiddle.net/tqejgae0/
See the extra blue space above the tabs when using Firefox? It looks as expected in Chromium, Chrome, Opera, and Safari.
There are a lot of similar questions on Stackoverflow, most of them solved with
* {
padding: 0;
margin: 0;
}
Neither this, nor any of the other solutions worked for me.
Web Design is certainly not my background, so I am thankful for any help!
Edit:
Here's a screenshot:
Adding display:block to the .tab label selector solved the problem for me.
.tab label {
background: #eee;
position: relative;
font-size: 16px;
display: block;
}
https://jsfiddle.net/tqejgae0/2/
Screenshot:
This question already has answers here:
How to style a checkbox using CSS
(43 answers)
Closed 8 years ago.
Actually I'm styling the radio button with this trick:
HTML:
<div class="radioButt" >
<h1>Radio:</h1>
<p>Val1 : <span></span><input type="radio" id="1" checked="checked" name="radio" ><span></span></p>
<p>Val2 : <span></span><input type="radio" id="2" name="radio" ><span></span></p>
<p>Val3 : <span></span><input type="radio" id="3" name="radio" ><span></span></p>
</div>
CSS:
.radioButt p {
padding: 10px;
}
.radioButt span{
position: relative;
right: 0;
width: 25px;
height: 25px;
line-height: 25px;
padding: 3px;
color: #FFF;
text-align: center;
background: #c06f59;
}
.radioButt span:after{
content: "no"; /*if CSS are disbled span elements are not displayed*/
}
.radioButt input{
position: relative;
right: 0;
margin: -26px;
width: 31px;
height: 31px;
/*hide the radio button*/
filter:alpha(opacity=0);
-moz-opacity:0;
-khtml-opacity: 0;
opacity: 0;
cursor: pointer;
}
.radioButt input[type="radio"] + span{ /*the span element that immediately follow the radio button */
visibility: hidden; /*temporarily hide the "YES" label*/
background: #6EB558;
}
.radioButt input[type="radio"] + span:after{
width: 30px;
display: inline-block;
content: "yes"; /*if CSS are disbled span elements are not displayed*/
}
.radioButt input[type="radio"]:checked + span{
visibility: visible; /*show the "YES" label only if the radio button is checked*/
}
A working example could be found at: http://jsfiddle.net/rzt3c/2/
I want to create the same effect also for the checkbox input.
I tried to add the type "checkbox" in the css but it seem to don't work...infact when the checkbox is checked id doesn't return unchecked. ( Here there is the code: http://jsfiddle.net/rkCMa/1/ )
UPDATED ANSWER
The reason below is still correct, but there's a much easier way to do it still with CSS (bearing usability restraints still...) by using the pointer-events style. Add this to your styles:
.radioButt span{
pointer-events: none;
}
That will allow the spans to be clicked through so the post span won't block the input anymore. This should answer your question, but do keep in mind some of the usibility issues mentioned in the comments to your original question.
The reason its not working is when it displays the "Yes" that span is over the input and so it is the span that is actually being clicked and not the input. I would change the formatting so that both of the spans are before the input, and use classnames on them to distinguish and style them rather than css selectors. Something like:
<div class="radioButt" >
<h1>Checkbox:</h1>
<p>Ck1 : <span class="no"></span><span class="yes"></span><input type="checkbox" id="ck1" checked="checked" ></p>
<p>Ck2 : <span class="no"></span><span class="yes"></span><input type="checkbox" id="ck2" ></p>
<p>Ck3 : <span class="no"></span><span class="yes"></span><input type="checkbox" id="ck3" ></p>
</div>