Checkboxes behind a div turned visible when their opacity is changed [duplicate] - html

This question already has answers here:
What has bigger priority: opacity or z-index in browsers?
(8 answers)
Stacking order of elements affected by opacity
(2 answers)
Why can't an element with a z-index value cover its child?
(5 answers)
Closed 2 years ago.
I just found a very strange HTML behaviour: a checkbox normally hidden behind another element (like a div) becomes visible if its opacity or the opacity of its container is set below 1.
Here is the basic setup, we have a set of checkboxes behind a grey div:
.checkboxes {
display: flex;
}
.tooltip {
position: absolute;
width: 300px;
height: 20px;
background-color: #ccc;
}
<div class="container">
<div class="tooltip"></div>
<div class="checkboxes">
<div class="checkbox">
<label>
<input type="checkbox">
<span>Foo</span>
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox">
<span>Bar</span>
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox">
<span>Baz</span>
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox">
<span>FooBar</span>
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox">
<span>FooBaz</span>
</label>
</div>
</div>
</div>
As expected, you cannot see the checkboxes. But if we change their opacity or the opacity of their containers, they do become visible:
.checkboxes {
display: flex;
}
.tooltip {
position: absolute;
width: 300px;
height: 20px;
background-color: #ccc;
}
<div class="container">
<div class="tooltip"></div>
<div class="checkboxes">
<div class="checkbox">
<label>
<input type="checkbox">
<span>Foo</span>
</label>
</div>
<div class="checkbox" style="opacity: 0.5">
<label>
<input type="checkbox">
<span>Bar</span>
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox">
<span>Baz</span>
</label>
</div>
<div class="checkbox" style="opacity: 0.5">
<label>
<input type="checkbox">
<span>FooBar</span>
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox">
<span>FooBaz</span>
</label>
</div>
</div>
</div>
Of course we can avoid this by setting the z-index of the grey div:
.checkboxes {
display: flex;
}
.tooltip {
position: absolute;
width: 300px;
height: 20px;
background-color: #ccc;
z-index: 10;
}
<div class="container">
<div class="tooltip"></div>
<div class="checkboxes">
<div class="checkbox">
<label>
<input type="checkbox">
<span>Foo</span>
</label>
</div>
<div class="checkbox" style="opacity: 0.5">
<label>
<input type="checkbox">
<span>Bar</span>
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox">
<span>Baz</span>
</label>
</div>
<div class="checkbox" style="opacity: 0.5">
<label>
<input type="checkbox">
<span>FooBar</span>
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox">
<span>FooBaz</span>
</label>
</div>
</div>
</div>
Therefore, the solution is obvious, but nevertheless I still have a question: why did that happen in the first place? What's the reason for the difference between the first and second snippets?
By the way, as I mentioned in the first paragraph, it's worth mentioning that the checkbox keeps hidden if the opacity is set to 1:
.checkboxes {
display: flex;
}
.tooltip {
position: absolute;
width: 300px;
height: 20px;
background-color: #ccc;
}
<div class="container">
<div class="tooltip"></div>
<div class="checkboxes">
<div class="checkbox">
<label>
<input type="checkbox">
<span>Foo</span>
</label>
</div>
<div class="checkbox" style="opacity: 1">
<label>
<input type="checkbox">
<span>Bar</span>
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox">
<span>Baz</span>
</label>
</div>
<div class="checkbox" style="opacity: 1">
<label>
<input type="checkbox">
<span>FooBar</span>
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox">
<span>FooBaz</span>
</label>
</div>
</div>
</div>

This is caused because opacity causes a new stacking context. This can also happen with the following CSS properties:
opacity
CSS Transforms
Filters
CSS Regions
Paged Media
Rule 8.2: All opacity descendants with opacity less than 1, in tree order, create a stacking context generated atomically.
.checkboxes {
display: flex;
}
.tooltip {
position: absolute;
width: 300px;
height: 20px;
background-color: #ccc;
}
<div class="container">
<div class="tooltip"></div><!-- own stack context and above the other elements -->
<div class="checkboxes">
<div class="checkbox" style="opacity:0.5"><!-- own stack context and later on the painting order than position -->
<label>
<input type="checkbox">
<span>Bar</span>
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox">
<span>Bar</span>
</label>
</div>
</div>
</div>

