How to make the label work with a link inside?

Asked

Viewed 986 times

3

How to do that when clicking on the link the checkbox is also selected?

Follows excerpt from the code below:

input {
  display: block;
}
label {
  display: block;
  margin-top: 20px;
}
iframe {
  margin-top: 20px;
  width: 100%;
}
<input type='checkbox' id='ch' />

<label for='ch'>
  <a href='https://dottcon.com' target='conteudo'>Site</a>
</label>

<iframe name='conteudo'></iframe>

I need that when clicking on the link the checkbox is marked or unchecked depending on its current state.

Note: If possible would like not to use JS.

  • 2

    This type of control you will only get with JS.

3 answers

4


It doesn’t need JS at all, but it seems as wrong as it should be.

I see no structural motive, let alone semantics for using a link within a label! See you on your way label has a for, ie, has a control input... I strongly recommend you read this: In the <label> it is semantic or allowed to use which elements inside?

But if you want to go through with it, just use a combination of z-index -1 and a tabindex -1 in the link, so when you click on it in reality you will be clicking on label, which in turn already has a for='ch' to the checkbox resulting in what you want.

inserir a descrição da imagem aqui

With the z-index -1 and tabindex -1 the link is inaccessible to both the mouse and the keyboard, so you cannot do the focus on it, and when you click you will click on the label, not on the link that is "blocked"


EDIT

I will complement with some information, because for me it was not clear that he wanted to load iframe, I thought he just wanted to mark the checkbox by clicking on the link

First I will make clear some details, to be exactly as in the code that is in the question, ie even without the iframe being loaded it takes up a space on the screen, so I put in it visibility:hidden, and I used a new attribute called loading="lazy", with that even without the iframe appear on the screen it occupies the corresponding space, and will only be loaded in background on demand due to the lazy load, with that the page does not get too heavy.

So you don’t need logic target/name, and let the src correct in the iframe (despite this I still left the attributes there for you to see that one thing does not interfere with the other)

Then his iframe has a frameborder, for me to ensure that the edge will appear, even without the iframe be visible, I needed to put the iframe within a div with class .box. In that div.box I put the same edge styles of the user-agent and in the iframe i put frameborder="0". Right now without the iframe being visible it still has the edges.

Now to "activate" the iframe case I clicked on link I used a simple rule of CSS selectors input:checked ~ .box > iframe{ visibility: visible; } So if the checkbox receive the cheked he will look for the first brother element below that has the class .box and within the .box the iframe and will set the element witho visible.

input {
  display: block;
}
label {
  display: block;
  margin-top: 20px;
}
iframe {
  /* margin-top: 20px; */
  width: 100%;

  visibility: hidden;
}
a {
  position: relative;
  z-index: -1;
}

input:checked ~ .box > iframe{
  visibility: visible;
}
.box {
  margin-top: 20px;

  display: flex;
  border-width: 2px;
  border-style: inset;
  border-color: initial;
  border-image: initial;
}
<input type='checkbox' id='ch' />

<label for='ch'>
  <a tabindex="-1" href='https://dottcon.com' target='conteudo'>Site</a>
</label>

<div class="box">
  <iframe src="https://dottcon.com" name='conteudo' loading="lazy" frameborder="0"></iframe>
</div>

  • It was almost, but when clicking the link also has to open in iframe. In the case you put I can only make the selection of chekbox.

  • @Allanmax understood young, is that for me it had not been clear that you wanted to load the iframe, for me you just wanted to mark the checkbox by clicking on the link... However, read the EDIT I did there in the answer, it has some details, but it is not difficult to understand. All only with CSS/HTML, and optimized not to weigh too much the screen if you have other iframes further down

1

I also think this will only be possible with javascript so I changed the html a little and made a script.

function showFrame() {
  const frame = document.getElementsByName("conteudo")[0];
  const checkbox = document.getElementById("ch");

  if (checkbox.checked) {
    frame.src = "https://dottcon.com";
  } else {
    //quando o checkbox nao estiver selecionado fazer alguma coisa
  }

}
<a href='#' target='conteudo' onclick="showFrame();">
  <input type='checkbox' id='ch' />
  <label for='ch'>
          Site
        </label></a>
<iframe name='conteudo'></iframe>

0

Without Javascript you won’t get what you want. As @hugocss said, putting a link inside the label is not the best idea.

You can leave the label normal, without link, only a text that you can indicate being a link (putting cursor: pointer, for example), and open the page you want inside the iframe otherwise, using Javascript and attributes dataset, as data-url and data-target.

As the link is a child of the label and this has a for directly related to id from the checkbox, it is easy to find it by clicking on the label. Just use a event handler click taking the value of for of the parent label and fetch the respective checkbox with it id that for:

// seleciona todos os checkbox
const boxes = document.querySelectorAll("[type='checkbox']");
// seleciona todos os label
const labels = document.querySelectorAll("label");

// cria event handlers para os checkbox
for(let i of boxes){
   i.onclick = function(){
      let id = this.getAttribute("id"); // pega o id do checkbox clicado
      // procura um label com um "for" igual ao id
      let label = document.querySelector("[for='"+id+"']");
      // se existir, chama a função enviando o label como parâmetro
      if(label) controle(label);
   }
}

// cria event handlers para os label
for(let i of labels){
   i.onclick = function(){
      let id = this.getAttribute("for"); // pega o "for" do label clicado
      // procura um checkbox com um id igual ao "for"
      let box = document.querySelector("#"+id);
      // se existir, chama a função enviando o label como parâmetro
      if(box) controle(i);
   }
}

function controle(label){
   
   let id = label.getAttribute("for"); // pega o "for" da label
   let url = label.dataset.url; // pega o data-url
   let target = label.dataset.target; // pega o data-target
   let box = document.getElementById(id); // pega o checkbox pelo id
   
   if(box.checked){
      // se o box for marcado, abrir a URL no iframe
      document.querySelector("[name='"+target+"']").src = url;
   }else{
      // faz algo quando o checkbox estiver desmarcado, como esvaziar o iframe
      document.querySelector("[name='"+target+"']").src = "";
   }
   
}
input {
  display: block;
}
label {
  display: block;
  margin-top: 20px;
  text-decoration: underline;
  cursor: pointer;
  color: blue;
}
iframe {
  margin-top: 20px;
  width: 100%;
}
<input type='checkbox' id='ch' />
<label for='ch' data-url="https://dottcon.com" data-target="conteudo">
  Site
</label>
<iframe name='conteudo'></iframe>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.