I would like to put a "vote" button on a webpage with a counter. The vote buttons come with a counter of current votes. If it is not clicked, the count displayed is the current number of votes. When clicked, the current number of votes is incremented of one (and the button change its state or appeareance).
Is there a way to do this in pure HTML5/CSS3?
The button and it's interaction can be done on the user-side with pure CSS given you generate a small style tag in your document server-side. Needless to say that you can't record the result in your database if you don't use Javascript or a post back, though.
#container {
width: 100px;
height: 20px;
position: relative;
text-align: center;
}
#like {
position: absolute;
display: block;
width: 100%;
height: 100%;
opacity: 0;
cursor: pointer;
}
#like:checked {
counter-increment: likes;
}
#button {
display: block;
width: 100%;
height: 100%;
background: green;
}
#like:checked ~ #button {
background: blue;
}
#count:before {
content: counter(likes);
}
<!-- Create this style tag server-side -->
<style>
body {
counter-reset: likes 7; /* Initial number of likes */
}
</style>
<div id="container">
<input id="like" type="checkbox" name="like" value="like" />
<span id="button">Like <span id="count"></span></span>
</div>
Related
Guys I am a total newbie. I learn through trying to solve problems which I create. I was reading about swaping one sentence and I decided to make this sentences swaped one after another and I failed so far. If original and a new sentence have same length it is easy. But lets assume they are different and need sometimes to go to another row to look like a traditional text. I can't solve it from several hours, in the attached screen there is a results and what I want. I was checking several websites and ideas. I managed to improve how it is showed on a screen, so it is more continuos but still it is not filling blank spaces or doesnt expand if the text is longer. I want after pressing a sentence, replaced it by another but text being continous without any kind of breaks. I based on this website https://css-tricks.com/swapping-out-text-five-different-ways/. Below is my html and css code.
Here is a drawing of my problem - https://ibb.co/qkqMbwB
<html>
<head>
<meta charset="utf-8"/>
<title>IGE</title>
<link rel="stylesheet" href="3code.css">
</head>
<body>
<div class="flexbox-container">
<input type="checkbox" id="zdanie1Checkbox" />
<label id="zdanie1" for="zdanie1Checkbox">Origxt1.</label>
<input type="checkbox" id="zdanie2Checkbox"/>
<label id="zdanie2" for="zdanie2Checkbox"> Original texsdsdsdsdsdsdsdsdddddd sdsd sdsdsdsd sd sd sdt2.</label>
<input type="checkbox" id="zdanie3Checkbox" />
<label id="zdanie3" for="zdanie3Checkbox">Original tsd ext3.</label>
<input type="checkbox" id="zdanie4Checkbox" />
<label id="zdanie4" for="zdanie4Checkbox">Orig sdsdsddsinalText4.</label>
<input type="checkbox" id="zdanie5Checkbox" />
<label id="zdanie5" for="zdanie5Checkbox">Orixt54.</label>
</div>
</body>
</html>
and here is css
body {
padding: 0px 10px 10px 10px;
}
.flexbox-container {
display:flex;
flex-wrap:wrap;
flex-direction: row;
justify-content:flex-start;
align-content:center;
}
#zdanie1 {
position: relative;
}
#zdanie1Checkbox {
display: none;
}
#zdanie1Checkbox:checked + #zdanie1:after {
content: "The outer layer is nearly melted through.";
align-self: stretch;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: white;
color: red;
width:auto!important; /*this set the height to auto for those supporting it (not IE)*/
width:500px; /*for IE, all others override it by the previous rule*/
min-width:500px; /*for the ones that support it (all but IE)*/
padding-right: auto;
}
#zdanie2 {
position: relative;
}
#zdanie2Checkbox {
display: none;
}
#zdanie2Checkbox:checked + #zdanie2:after {
content: "The outer layer is nearly melted through.";
align-self: stretch;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: white;
color: red;
width:auto!important; /*this set the height to auto for those supporting it (not IE)*/
width:500px; /*for IE, all others override it by the previous rule*/
min-width:500px; /*for the ones that support it (all but IE)*/
}
#zdanie3 {
position: relative;
}
#zdanie3Checkbox {
display: none;
}
#zdanie3Checkbox:checked + #zdanie3:after {
content: "Soon the second layer will go.";
align-self: stretch;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: white;
color: red;
width:auto!important; /*this set the height to auto for those supporting it (not IE)*/
width:500px; /*for IE, all others override it by the previous rule*/
min-width:500px; /*for the ones that support it (all but IE)*/
}
#zdanie4 {
position: relative;
}
#zdanie4Checkbox {
display: none;
}
#zdanie4Checkbox:checked + #zdanie4:after {
content: "Then the scanner blinks silver and I’ve got what I came for.";
position: absolute;
align-self: stretch;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: white;
color: red;
overflow-wrap: break-word;
width:auto!important; /*this set the height to auto for those supporting it (not IE)*/
width:500px; /*for IE, all others override it by the previous rule*/
min-width:500px; /*for the ones that support it (all but IE)*/
/* Non standard for webkit */
word-break: break-word;
-webkit-hyphens: auto;
-moz-hyphens: auto;
-ms-hyphens: auto;
hyphens: auto;
}
#zdanie5 {
position: relative;
}
#zdanie5Checkbox {
display: none;
}
#zdanie5Checkbox:checked + #zdanie5:after {
content: "The outer layer is nearly melted throu I almost didn’t notice.";
position: absolute;
align-self: stretch;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: white;
color: red;
width:auto!important; /*this set the height to auto for those supporting it (not IE)*/
width:500px; /*for IE, all others override it by the previous rule*/
min-width:500px; /*for the ones that support it (all but IE)*/
}
There many ways to achieve it. The easiest way with the most varity to use would be the use of JS with an onlick event as shown below. In this case you have 2 lines used as a span so that they could be used within a paragraph. One is set to display: none; by default and therefor invisible. With clicking on the line, you trigger the script, that will hide the line with display: none; and show the other by changing it to display: block;.
function show1b() {
document.getElementById("line-1b").style.display = "block";
document.getElementById("line-1a").style.display = "none";
}
function show1a() {
document.getElementById("line-1a").style.display = "block";
document.getElementById("line-1b").style.display = "none";
}
#line-1b {
display: none;
}
<span id="line-1a" onclick="show1b()">This is the original text. Click on me to show the alternative text.</span>
<span id="line-1b" onclick="show1a()">This is the alternative text. Click on me to show the original text.</span>
CSS only
here you "mis-use" the input as a checkbox with the label. You hide the checkbox by using its id and display: none;. then you sue the id of the label with :after to use the attribute content:. Then you define the etxt that should be used. If the checkbox id is checked, then it will dispaly an alternative text as used in the sampel below.
#line-1a {
display: none;
}
#line-1b:after {
content: "This is the original text. Click on me to show the alternative text.";
}
#line-1a:checked + #line-1b:after {
content: "This is the alternative text. Click on me to show the original text.";
}
<input id="line-1a" type="checkbox">
<label for="line-1a" id="line-1b"></label>
I have some checkboxes in a grid and want to use vanilla-css and html to make a custom checkbox. That works fine. The problem is the remaining box of the original checkbox, that stays in my grid and makes it behave in strange ways as it takes a cell. Even when I make it transparent or deactivate it, as it is often suggested.
In the original example they moved it out of the screen area, but I can make it escape the grid.
I think this is the part where it fails to behave like I want to:
[type="checkbox"]:not(:checked),
[type="checkbox"]:checked {
position: absolute;
left: -9999px;
}
Here is a minimal example: https://jsfiddle.net/3mzsLj1v/14/
Here is the example I used: https://css-tricks.com/the-checkbox-hack/
Here is the real code I work on: https://codepen.io/vaeng/pen/XWXKoMb
Thanks for your help. I am sure this is very common, but being a beginner, I might not use css in the correct way?
In both your "minimal" and "real code" examples, your "New Checkboxes" comments are not properly opened.
In minimal example:
Line 23: *New Checkboxes*/ s/b /*New Checkboxes*/
In real code example:
Line 123: * New Checkboxes and radio buttons*/ s/b /* New Checkboxes and radio buttons*/
If you fix these lines, your code should work as intended.
Also, I noticed in line 102 that you put // before visibility: hidden;. If you want to comment this line, this syntax is not valid in CSS.
You see, your label and input element are on the same level, and even with position: absolute; your input still a part of the grid. Replaced your input inside the label, added span element and rewrited CSS.
Although in your code was
* New Checkboxes*/
/* Base for label styling */
[type="checkbox"]:not(:checked),
[type="checkbox"]:checked {
position: absolute;
left: -9999px;
}
The first comment was closed incorrect, so next statement didn't work.
.body {
height: 100%;
}
.outer-box {
display: grid;
margin: auto;
background-color: green;
width: 300px;
align-self: center;
grid-gap: 10px;
}
.inner-box {
display: grid;
width: 80%;
background-color: red;
align-self: center;
margin: 5px 5px 5px 5px;
}
/* New Checkboxes*/
/* Base for label styling */
[type="checkbox"] {
position: absolute;
left: -9999px;
}
[type="checkbox"]:not(:checked)+span,
[type="checkbox"]:checked+span {
position: relative;
padding-left: 1.95em;
cursor: pointer;
}
/* checkbox aspect */
[type="checkbox"]:not(:checked)+span:before,
[type="checkbox"]:checked+span:before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 1em;
height: 1em;
border: 1px solid grey;
background: transparent;
}
/* checked mark aspect */
[type="checkbox"]:not(:checked)+span:after,
[type="checkbox"]:checked+span:after {
content: '\2713\0020';
position: absolute;
top: .05em;
left: .2em;
font-size: 1.3em;
line-height: 0.8;
color: whitesmoke;
transition: all .2s;
font-family: Arial;
}
/* checked mark aspect changes */
[type="checkbox"]:not(:checked)+span:after {
opacity: 0;
transform: scale(0);
}
[type="checkbox"]:checked+span:after {
opacity: 1;
transform: scale(1);
}
<div class="outer-box">
<div class="inner-box">
Some text
</div>
<div class="inner-box">
<label for="box1" class="container">
<input type="checkbox" id="box1"><span>Selectbox1</span>
</label>
<label for="box2" class="container">
<input type="checkbox" id="box2"><span>Selectbox2</span>
</label>
</div>
</div>
And please, don't use display: grid; for every element. It's very specific setting only for cases, when you really need you use grid.
I have a problem with my custom checkbox.
If you click on a checkbox element, move the mouse cursor and then release the click inside the checkbox area, the checkbox is checked.
However, if you do the same on a custom checkbox (here, a div inside a label), the checkbox isn't checked.
It's a problem because if you want to quickly check a checkbox, you may move the mouse after pressing the button of the mouse and before releasing it, thus not toggling the checkbox.
The user is obligated to click without moving the mouse.
I know I can use JS to emulate a checkbox with a div, but I want the HTML to be semantically correct, so: Is it possible to fix it without js?
Here's the code :
/* 1. Hide the checkbox */
.hidden {
/* https://zellwk.com/blog/hide-content-accessibly/ */
border: 0;
clip: rect(0, 0, 0, 0);
height: auto;
margin: 0;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
white-space: nowrap;
}
/* 2. Use a label to retrieve the click event */
label {
/* not used directly to prevent the bug in firefox https://bugzilla.mozilla.org/show_bug.cgi?id=608180 */
pointer-events: none;
display: inline-flex;
}
label > input {
/*usefull for testing only*/
pointer-events : all;
}
label > .customCheckbox {
cursor: pointer;
display: inline-flex;
justify-content: center;
align-items: center;
position: relative;
--size:200px;
width: var(--size);
height: var(--size);
font-size: calc(var(--size)/2);
pointer-events: all;
}
label > .customCheckbox::selection{
/* prevent highliting the text within the custom checkbox */
background: none;
}
label > .customCheckbox:after {
z-index: -1;
content: "✔";
display: inline-flex;
justify-content: center;
align-items: center;
position: absolute;
width: 100%;
height: 100%;
box-sizing: border-box;
border-radius: calc(var(--size)/4);
border: solid black calc(var(--size)/10);
}
label > input:not(:checked) + div.customCheckbox:after {
background:#0000;
content: "\a0";
}
<input type="checkbox"/>
<label >
<input type="checkbox" class="hidden"/>
<div class="customCheckbox"></div>
</label >
I need the checkbox to be inside the label because I can't use the "for" attribute.
Thanks a lot for your help!
EDIT: for those wondering, here's the js solution (not ideal but since I can't do it in CSS, it's better than nothing) :
let checkboxes = document.getElementsByClassName("customCheckbox");
for(let i=0; i<checkboxes.length; i++){
checkboxes[i].addEventListener('mouseover', (e)=>{handleMouseOverCheckbox(e)})
checkboxes[i].addEventListener('mousedown', (e)=>{handleMouseOverCheckbox(e)})
}
function handleMouseOverCheckbox(e) {
e.srcElement.previousElementSibling.disabled = "true";
if (e.buttons == 1) {
e.srcElement.previousElementSibling.checked= !e.srcElement.previousElementSibling.checked;
}}
EDIT 2 : Here's the best solution I could come up with, thanks to
#zer00ne
codepen.io/DesignThinkerer/pen/bGVBLjM
A checkbox within a label is no problem. The problem arises when that checkbox is altered for the sake of accessibility instead of complete removal using display: none. When an interactive element like an input or button exists in the DOM, it will still be a factor no matter how its hidden unless display: none is applied.
In the Original Post the checkbox is almost impossible to click due to its 0px height and 1px width and yet when the div is clicked, the checkbox is clicked... sometimes not. Normally if the label was able to detect a click, that click would trigger a click event to the nested checkbox as well. In the OP code that's not happening because the label has pointer-events: none.
So the div is getting clicked and by some magical miracle this gains features that would not normally be attributed to it? Divs are not interactive they cannot affect elements that are not nested within themselves (i.e. like the checkbox that sits before the div). Nope, the div is useless, its the checkbox itself that's getting clicked due to the fact it is the only element within the inert label that gains focus by default. Gaining focus on an input doesn't necessarily guarantee a click event -- matter of fact a focus event selects an element and a click event sets an element as active. So what happens when a user double-clicks or moves the mouse quickly before the next click clears a label? Undesirable behavior as described in OP.
In the following demo, the checkboxes are hidden as per OP (also set width and height to 0) and removed pointer-events: none from the label and added it to the checkboxes. In this setup the label gains focus and click events and the click event will trigger the checkbox. The checkbox having been isolated from any extra clicks due to pointer-events: none and z-index: -1 should behave as expected.
As proof of concept I have added some JavaScript to demonstrate said code stability. The two event handlers are for demonstration purposes. The JS does not facilitate, stabilize, or modify performance of the HTML/CSS behavior.
On any change event on a checkbox (via label) will trigger function changeHandler() to gather all the values of the checked checkboxes and display them in an output.
If there's a checkmark in a box and there's a value displayed that corresponds to said checked checkbox, then it successfully passes as valid behavior.
Clicking button.show will trigger function clickHandler() to toggle the .reveal class to each checkbox.
While clicking rapidly observe that the revealed checkboxes are checked and its corresponding custom label is checked as well. Also notice that the value should also be displayed as well.
BTW
"....target doesn't work in IE IIRC"
event.target is the standard property to use in every modern browser. event.srcElement is a deprecated property used by IE which is almost entirely unsupported.
pointer-events: all assigned to input and .customCheckbox
The value all applies to SVG only. Only the values of none and auto are relevant to HTML. auto is default.
Demo
I cannot reproduce the described behavior except in the code provided in OP. If you can reproduce that behavior on my demo, please record a short video of it and post that and the machine/device, OS, and browsers (I will assume everything is reasonably up to date).
const main = document.forms.main;
main.onchange = checkHandler;
function checkHandler(e) {
const fc = this.elements;
const chx = [...fc.hidden];
const ui = e.target;
if (ui.matches('.hidden')) {
let text = chx.flatMap(c => c.checked ? [c.value] : []);
fc.view.value = '';
fc.view.value = text.join(', ');
}
}
main.onclick = clickHandler
function clickHandler(e) {
const fc = this.elements;
const chx = [...fc.hidden];
const ui = e.target;
if (ui.matches('button.show')) {
chx.forEach(c => c.classList.toggle('reveal'));
}
}
:root,
body {
--size: 10rem;
font: 400 small-caps 2vw/1.5 Times;
width: 100%;
height: 100%;
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
font: inherit;
}
.display {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
align-items: center;
width: max-content;
max-height: min-content;
margin: 10px;
border: calc(var(--size) / 20) solid #000;
border-radius: 24px;
}
.view {
display: inline-block;
min-width: 35ch;
font-size: 1.5rem;
height: 1.5rem;
line-height: 1;
}
.show {
display: inline-block;
width: 12ch;
padding: 1px 3px;
margin: 4px;
border: 2px solid #000;
border-radius: 8px;
background: none;
text-align: center;
font-size: 1.25rem;
cursor: pointer;
}
.mask {
position: relative;
z-index: 2;
display: block;
width: var(--size);
height: var(--size);
padding: 0;
margin: 0 5px;
border: solid black calc(var(--size) / 10);
border-radius: calc(var(--size) / 4);
font-size: calc(var(--size) * 0.8);
background: none;
cursor: pointer;
}
.icon {
position: absolute;
z-index: 1;
top: -1.5rem;
right: 1rem;
display: inline-block;
margin: 0;
padding: 0;
border: 0;
}
.hidden {
position: relative;
z-index: -1;
display: inline-block;
width: 0;
height: 0;
margin: 0;
padding: 0;
border: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
pointer-events: none;
opacity: 0;
}
.reveal {
z-index: 0;
top: -24px;
left: 4px;
width: 1px;
height: 1px;
opacity: 1;
}
.icon::after {
content: attr(data-blank);
}
.hidden:checked+.icon::after {
content: attr(data-check);
}
<!DOCTYPE html>
<html>
<head lang='en'>
<meta charset='utf-8'>
<style></style>
</head>
<body>
<form name='main'>
<fieldset name='display' class='display'>
<output name='view' class='view'></output>
<button name='show' class='show' type='button'>Show</button>
</fieldset>
<fieldset name='display' class='display'>
<label name='mask' class='mask'>
<input name='hidden' class="hidden" type="checkbox" value='Check I'>
<fieldset name='icon' class='icon' data-check='✔' data-blank=' '></fieldset>
</label>
<label name='mask' class='mask'>
<input name='hidden' class="hidden" type="checkbox" value='Check II'>
<fieldset name='icon' class='icon' data-check='✔' data-blank=' '></fieldset>
</label>
<label name='mask' class='mask'>
<input name='hidden' class="hidden" type="checkbox" value='Check III'>
<fieldset name='icon' class='icon' data-check='✔' data-blank=' '></fieldset>
</label>
<label name='mask' class='mask'>
<input name='hidden' class="hidden" type="checkbox" value='Check IV'>
<fieldset name='icon' class='icon' data-check='✔' data-blank=' '></fieldset>
</label>
</fieldset>
</form>
<script></script>
</body>
</html>
I have multiple tooltips on my website which I created using data-tooltip. The problem is that it's an attribute so I can't just apply a class in front of it and use it. So what I want is for instance different width for one tooltip or different color etc.
This is an example in the css for the "data-tooltip"
[data-tooltip] {
position: relative;
z-index: 2;
cursor: pointer;
}
Can you please provide some additional html?
It's possible to use a class:
.my-class-1[data-tooltip] {
width: 100px;
}
.my-class-2[data-tooltip] {
width: 200px;
}
<div class="my-class-1" data-tooltip="true">...</div>
<div class="my-class-2" data-tooltip="true">...</div>
or you could also use another data-attribute:
[data-tooltip][data-tooltip-small] {
width: 100px;
}
[data-tooltip][data-tooltip-big] {
width: 200px;
}
<div data-tooltip="true" data-tooltip-small="true">...</div>
<div data-tooltip="true" data-tooltip-big="true">...</div>
I've a question about star-symbols for rating showing. I have code
<style>
.goldstardiv { color: gold; }
.goldgraystardiv { color: khaki; }
.graystardiv { color: gray; }
</style>
<div class="goldstardiv">★</div>
<div class="goldgraystardiv">★</div>
<div class="graystardiv">★</div>
How to show with css a star having a gray left site and yellow right site?
Thank you
Put a div with a half grayed star (width 50% overflow hidden) over the colored one.
Html:
<div class="goldstardiv">
★
<div class="halfstar">★</div>
</div>
Css:
.goldstardiv { color: gold; position: relative; }
.halfstar {
position: absolute;
top: 0;
left: 0;
width: 8px;
color: #666;
overflow: hidden;
}
Half star with is given in pixels, but fiddle around with it to get it in % if you want.
Example:
http://jsfiddle.net/LV7SS/2/
The only way to do this with pure CSS is with a nasty hack like this, which isn't really ideal. This uses a negative margin(margin-left: -104px;) to position the grey div over the gold one.
You would be better off using images and sprites
You can do it by using the content:after property in CSS to display a second gold star over the gray one like this:
<style type="text/css">
.star {
display: inline-block;
width: 20px;
text-align: center;
}
.star.gold { color: gold; }
.star.gold-gray { color: gray; }
.star.gold-gray:after {
display: inline-block;
color: gold;
content: '\2605';
position: absolute;
margin-left: -16px;
width: 8px;
overflow: hidden;
}
.star.gray { color: gray; }
</style>
<div class="star gold">★</div>
<div class="star gold-gray">★</div>
<div class="star gray">★</div>
You do need to be specific about sizes for this to work properly, so that you can correctly set the negative margin on the half-star, and crop it at half-width using overflow:hidden, but it does what you're after.
(I haven't specified font-size in the example, you may want to do that also)
Up-side to this technique is that you don't need additional markup in your html for the half-star, just the correct class.
EDIT
Somehow I pasted the wrong link to my jsFiddle, from a previous version I was still hacking the solution, rather than the working one... Probably deserved the downvote for that, but it does work!
See it working here.
EDIT 2
cimmanon mentioned the stars 'not really being content', which is quite true, but since the question asked for a CSS solution to the problem, I made one that doesn't require a sprite-map with all possible combinations.
Not because I've got anything against sprite maps - I don't - just because I wanted to have a go at it :)
Still including <span> elements for each star (hard to avoid) but aside from that it's all good markup and I assume would work pretty well for a screenreader.
Check it out here.
<style type="text/css">
.stars .label {
width: 1px;
color: transparent;
overflow: hidden;
position: absolute;
}
.star {
display: inline-block;
width: 20px;
text-align: center;
}
.star:before {
display: inline-block;
content: '\2605';
}
.star.on { color: gold; }
.star.half { color: gray; }
.star.half:after {
display: inline-block;
color: gold;
content: '\2605';
position: absolute;
margin-left: -16px;
width: 8px;
overflow: hidden;
}
.star.off { color: gray; }
</style>
<div class="stars">
<span class="label">One and a half start (out of three)</span>
<span class="star on"></span>
<span class="star half"></span>
<span class="star off"></span>
</div>