i've been designing a button, then you press, then appears an ::after with content "copied!"
Ok, while ::after appears there is an animation, that animation triggers with :active property, but when i stop pressing the animation ends brutally, interrupts. doesnt end properly
how can i stop pressing and the animation ends properly?
here my code!
* {
font-family: monospace;
}
table{
table-layout: fixed;
width: 100%;
border-collapse: collapse;
border: 2px dashed black;
}
td, th{
padding: 5px;
border: 2px dashed black;
text-align: center;
}
tr td:nth-child(4) span {
cursor: pointer;
background: #95c1e3;
color: white;
padding: 12px;
border-radius: 50px;
font-weight: bolder;
font-size: 17px;
}
tr td:nth-child(4) span:active::after {
display: block;
position: absolute;
width: 100px;
height: max-content;
padding: 10px 0px 10px 0px;
background: black;
border-radius: 50px;
animation: copied 1s;
content: "copiado!";
opacity: 0;
}
@keyframes copied {
0%{
margin-top: 0;
opacity: 1;
}
100%{
margin-top: 15px;
opacity: 0;
}
}
<table>
<thead>
<tr>
<th>Server</th>
<th>Nombre</th>
<th>Jugadores</th>
<th>IP</th>
</tr>
</thead>
<tbody id="tabla">
<tr>
<td></td>
<td>Sin nombre</td>
<td>1399 / 5000</td>
<td><span onclick="onclicker()">hub.mc-complex.com</span></td>
</tr>
<tr>
<td></td>
<td> ! SuperCraft Network [1.8-1.21] ❤ !
Amigos en: discord.supercraft.es
</td>
<td>333 / 2000</td>
<td><span onclick="onclicker()">supercraft.es</span></td>
</tr>
<tr>
<td></td>
<td> 1.8-1.21
NUEVO > 15 REGALOS DE NAVIDAD
</td>
<td>189 / 1000</td>
<td><span onclick="onclicker()">play.zonecraft.es</span></td>
</tr>
<tr>
<td></td>
<td> ! UniversoCraft Network [1.8-1.21] ❤ !
Chatea en: discord.universocraft.com
</td>
<td>5427 / 20000</td>
<td><span onclick="onclicker()">mc.universocraft.com</span></td>
</tr>
</tbody>
</table>
As @A Haworth mentioned, you could consider using JavaScript to play the animation.
Here, we use a copy
class to show the ::after
element and then remove the class one frame later. This then plays the transition
, which is independent of wether the :active
pseudo class matches. This means there is no abrupt end.
document.body.addEventListener('click', ({ target }) => {
if (target.matches('span[onclick="onclicker()"]')) {
// Add the copy class to show the `::after`.
target.classList.add('copy');
// Go through two animation frames to ensure we are on the next frame.
requestAnimationFrame(() => {
requestAnimationFrame(() => {
// Remove the copy class to hide the `::after`.
target.classList.remove('copy');
});
});
}
});
window.onclicker = () => {};
* {
font-family: monospace;
}
table {
table-layout: fixed;
width: 100%;
border-collapse: collapse;
border: 2px dashed black;
}
td,
th {
padding: 5px;
border: 2px dashed black;
text-align: center;
}
tr td:nth-child(4) span {
cursor: pointer;
background: #95c1e3;
color: white;
padding: 12px;
border-radius: 50px;
font-weight: bolder;
font-size: 17px;
}
tr td:nth-child(4) span::after {
display: block;
position: absolute;
width: 100px;
height: max-content;
padding: 10px 0px 10px 0px;
background: black;
border-radius: 50px;
content: "copiado!";
opacity: 0;
translate: 0 15px;
transition: translate 1s, opacity 1s;
}
tr td:nth-child(4) span.copy::after {
opacity: 1;
translate: 0 0;
transition: 0s;
}
<table>
<thead>
<tr>
<th>Server</th>
<th>Nombre</th>
<th>Jugadores</th>
<th>IP</th>
</tr>
</thead>
<tbody id="tabla">
<tr>
<td></td>
<td>Sin nombre</td>
<td>1399 / 5000</td>
<td><span onclick="onclicker()">hub.mc-complex.com</span></td>
</tr>
<tr>
<td></td>
<td>! SuperCraft Network [1.8-1.21] ❤ ! Amigos en: discord.supercraft.es</td>
<td>333 / 2000</td>
<td><span onclick="onclicker()">supercraft.es</span></td>
</tr>
<tr>
<td></td>
<td>1.8-1.21 NUEVO > 15 REGALOS DE NAVIDAD</td>
<td>189 / 1000</td>
<td><span onclick="onclicker()">play.zonecraft.es</span></td>
</tr>
<tr>
<td></td>
<td>! UniversoCraft Network [1.8-1.21] ❤ ! Chatea en: discord.universocraft.com</td>
<td>5427 / 20000</td>
<td><span onclick="onclicker()">mc.universocraft.com</span></td>
</tr>
</tbody>
</table>
An alternative JavaScript solution could be to use the Web Animations API:
document.body.addEventListener('click', ({ target }) => {
if (target.matches('span[onclick="onclicker()"]')) {
const keyframes = [
{
opacity: 1,
translate: '0 0',
},
{
opacity: 0,
translate: '0 15px',
},
];
const options = {
duration: 1000,
timing: 'cubic-bezier(0.32, 0, 0.67, 0)',
pseudoElement: '::after',
};
target.animate(keyframes, options);
}
});
window.onclicker = () => {};
* {
font-family: monospace;
}
table {
table-layout: fixed;
width: 100%;
border-collapse: collapse;
border: 2px dashed black;
}
td,
th {
padding: 5px;
border: 2px dashed black;
text-align: center;
}
tr td:nth-child(4) span {
cursor: pointer;
background: #95c1e3;
color: white;
padding: 12px;
border-radius: 50px;
font-weight: bolder;
font-size: 17px;
}
tr td:nth-child(4) span::after {
display: block;
position: absolute;
width: 100px;
height: max-content;
padding: 10px 0px 10px 0px;
background: black;
border-radius: 50px;
content: "copiado!";
opacity: 0;
translate: 0 15px;
}
<table>
<thead>
<tr>
<th>Server</th>
<th>Nombre</th>
<th>Jugadores</th>
<th>IP</th>
</tr>
</thead>
<tbody id="tabla">
<tr>
<td></td>
<td>Sin nombre</td>
<td>1399 / 5000</td>
<td><span onclick="onclicker()">hub.mc-complex.com</span></td>
</tr>
<tr>
<td></td>
<td>! SuperCraft Network [1.8-1.21] ❤ ! Amigos en: discord.supercraft.es</td>
<td>333 / 2000</td>
<td><span onclick="onclicker()">supercraft.es</span></td>
</tr>
<tr>
<td></td>
<td>1.8-1.21 NUEVO > 15 REGALOS DE NAVIDAD</td>
<td>189 / 1000</td>
<td><span onclick="onclicker()">play.zonecraft.es</span></td>
</tr>
<tr>
<td></td>
<td>! UniversoCraft Network [1.8-1.21] ❤ ! Chatea en: discord.universocraft.com</td>
<td>5427 / 20000</td>
<td><span onclick="onclicker()">mc.universocraft.com</span></td>
</tr>
</tbody>
</table>
For a CSS-only alternative, you could have the element be shown while :active
matches and then have it fade out when it longer does:
document.body.addEventListener('click', ({ target }) => {
if (target.matches('span[onclick="onclicker()"]')) {
// Add the copy class to show the `::after`.
target.classList.add('copy');
// Go through two animation frames to ensure we are on the next frame.
requestAnimationFrame(() => {
requestAnimationFrame(() => {
// Remove the copy class to hide the `::after`.
target.classList.remove('copy');
});
});
}
});
window.onclicker = () => {};
* {
font-family: monospace;
}
table {
table-layout: fixed;
width: 100%;
border-collapse: collapse;
border: 2px dashed black;
}
td,
th {
padding: 5px;
border: 2px dashed black;
text-align: center;
}
tr td:nth-child(4) span {
cursor: pointer;
background: #95c1e3;
color: white;
padding: 12px;
border-radius: 50px;
font-weight: bolder;
font-size: 17px;
}
tr td:nth-child(4) span::after {
display: block;
position: absolute;
width: 100px;
height: max-content;
padding: 10px 0px 10px 0px;
background: black;
border-radius: 50px;
content: "copiado!";
opacity: 0;
translate: 0 15px;
transition: translate 1s, opacity 1s;
}
tr td:nth-child(4) span:active::after {
opacity: 1;
translate: 0 0;
transition: 0s;
}
<table>
<thead>
<tr>
<th>Server</th>
<th>Nombre</th>
<th>Jugadores</th>
<th>IP</th>
</tr>
</thead>
<tbody id="tabla">
<tr>
<td></td>
<td>Sin nombre</td>
<td>1399 / 5000</td>
<td><span onclick="onclicker()">hub.mc-complex.com</span></td>
</tr>
<tr>
<td></td>
<td>! SuperCraft Network [1.8-1.21] ❤ ! Amigos en: discord.supercraft.es</td>
<td>333 / 2000</td>
<td><span onclick="onclicker()">supercraft.es</span></td>
</tr>
<tr>
<td></td>
<td>1.8-1.21 NUEVO > 15 REGALOS DE NAVIDAD</td>
<td>189 / 1000</td>
<td><span onclick="onclicker()">play.zonecraft.es</span></td>
</tr>
<tr>
<td></td>
<td>! UniversoCraft Network [1.8-1.21] ❤ ! Chatea en: discord.universocraft.com</td>
<td>5427 / 20000</td>
<td><span onclick="onclicker()">mc.universocraft.com</span></td>
</tr>
</tbody>
</table>