¿Cómo deshabilitar el botón de enviar y los enlaces al hacer clic en CSS puro?

9

Me he desafiado a mí mismo para crear una experiencia visualmente dinámica e interactiva en HTML y CSS solamente (sin Javascript). Hasta ahora, no he encontrado ninguna característica que necesitara que no pudiera hacer en CSS y HTML puro. Este es quizás un poco más difícil.

Tengo que evitar que el usuario hace doble clic <a>, <input type="submit">y <button>las etiquetas. Esto es para evitar que envíen dos veces un formulario o realicen accidentalmente 2 solicitudes GET a una URL. ¿Cómo se puede hacer esto en CSS puro? Incluso si no podemos establecer disabledsin JS, debería haber alguna técnica de enmascaramiento o combinación de estilos que pueda manejarlo aquí en 2020.

Aquí hay un ejemplo simple de un intento:

.clicky:focus{
  display: none;
  pointer-events: none;
}
<a href="#down" class="clicky">test</a>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p id="down">target</p>

Desafortunadamente, esto lo deshabilita antes de que se active el evento de clic real por alguna razón. ¿Quizás las anclas no son la mejor manera de probar? Continuaré haciendo más intentos.

Paragon512
fuente
¿Puedes hacer que el formulario se dé una clase después de que se haya enviado por primera vez?
SIGSTACKFAULT
1
Tal vez pointer-events: allpor defecto, pero no en los estados: activo o: ¿foco? ¿Como establecido pointer-events: nonepara esos estados?
Jeremy Harris
tal vez el:active, el:focuscombinado con eventos de puntero
Paragon512
¿Esto funciona? : activo {display: none; // por ejemplo}
MD Hesari
Intento agregado. Sin embargo, lo deshabilitó antes de disparar el clic.
Paragon512

Respuestas:

4

Una idea es tener una capa que aparezca en la parte superior del elemento después del primer clic para evitar el segundo.

Aquí hay una idea básica donde consideraré una duración de 1s entre dos clics que puede disminuir. Intente hacer clic en el botón / enlace y notará que puede hacer clic nuevamente solo después 1s.

Estoy agregando una pequeña superposición para ver mejor el truco

.button {
  position:relative;
  display:inline-block;
}
.button span{
  position:absolute;
  top:0;
  left:0;
  right:0;
  bottom:100%;
  z-index:-1;
  animation:overlay 1s 0s; /* Update this value to adjust the duration */
  transition:0s 2s; /* not this one! this one need to be at least equal to the above or bigger*/
}


.button *:active + span {
  animation:none;
  bottom:0;
  transition:0s 0s;
}

@keyframes overlay {
  0%,100% {
    z-index:999;
    background:rgba(255,0,0,0.2); /* To illustrate */
  }
}
<div class="button">
  <button>Click me</button>
  <span></span>
</div>

<div class="button">
  <a href="#" onclick="console.log('clicked !')">Click me</a>
  <span></span>
</div>

Temani Afif
fuente
1
parece que no funciona con la <a>etiqueta
Aleksandr Belugin
@AleksandrBelugin está funcionando bien, verifique la actualización. Tal vez hiciste algo mal
Temani Afif
¿Creo que todavía me deja hacer clic en el botón 2 veces? Puedo ver el botón presionar la segunda vez.
Paragon512
1
@TemaniAfif cuando hago esto <a href="#" onclick="console.log('lalala')">Click me</a>para vincular con el resto del código, nada se registra en la consola. En mi opinión, el enlace no se hace clic
Aleksandr Belugin
1
Parece que la mejor manera de probar esto es con la <a>etiqueta. Intenté probar con los botones de envío, pero monitorear al inspector de red es extraño e inconsistente. Cuando hago clic en el enlace, no activa el clic. Si establece un objetivo en un ancla y hace clic en el enlace, deshabilitará el enlace pero no saltará al ancla.
Paragon512
0

La primera solución

La idea es usar radio buttonstate by :checkedpara hacer modificaciones. Escondemos el radiocírculo y cuándo :checkedpara <a>hacer pointer-events: none;y para buttonsdiferentes tipos los ocultamos y mostramos disabledunos.

div {
  margin: 10px;
}

#radio0, .my-checkbox {
  position: absolute;
  height: 0;
  width: 0;
  opacity: 0;
}

#radio0 + a label {
  cursor: pointer;
}

#radio0:checked+a {
  pointer-events: none;
}

.btn-one,
.btn-two {
  padding: 0;
}

.btn-one>label,
.btn-two>label {
  padding: 1px 6px;
}

.my-checkbox:checked+.btn-one {
  display: none;
}

.btn-two {
  display: none;
}

.my-checkbox:checked+.btn-one+.btn-two {
  display: inline-block;
}
<div>
  <input id="radio0" type="radio" onclick="console.log('radio0 clicked!')">
  <a href="#">
    <label for="radio0">
        Click the link!
      </label>
  </a>
</div>

<div>
  <input type="radio" id="radio1" class="my-checkbox">
  <button type="button" class="btn-one" onclick="console.log('radio1 clicked!')">
      <label for="radio1">Click the button!</label>
    </button>
  <button type="button" class="btn-two" onclick="console.log('radio1 NOT clicked!')" disabled>
        <label for="radio1">Click the button!</label>
      </button>
</div>

<div>
  <input type="radio" id="radio2" class="my-checkbox">
  <button type="submit" class="btn-one" onclick="console.log('radio2 clicked!')">
    <label for="radio2">Submit!</label>
  </button>
  <button type="submit" class="btn-two" onclick="console.log('radio2 NOT clicked!')" disabled>
      <label for="radio2">Submit!</label>
    </button>
</div>

La segunda solución

Este se adapta para links. La idea es usar :target. El objetivo elementestá oculto en primer lugar. Luego, cuando se dirige el uso :targetde pointer-events: none;de <a>.

Aleksandr Belugin
fuente