To understand what happened I have to simplify your example much more :
.checkbox{
opacity: 0.5;
}
.tooltip {
position: absolute;
width: 300px;
height: 20px;
background-color: #ccc;
}
<div class="tooltip"></div>
<div class="checkbox">
<span>Foo</span>
</div>
Now it looks not related to checkbox any more. It just how position elements works :
according to your document flow The .checkbox element comes after .checkbox what means a higher position for .checkbox
why? because you didn't set z-index property for .tooltip what means z-index still auto . and the value of auto does not establish a new local stacking context
see the MDN about z-index auto here
so to resolve this whiteout using z-index :
you need to move the div you want to be at the top at the end and use top:0
.checkbox{
opacity: 0.5;
}
.tooltip {
position: absolute;
width: 300px;
height: 20px;
background-color: #ccc;
top:0;
}
<div class="checkbox">
<span>Foo</span>
</div>
<div class="tooltip"></div>
or using z-index as you mentioned with positive value to create a new local stacking context

Related

I cannot select span:before with CSS

I want to access span elements inside .payment-method. For first span element I want to set image "image1.png" and for second element "image2.png".
Here is my HTML code:
.payment-group .payment-method:nth-child(0){
.payment-method-title label span:before{
content: url(https://icon-library.com/images/delivery-service-icon/delivery-service-icon-6.jpg);
}
}
.payment-group.payment-method:nth-child(1){
.payment-method-title label span:before{
content: url(https://icon-library.com/images/bank-transfer-icon/bank-transfer-icon-6.jpg);
}
}
<div class="payment-group">
<div class="payment-method">
<div class="payment-method-title field choice">
<input type="radio" class="radio" id="cashondelivery" value="cashondelivery"/>
<label class="label">
<span>Cash on delivery</span>
</label>
</div>
</div>
<div class="payment-method">
<div class="payment-method-title field choice">
<input type="radio" class="radio" id="banktransfer" value="banktransfer"/>
<label class="label">
<span>Bank transfer</span>
</label>
</div>
</div>
</div>
Can someone help me ?
(I am using LESS, but you can help me with plain CSS)
There are a few problems here:
nth-child starts at 1 not 0 in CSS.
The nesting of selectors does not exist in pure CSS, this snippet 'flattens' them
Space is a very important character in a CSS selector. It is a 'combinator'. The second selector missed it out before .payment-method
the before of a pseudo element nowadays should have a double colon as in ::before (this indicates a pseudo element as opposed to a pseudo class).
.payment-group .payment-method:nth-child(1) .payment-method-title label span::before {
content: url(https://icon-library.com/images/delivery-service-icon/delivery-service-icon-6.jpg);
}
.payment-group .payment-method:nth-child(2) .payment-method-title label span::before {
content: url(https://icon-library.com/images/bank-transfer-icon/bank-transfer-icon-6.jpg);
}
<div class="payment-group">
<div class="payment-method">
<div class="payment-method-title field choice">
<input type="radio" class="radio" id="cashondelivery" value="cashondelivery" />
<label class="label">
<span>Cash on delivery</span>
</label>
</div>
</div>
<div class="payment-method">
<div class="payment-method-title field choice">
<input type="radio" class="radio" id="banktransfer" value="banktransfer" />
<label class="label">
<span>Bank transfer</span>
</label>
</div>
</div>
</div>

adding space to right between 2 divs vertically

I want to arrange div below each other but lower div should be moved to right. so i am expecting output like this
Right now i have made it to work by using below code
<div id="div1" class="checkbox">
<label>
<input type="checkbox" id="chk1" data-bind="checked: data1" />
<span>DIV 1</span>
</label>
</div>
<div id="div2" class="checkbox" style="text-align: center;width: 370px">
<label>
<input type="checkbox" id="chk2" data-bind="checked: data2" />
<span>div2</span>
</label>
</div>
so basically i reduced width of div2 and aligned text to center but i dont think thats good way to do it. Any other better way?
If there's only going to be two divs that need to be spaced apart; you can use one of the following inside your HTML markup.
- Adds a single space
  - Adds 2 spaces
  - Adds 4 spaces
<div id="div1" class="checkbox">
<label>
<input type="checkbox" id="chk1" data-bind="checked: data1" />
<span>DIV 1</span>
</label>
</div>
<div id="div2" class="checkbox">
<label>
 
<input type="checkbox" id="chk2" data-bind="checked: data2" />
<span>DIV 2</span>
</label>
</div>
.container {
display: flex;
flex-direction: column;
width: 200px
}
#div1 {
height: 20px;
width: 150px;
border: 1px solid;
}
#div2 {
height: 20px;
width: 150px;
border: 1px solid;
align-self: flex-end;
}
<div class="container">
<div id="div1" class="checkbox">
<label>
<span>DIV 1</span>
</label>
</div>
<div id="div2" class="checkbox" >
<label>
<span>div2</span>
</label>
</div>
</div>

Multiple tabs on a page - HTML CSS

I have the following code: Link
The problem is that the tabs are not active at the same time, when one is
active the other is disabled and I do not know how to make it work. I have
only used HTML and CSS
What I want is that both are active in tab 1 and that we keep active even
though we have the different tabs because my idea is to add more div with
tabs. I leave a link to CodePen and also insert the code here.
.tabs {
display: flex;
flex-wrap: wrap;
}
.tabs label {
order: 1;
display: block;
padding: 1rem 2rem;
cursor: pointer;
background: #90CAF9;
font-weight: bold;
transition: background ease 0.2s;
}
.tabs .tab {
order: 99;
flex-grow: 1;
width: 100%;
display: none;
padding: 1rem;
background: #fff;
}
.tabs input[type="radio"] {
display: none;
}
.tabs input[type="radio"]:checked + label {
background: #fff;
}
.tabs input[type="radio"]:checked + label + .tab {
display: block;
}
<div class="tabs">
<input type="radio" name="tab" id="tabone" checked="checked">
<label for="tabone">Tab One</label>
<div class="tab">
<h1>Tab One Content</h1>
</div>
<input type="radio" name="tab" id="tabtwo">
<label for="tabtwo">Tab Two</label>
<div class="tab">
<h1>Tab Two Content</h1>
</div>
<input type="radio" name="tab" id="tabthree">
<label for="tabthree">Tab Three</label>
<div class="tab">
<h1>Tab Three Content</h1>
</div>
</div>
<br><br><br>
<div class="tabs">
<input type="radio" name="tab" id="tabfour" checked="checked">
<label for="tabfour">Tab One</label>
<div class="tab">
<h1>Tab One Content</h1>
</div>
<input type="radio" name="tab" id="tabfive">
<label for="tabfive">Tab Two</label>
<div class="tab">
<h1>Tab Two Content</h1>
</div>
<input type="radio" name="tab" id="tabsix">
<label for="tabsix">Tab Three</label>
<div class="tab">
<h1>Tab Three Content</h1>
</div>
</div>
<div class="tabs">
<input type="radio" name="tab2" id="tabfour" checked="checked">
<label for="tabfour">Tab One</label>
<div class="tab">
<h1>Tab One Content</h1>
</div>
<input type="radio" name="tab2" id="tabfive">
<label for="tabfive">Tab Two</label>
<div class="tab">
<h1>Tab Two Content</h1>
</div>
<input type="radio" name="tab2" id="tabsix">
<label for="tabsix">Tab Three</label>
<div class="tab">
<h1>Tab Three Content</h1>
</div>
</div>
For the second section, add a different value to the name attribute for each set of radio buttons. What you were doing before was adding checked to two buttons in the same set of radio buttons.
Not 100% sure I understand the question, but it seems to me that you just need to use a different value for the name attribute in each separate tabset.
It seems you want to make many tab groups work (one is open others are close) independently from each other.
Add a different value of name attribute for each set of tabs such that each set will work as a unit where if one is opened other tabs would be closed.
In the example you have given, all the radios along the side of tab inside the first tab could have value of name attribute as tab1 and other radios under second tab-group could have tab2.
PS: radio button's name attribute allows only one of same name radio buttons to be checked.
Here is the full solution working with two panels.
.tabs {
display: flex;
flex-wrap: wrap;
}
.tabs label {
order: 1;
display: block;
padding: 1rem 2rem;
cursor: pointer;
background: #90CAF9;
font-weight: bold;
transition: background ease 0.2s;
}
.tabs [class^="tab"] {
order: 99;
flex-grow: 1;
width: 100%;
display: none;
padding: 1rem;
background: #fff;
}
.tabs input[type="radio"] {
display: none;
}
.tabs input[type="radio"]:checked + label {
background: #fff;
}
.tabs input[type="radio"]:checked + label + [class^="tab"] {
display: block;
}
<div class="tabs">
<input type="radio" name="tab" id="tabone" checked="checked">
<label for="tabone">Tab One</label>
<div class="tab">
<h1>Tab One Content (1)</h1>
</div>
<input type="radio" name="tab" id="tabtwo">
<label for="tabtwo">Tab Two</label>
<div class="tab">
<h1>Tab Two Content (1)</h1>
</div>
<input type="radio" name="tab" id="tabthree">
<label for="tabthree">Tab Three</label>
<div class="tab">
<h1>Tab Three Content (1)</h1>
</div>
</div>
<div class="tabs">
<input type="radio" name="tab2" id="tabfour" checked="checked">
<label for="tabfour">Tab One</label>
<div class="tab2">
<h1>Tab One Content (2)</h1>
</div>
<input type="radio" name="tab2" id="tabfive">
<label for="tabfive">Tab Two</label>
<div class="tab2">
<h1>Tab Two Content (2)</h1>
</div>
<input type="radio" name="tab2" id="tabsix">
<label for="tabsix">Tab Three</label>
<div class="tab2">
<h1>Tab Three Content (2)</h1>
</div>
</div>

Vertically responsive panel with overflow scroll

Could anyone give new ideas how to realize the following? If it generally possible).
The content of Left panel will be changed dynamically with Angular. So, we can have several items or, for example, 50 items on the panel. In accordance with that, the height of panel will be shorter or overflow hidden will be displayed.
Here is fiddle draft https://jsfiddle.net/b9on9gup/7/
First of all the div class="filter-title" should fill 100% height.
The second, title container shouldn't be in scrolling area. Scroll should be inside div class="radio-container". You could add class .shown on
div class="main-container" to display bottom panel.
Additional condition is good displaying with and without scroll (different quantity of items, different screen resolutions etc).
in fiddle I was trying different ways, so some css properties can be odd.
<body>
<div class = "main-container">
<div class="left-panel">
<div class="filter-container">
<div class="table">
<div class="table-row">
<div class="radio-container">
<div class="overflow">
<div>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm" />
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm" />
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm" />
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm" />
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button
</label>
</div>
<div>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button
</label>
</div>
</div>
</div>
<div class="filter-title">
<span>
Filter title
</span>
</div>
</div>
</div>
</div>
</div>
<div class="bottom-panel"></div>
</div>
</body>
html, body {
height: 100%;
padding: 0;
position: relative;
margin: 0;
}
.main-container {
position: relative;
overflow: hidden;
height: 100%;
width: 100%;
.left-panel {
top: 0;
left: 0;
bottom: 0;
width: 300px;
background: #fff;
position: absolute;
transition: bottom 0.5s ease;
.filter-container {
position: absolute;
background: #F6F6F6;
top: 50%;
transform: translateY(-50%);
width: 100%;
.table {
display: table;
width: 100%;
.table-row {
display: table-row;
height: 100%;
.radio-container {
display: table-cell;
padding: 25px 25px;
display: table-cell;
vertical-align: middle;
.overflow {
overflow-y: scroll;
max-height: 100%;
}
}
}
.filter-title {
display: table-cell;
width: 20px;
background: #539ACC;
vertical-align: middle;
span {
-webkit-writing-mode: vertical-lr;
white-space: nowrap;
}
}
}
}
}
.bottom-panel {
height: 200px;
position: absolute;
bottom: -200px;
background: #F6F6F1;
width: 80%;
left: 0;
right: 0;
margin: auto;
transition: bottom 0.5s ease;
}
&.shown {
.left-panel {
bottom: 200px;
}
.bottom-panel {
bottom: 0;
}
}
}
UPDATE
It's a simple piece of javascript that you can edit to better fill your needs...
it changes the title height if necessary (it actually changes the element's width since the it's rotated 90deg)
var ftitle = document.querySelector('.filter-title');
var radiocont = document.querySelector('.radio-container');
var w = ftitle.clientWidth;
var h = radiocont.clientHeight;
if (h > w) { ftitle.style.width = h + 'px';}
.left-panel {
position: relative;
width: 150px;
}
/*
.radio-container {
height: 100px;
overflow: auto;
}
*/
.radio-container label {
display: block;
}
.filter-title {
background: #ddd;
text-align: center;
position: absolute;
top: 0; left: 0;
transform: translateX(170px) rotate(90deg);
transform-origin: 0 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div class = "main-container">
<div class="left-panel">
<div class="radio-container">
<label>
<input type="radio" name="filterFieldsForm"/>
radio button1
</label>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button2
</label>
<label>
<input type="radio" name="filterFieldsForm" />
radio button3
</label>
<label>
<input type="radio" name="filterFieldsForm" />
radio button4
</label>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button5
</label>
<label>
<input type="radio" name="filterFieldsForm" />
radio button6
</label>
<label>
<input type="radio" name="filterFieldsForm" />
radio button7
</label>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button8
</label>
<label>
<input type="radio" name="filterFieldsForm" />
radio button9
</label>
<label>
<input type="radio" name="filterFieldsForm" />
radio button10
</label>
<label>
<input type="radio" name="filterFieldsForm"/>
radio button11
</label>
<label>
<input type="radio" name="filterFieldsForm" />
radio button12
</label>
<label>
<input type="radio" name="filterFieldsForm" />
radio button13
</label>
<label>
<input type="radio" name="filterFieldsForm" />
radio button14
</label>
</div>
<div class="filter-title">
<span>Filter title</span>
</div>
</div>
</div>
</body>
</html>
http://jsbin.com/wiyuhu/edit?css,js,output
The best decision I've found in my case is using max-height for div class= "overflow" and media-queries min-height.
I noticed scroll is displayed if to set max-height for div class= "overflow". But max-height should be at least in 'px', not in '%'.
Also max-height should be different for different resolutions. I set some breakpoints for max-height using media queries. Something like this:
#media(min-height:520px) {
max-height: 170px;
}
#media(min-height:600px) {
max-height: 250px;
}
#media(min-height:768px) {
max-height: 400px;
}
#media(min-height:900px) {
max-height: 500px;
}
.....
It allows me having panel's height shorter than browser view's height in any resolutions and having or not having scroll inside panel (depends on quantity of items)
The same approach is applied to filter title + text-overflow
Here is video - http://take.ms/WBDcy
and here is code - http://plnkr.co/edit/SbMa9Ece2eOPJ2C0Lt5U?p=preview
When I was writing this post I've understood that using of max-height: 80vh maybe was even better than media queries. It should be tested.

