Scenario
I have a CSS selector that is supposed to display sub-content when a label is clicked. The selector is along the lines of input:checked + element + element giving that final element a display of block (default is none). The problem is that it works in all the major browsers with the exception of webkit. Chrome, Safari, and a mobile browser for android (v2.2 sorry, I'm behind the times) all fail to display the element. When I inspect the element in Chrome, it shows that it is supposed to be display: block but it doesn't render it. I can unchec and check the property in developer tools and it displays, but not before.
I assume that this is a bug in webkit.
Question
Here is the multipart question: Is this a known bug in webkit? Am I doing anything wrong with my selectors? And how can I work around the issue for webkit browsers (any creative suggestions)?
Code
HTML
<input id="c1" type="checkbox">
<label for="c1">Ein</label>
<section>Content</section>
<input id="c2" type="checkbox">
<label for="c2">Zwei</label>
<section>Content</section>
<input id="c3" type="checkbox">
<label for="c3">Drei</label>
<section>Content</section>
CSS
input {
float:left;
clear:left;
visibility: hidden;
position:absolute;
}
label {
color:green;
display:block;
cursor:pointer;
}
section {
display:none;
}
label:after {
content:" +";
}
input:checked + label:after {
content:" -";
}
input:checked + label + section {
display:block;
}
Demo
Demo: http://jsbin.com/epibin/2
Source: http://jsbin.com/epibin/2/edit
Chain A Pseudo-Class
This demonstrates that this code fixes the bug (note that nth-child(n) matches any element, but the adding of it into the chain causes it to work):
input:checked + label:nth-child(n) + section {
display:block;
}
#ScottS provides a solid solution. Another possible one that worked for me and makes more sense from an outsiders "why the heck did they do that" point of view:
input:checked ~ section {
display:block;
}
which selects every 'section' that come after and are siblings of 'input:checked'.
There are two conditions I can think of where #ScottS's version is superior because the element in the position of 'label' gets selected as well in my solution:
(1) 'input's sibling #1 & #2 are the same elements (instead of 'label' & 'section')
(2) you are trying to be general by using the '*' selector.
sounds like a match to Bug 45168 – CSS multiple adjacent sibling selector sequence is ignored if prefixed with a pseudo-class selector
if you swap the <label> and <input> structure in the markup (and adjust the CSS accordingly) it works.
http://jsbin.com/epibin/10/edit
(but now the + - don't toggle)
EDIT:
putting the <label> and <section> in a div container works: http://jsbin.com/epibin/12/edit
As mdmullinax states, this is an outstanding bug in chrome.
This hack worked for me from the link in the accepted answer:
body { -webkit-animation: bugfix infinite 1s; }
#-webkit-keyframes bugfix { from { padding: 0; } to { padding: 0; } }
Related
I wrote a radio list with image animate. When it was hovered and checked, it can change to another image.
it's works on all of the browsers but on IE its not work when I hover on it.
I don't know if I wrote some css wrong or miss something about ie issue?
the html is:
<ul>
<li>
<input type="radio" id="f-option" name="gender">
<label for="f-option" class="gender female"><img src="images/52x42.png"></label>
<div class="check"></div>
</li>
</ul>
and my css is:
.user-form ul li label.gender.female {
background-image: url(../images/female.png);
}
.user-form input[type=radio]:checked ~ label.gender.female,
.user-form input[type=radio]:hover ~ label.gender.female {
background-image: url(../images/female-checked.png);
}
its works all of the browser but not work on ie
can anybody help me fix it?
The online demo is in this bottom of page:
http://bestinthink.com/wg/buy-p1.html
Try the below. I'm accessing the female class directly after the label as .gender and .female were siblings.
.user-form ul li label.gender.female {
background-image: url(../images/female.png);
}
.user-form input[type=radio]:checked ~ label .female,
.user-form input[type=radio]:hover ~ label .female {
background-image: url(../images/female-checked.png);
}
Your example works in modern browsers because they treat hovering over your label element as though you are hovering over the radio element itself, even though the radio element is set to visibility:hidden. IE doesn't behave that way. You have to explicitly hover over the radio element — which you can't do because you've hidden it — to see your input[type=radio]:hover styles.I suggest changing the background-image on label:hover rather than input[type=radio]:hover. The below code might work for you.
.user-form input[type=radio]:checked ~ label.gender.female,
.user-form label.gender.female:hover {
background-image: url(../images/female-checked.png);
}
Use it and let me know how it goes.☺
I'll update if I find a less hacky solution.
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".
According to http://www.w3schools.com/cssref/sel_not.asp the "not" selector is supported in IE9
However the following doesn't work in ie9:
HTML:
<input type="checkbox"><span>I agree to the terms and conditions</span>
CSS:
input:not(:checked) + span
{
font-weight:bold;
text-decoration:underline;
color:red;
}
When you check the checkbox, the style is still applied. In other browsers (FF, Chrome) it works as expected.
Is it some sort of bug with IE9?
Thanks.
I don't know what the bug is exactly, but I have got a workaround for you.
With some experimenting I discovered that if you put this line
input:checked + p {}
above your CSS, your CSS works fine in IE. So I propose you just put that in and forget about it, unless you want to invest a lot of time in finding out what the extent of the bug is exactly.
input:checked + p {}
input:not(:checked) + span {
font-weight: bold;
text-decoration: underline;
color: red;
}
<input type="checkbox"><span>I agree to the terms and conditions</span>
To test, you can comment out the first line, and then it stops working in IE.
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 know there are lot's of questions regarding this query here but none of them provide the solution for me.
HTML
<input id="tb1" type="text" class="note" />
<br>
<p class="note1"> This is not done.</p>
CSS
p.note1:before{
content: "Note:";
}
tb1.note:before{
content: "Enter your number";
}
I am trying with above code and the variation as found on the web but none seems to work for input tag. It's working for p tag.
EDIT: I can't add value attribute to input tag and manage css for the desired result. It's the limitation of the system.
EDIT2: Forget about my css, is there any way that placeholder text is possible without using placeholder attribute and just with plain css for input type="text"
:before creates a pseudo-element that is the first child of the element matched.
The selected element MUST be a container tag. An empty tag like <input> doesn't have any children element.
If you can't edit your HTML code manually, you're still able to that by using JavaScript:
document.getElementById("tb1").setAttribute("placeholder", "Enter your number");
Update
If you want to achieve this by using CSS only, you need to have a container element wrapping your <input> (or come after it).
BUT It doesn't work correctly as placeholder do. You'll not able to check the value of <input> by CSS. If you write something inside the <input>, after blur event, the generated placeholder will be displayed over the <input> again.
HTML:
<label>
<input id="tb1" type="text" class="note">
</label>
CSS:
label {
position: relative;
}
label:after {
content: 'Enter your number';
position: absolute;
left: 5px;
top: 0;
color: #bbb;
}
#tb1 {
position: relative;
}
#tb1:focus {
z-index: 10;
}
JSBin Demo
It doesn't work for the simple fact that this:
<input id="tb1" type="text" class="note"></input>
is not valid. <input /> elements are not containers. As the spec notes, endtags are forbidden (and essentially ignored by the browser): http://www.w3.org/TR/html401/interact/forms.html#h-17.4
If you cant manipulate the html and use placeholder="". Use javascript to manipulate the placeholder. Every css approach is hack-isch anyway.
E.g. with jQuery:
$('#myFieldId').attr('placeholder', 'Search for Stuff');
I have found this method but not supported by all browsers:
#tb1.note:empty:before{
content: "Enter your number";
}
Note: you have forgot to place an id selector # tb1.note
see this link
EDIT:
Try this for starters: (Note: you'll need some js to detect if text has been entered in the input)
Apart from this - I don't think this there is a css solution for placeholder text on an input element without using the placeholder attribute.
FIDDLE
Markup
<div class="container">
<input />
<div class="fakePlaceholder">Some placeholder text</div>
</div>
css
.container
{
position: relative;
}
input
{
background: transparent;
}
input:focus + .fakePlaceholder
{
display: none;
}
.fakePlaceholder
{
color:gray;
position:absolute;
top: 3px;
left: 5px;
z-index: -1;
}
You can't use pseudo elements on an input tag - or any other non-container elements for that matter
From the Pseudo-Elements tag info:
you cannot use them (pseudo elements) with replaced elements (see
below) which do not have actual content. This is because the generated
content resides within the element.
...
Replaced Elements
Any element whose appearance and/or dimensions are determined by some
external resource is considered to be a replaced element. Some
pseudo-elements cannot be applied to replaced elements because they
have no "content" or get replaced with something (such as user
interface controls). Replaced elements include images (<img>), inline
frames (<iframe>), line breaks (<br>), horizontal rules (<hr>),
plugins (<object>), form elements (<button>, <textarea>, <input>, and
<select>), videos (<video>), audio sounds (<audio>), and canvases
(<canvas>). Any other element is considered to be a non-replaced
element.
Another way this can be accomplished, and have not really seen any others give it as an option, is to instead use an anchor as a container around your input and label, and handle the removal of the label via some color trickory, the #hashtag, and the css a:visited. (jsfiddle at the bottom)
Your HTML would look like this:
<a id="Trickory" href="#OnlyHappensOnce">
<input type="text" value="" id="email1" class="inputfield_ui" />
<label>Email address 1</label>
</a>
And your CSS, something like this:
html, body {margin:0px}
a#Trickory {color: #CCC;} /* Actual Label Color */
a#Trickory:visited {color: #FFF;} /* Fake "Turn Off" Label */
a#Trickory:visited input {border-color: rgb(238, 238, 238);} /* Make Sure We Dont Mess With The Border Of Our Input */
a#Trickory input:focus + label {display: none;} /* "Turn Off" Label On Focus */
a#Trickory input {
width:95%;
z-index:3;
position:relative;
background-color:transparent;
}
a#Trickory label {
position:absolute;
display:block;
top:3px;
left:4px;
z-index:1;
}
You can see this working over at jsfiddle, note that this solution only allows the user to select the field once, before it removes the label for good. Maybe not the solution you want, but definitely an available solution out there that I have not seen others mention. If you want to experiment multiple times, just change your #hashtag to a new 'non-visited' tag.
http://jsfiddle.net/childerskc/M6R7K/