Como desativar o botão enviar e os links ao clicar em CSS puro?

9

Desafiei-me a criar uma experiência visualmente dinâmica e interativa apenas em HTML e CSS (sem Javascript). Até agora, não encontrei nenhum recurso que eu precisasse em CSS e HTML puro. Este talvez seja um pouco mais difícil.

Eu preciso impedir que o usuário clicar duas vezes <a>, <input type="submit">e <button>tags. Isso evita que eles enviem um formulário duas vezes ou acidentalmente façam 2 solicitações GET para um URL. Como isso pode ser feito em CSS puro? Mesmo que não possamos definir disabledsem o JS, deve haver alguma técnica de máscara ou combinação de estilos que possa lidar com isso aqui em 2020.

Aqui está um exemplo simples de uma tentativa:

.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>

Infelizmente, isso é desativado antes que o evento de clique real seja acionado por algum motivo. Talvez as âncoras não sejam a melhor maneira de testar? Vou continuar a fazer novas tentativas.

Paragon512
fonte
você pode fazer o formulário dar uma aula para si mesmo depois de enviado pela primeira vez?
SIGSTACKFAULT
11
Talvez pointer-events: allpor padrão, mas não nos estados: active ou: focus? Como definido pointer-events: nonepara esses estados?
Jeremy Harris
talvez el:active, el:focuscombinado com eventos-ponteiro
Paragon512
Isto funciona? : ativo {display: nenhum; // por exemplo}
MD Hesari
Tentativa adicionada. Ele foi desativado antes de disparar o clique.
Paragon512 5/02

Respostas:

4

Uma idéia é ter uma camada que apareça na parte superior do elemento após o primeiro clique para evitar o segundo.

Aqui está uma idéia básica em que considerarei uma duração 1sentre dois cliques que você pode diminuir. Tente clicar no botão / link e você perceberá que só pode clicar novamente depois 1s.

Estou adicionando uma pequena sobreposição para ver melhor o truque

.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
fonte
11
parece que não está funcionando com <a>tag
Aleksandr Belugin
@AleksandrBelugin está funcionando bem, verifique a atualização. Talvez você tenha feito algo errado
Temani Afif
Eu acho que ainda me permite clicar no botão 2 vezes? Eu posso ver o botão pressionar pela segunda vez.
Paragon512
11
@TemaniAfif quando faço isso <a href="#" onclick="console.log('lalala')">Click me</a>para vincular com o restante do código, nada registra no console. imho isso significa que o link não é clicado
Aleksandr Belugin
11
Parece que a melhor maneira de testar isso é com a <a>tag. Tentei testar com os botões de envio, mas monitorar o inspetor de rede é estranho e inconsistente. Quando clico no link, ele não dispara. Se você definir um destino para uma âncora e clicar no link, ele desativará o link, mas não passará para a âncora.
Paragon512 5/02
0

A primeira solução

A idéia é usar radio buttonstate by :checkedpara fazer modificações. Escondemos radiocírculo e quando :checkedpara <a>fazer pointer-events: none;e para buttonscom tipos diferentes, os escondemos e mostramos disabled.

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>

A segunda solução

Este serve para links. A ideia é usar :target. O Targe elementestá oculto em primeiro lugar. Então, quando é direcionado, use :targetpara pointer-events: none;de <a>.

Aleksandr Belugin
fonte