27
loading...
This website collects cookies to deliver better user experience
<label>
, and add the <svg>
and an empty <span>
after a <input type="checkbox">
:<label aria-label="React with heart">
<input type="checkbox" name="reaction-heart" value="75" style="--c:75" />
<svg></svg>
<span></span>
</label>
<input type="checkbox">
is what we'll use to control both state
and value
. fill
, stroke
or stroke-width
– but let's leave it at two icons. We'll <g>
roup them within a single SVG:<svg viewBox="0 0 24 24">
<g><path d="M21.179 12.794l.013.014L12 22l-9.192-9.192.013-.014A6.5 6.5 0 0112 3.64a6.5 6.5 0 019.179 9.154zM4.575 5.383a4.5 4.5 0 000 6.364L12 19.172l7.425-7.425a4.5 4.5 0 10-6.364-6.364L8.818 9.626 7.404 8.21l3.162-3.162a4.5 4.5 0 00-5.99.334l-.001.001z"></path></g>
<g><path d="M2.821 12.794a6.5 6.5 0 017.413-10.24h-.002L5.99 6.798l1.414 1.414 4.242-4.242a6.5 6.5 0 019.193 9.192L12 22l-9.192-9.192.013-.014z"></path></g>
</svg>
:checked
pseudo-selector to toggle between the two icons (in <g>
-tags):[name*="reaction-"]:checked + svg g:first-of-type,
[name*="reaction-"]:not(:checked) + svg g:last-of-type {
opacity: 0;
}
[name*="reaction-"]:checked + svg g:last-of-type {
opacity: 1;
}
style="--c:75"
in the markup?counter-reset: reaction var(--c);
value
-attribute, as in:counter-reset: reaction attr(value);
--c
, for the initial value.:checked
-selector again:[name*="reaction-"]:checked {
counter-increment: reaction;
}
<span>
in the markup will now play it's part:span::after {
content: counter(reaction);
}
<span>
? That's because we have to add the counter as pseudo-element content (::before
or ::after
).<input type="checkbox">
, as <input>
-tags are part of the group of tags, that can't have children (aka “self-closing” tags) or pseudo-content (actually they can in Chrome and Safari, but it's not part of the spec!).style="--c"
-part from the markup. We'll wrap the reactions in a <form id="react">
, and listen for changes using the onchange
-eventListener:react.addEventListener('change', (e) => {
const t = e.target;
t.parentNode.lastElementChild.innerText = t.value = t.value - 0 + (t.checked ? 1 : -1);
});
1
(one) from the value
of the current reaction, then set the innerText
of the <span>
to that.fetch()
(with POST
) to store the current reaction.JSON
-object is POST
ed:{
result: "create",
category: "like"
}
<span>
-elements to the value
of the <input>
s, use this small snippet to iterate the elements
-collection of the <form>
:[...react.elements].forEach(t => t.parentNode.lastElementChild.innerText = t.value);