Bootstrap Checkbox is not working properly

I'm using the following mark up and styles (Bootstrap). It shows my checkbox but it is paralysed, that is, it cannot be checked. here is my mark up:
I want something more Bootstrap-ish. I know there are other options to make the checkbox look fancy but that do not solve the problem.
<div class="form-group">
<div class="checkbox">
1.
<input type="checkbox" name="options" id="chk2" />
<label class="checkbox-label">Option 2</label>
</div>
</div>
Here is how it looks.
What exactly is the issue?
If I put the input element inside label I get this ugly thing:
<input type="checkbox" name="options" id="chk2" />
<label class="checkbox-label">Option 2</label>
The problem is with your label. The for attribute must match with the name attribute of your label
Looks need to tweak bootstrap styling for custom checkbox.
Check this
HTML
<div class="form-group">
<div class="checkbox">
<label for="check">
<input type="checkbox" id="check"/>
<span class="fake-input"></span>
<span class="fake-label">Option 2</span>
</label>
</div>
</div
CSS
.fake-input {
float: left;
width: 20px;
height: 20px;
border: 1px solid #9f9f9f;
background: #fff;
vertical-align: middle;
position: relative;
margin-right: 10px;
border-radius: 4px;
}
input[type="checkbox"] {
position: fixed;
top: -9999px;
left: -9999px;
}
input[type="checkbox"]:checked + .fake-input:before {
content:"\2713";
position: absolute;
color: #000;
text-align: center;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
Check in Fiddle
Reading around it looks like you have to style the checked version and the unchecked version.
input[type=checkbox]:checked {
}
Styling with this tag should solve your problems.
Use "for" attribute to solve this issue.
<div class="form-group">
<div class="checkbox">
1.
<input type="checkbox" name="options" id="chk2" />
<label for="chk2" class="checkbox-label">Option 2</label>
</div>
</div>
<div class="col-md-3">
<input class="form-check-input" type="checkbox" id="" asp-for="">
<label class="form-check-label" for="" asp-for="">
</label>
</div>
It's not due to Bootstrap but to Wordpress. The checkboxes became visible after I added "display:block;" to the css of the checkbox input tag.
<input class="form-check-input" type="checkbox" id="">
input.form-check-input {
display:block;
}