Seletor CSS para o rótulo de um botão de opção marcado

221

É possível aplicar um estilo css (3) a um rótulo de um botão de opção marcado?

Eu tenho a seguinte marcação:

<input type="radio" id="rad" name="radio"/>
<label for="rad">A Label</label>

O que eu estava esperando é que

label:checked { font-weight: bold; }

faria algo, mas infelizmente não faz (como eu esperava).

Existe um seletor que pode atingir esse tipo de funcionalidade? Você pode cercar divs, etc., se isso ajudar, mas a melhor solução seria aquela que usa o atributo label '' for ''.

Note-se que eu sou capaz de especificar navegadores para o meu aplicativo, então o melhor da classe css3 etc, por favor.

Stephen
fonte

Respostas:

361

tente o +símbolo: É um combinador de irmãos adjacentes. Combina duas seqüências de seletores simples com o mesmo pai e a segunda deve vir IMEDIATAMENTE após a primeira.

Assim sendo:

input[type="radio"]:checked+label{ font-weight: bold; } 
 //a label that immediately follows an input of type radio that is checked 

funciona muito bem para a seguinte marcação:

<input id="rad1" type="radio" name="rad"/><label for="rad1">Radio 1</label>
<input id="rad2" type="radio" name="rad"/><label for="rad2">Radio 2</label>

... e funcionará para qualquer estrutura, com ou sem divs, etc, desde que o rótulo siga a entrada de rádio.

Exemplo:

input[type="radio"]:checked+label { font-weight: bold; }
<input id="rad1" type="radio" name="rad"/><label for="rad1">Radio 1</label>
<input id="rad2" type="radio" name="rad"/><label for="rad2">Radio 2</label>

Stephen
fonte
11
Existe uma maneira de fazer isso, mas com o rótulo de ser o elemento antes EG:<label for="rad1">Radio 1</label><input id="rad1" type="radio" name="rad">
Nathan Koop
17
Você pode usar um tilda ~para selecionar elementos irmãos que não são necessariamente adjacentes. css-tricks.com/child-and-sibling-selectors
Martin
1
Obrigado, isso só me ajudou a criar "botões de opção de imagem" sem JS.
KillerX
9
Vale ressaltar que isso não funcionará no IE 8, pois o :checkedseletor não é suportado .
Mark Amery
2
@ Martin No caso de você estar se perguntando, isso realmente não funcionará no seu caso, pois o rótulo ainda precisa seguir a entrada. A diferença entre '+' e '~' é se o rótulo é diretamente adjacente ou geralmente é adecente: se o rótulo é o próximo elemento ou apenas um dos próximos elementos.
Njord
127

Sei que essa é uma pergunta antiga, mas se você gostaria de ter <input>filhos em <label>vez de separá-los, aqui está uma maneira pura de CSS que você pode fazer:

:checked + span { font-weight: bold; }

Em seguida, envolva o texto com um <span>:

<label>
   <input type="radio" name="test" />
   <span>Radio number one</span>
</label>

Veja no JSFiddle .

Mike
fonte
Excelente. Isso é muito útil quando se lida com a situação da navalha <label>@Html.RadioButtonFor(..) someText<label>, joguei <span>"someText" e funcionou como um encanto. Obrigado!
S1r-Lanzelot
Agradável! Não tinha pensado nisso.
Matthew Dean
Apenas o que eu precisava! Obrigado.
26716 Ryan
E se você quiser estilizar: rótulo ativo com: marcado? Esta não é realmente uma solução.
Maciej Krawczyk
2
@MaciejKrawczyk Não é uma solução para você porque seu caso de uso é completamente diferente. Se você deseja estilizar um rótulo: active, basta fazê-lo label:active { font-weight: bold; }. Veja: jsfiddle.net/Gbq8Z/608 (uau, não acredito que o violino tenha sido bifurcado 608 vezes).
Mike
22

Eu esqueço onde vi pela primeira vez mencionado, mas é possível incorporar seus rótulos em um contêiner em outro lugar, desde que você tenha o for=conjunto de atributos. Então, vamos verificar uma amostra no SO:

* {
  padding: 0;
  margin: 0;
  background-color: #262626;
  color: white;
}

.radio-button {
  display: none;
}

#filter {
  display: flex;
  justify-content: center;
}

.filter-label {
  display: inline-block;
  border: 4px solid green;
  padding: 10px 20px;
  font-size: 1.4em;
  text-align: center;
  cursor: pointer;
}

main {
  clear: left;
}

.content {
  padding: 3% 10%;
  display: none;
}

h1 {
  font-size: 2em;
}

.date {
  padding: 5px 30px;
  font-style: italic;
}

.filter-label:hover {
  background-color: #505050;
}

#featured-radio:checked~#filter .featured,
#personal-radio:checked~#filter .personal,
#tech-radio:checked~#filter .tech {
  background-color: green;
}

#featured-radio:checked~main .featured {
  display: block;
}

#personal-radio:checked~main .personal {
  display: block;
}

#tech-radio:checked~main .tech {
  display: block;
}
<input type="radio" id="featured-radio" class="radio-button" name="content-filter" checked="checked">
<input type="radio" id="personal-radio" class="radio-button" name="content-filter" value="Personal">
<input type="radio" id="tech-radio" class="radio-button" name="content-filter" value="Tech">

<header id="filter">
  <label for="featured-radio" class="filter-label featured" id="feature-label">Featured</label>
  <label for="personal-radio" class="filter-label personal" id="personal-label">Personal</label>
  <label for="tech-radio" class="filter-label tech" id="tech-label">Tech</label>
</header>

<main>
  <article class="content featured tech">
    <header>
      <h1>Cool Stuff</h1>
      <h3 class="date">Today</h3>
    </header>

    <p>
      I'm showing cool stuff in this article!
    </p>
  </article>

  <article class="content personal">
    <header>
      <h1>Not As Cool</h1>
      <h3 class="date">Tuesday</h3>
    </header>

    <p>
      This stuff isn't nearly as cool for some reason :(;
    </p>
  </article>

  <article class="content tech">
    <header>
      <h1>Cool Tech Article</h1>
      <h3 class="date">Last Monday</h3>
    </header>

    <p>
      This article has awesome stuff all over it!
    </p>
  </article>

  <article class="content featured personal">
    <header>
      <h1>Cool Personal Article</h1>
      <h3 class="date">Two Fridays Ago</h3>
    </header>

    <p>
      This article talks about how I got a job at a cool startup because I rock!
    </p>
  </article>
</main>

Ufa. Isso foi demais para uma "amostra", mas eu sinto que realmente leva a efeito e ponto: certamente podemos selecionar um rótulo para um controle de entrada verificado sem que seja um irmão. O segredo está em manter as inputtags de uma criança apenas no que elas precisam ser (neste caso - apenas no bodyelemento) .

Como o labelelemento não utiliza o :checkedpseudo-seletor, não importa que os rótulos estejam armazenados no header. Ele tem o benefício adicional de que, como headeré um elemento irmão, podemos usar o ~seletor genérico de irmão para mover do input[type=radio]:checkedelemento DOM para o headercontêiner e, em seguida, usar seletores descendentes / filhos para acessar os labelpróprios, permitindo a capacidade de estilizá-los quando seus as respectivas caixas de seleção / rádio estão marcadas .

Não apenas podemos estilizar os rótulos, mas também estilizar outro conteúdo que possa ser descendente de um contêiner irmão em relação a todos os inputs. E agora, no momento em que todos esperavam, o JSFIDDLE ! Vá lá, brinque com ele, faça funcionar para você, descubra por que funciona, quebre, faça o que você faz!

Espero que tudo faça sentido e responda totalmente à pergunta e, possivelmente, qualquer acompanhamento que possa surgir.

Nathan Blair
fonte
2
Esta é a resposta para esta pergunta. Outros enquanto corretos são essencialmente super básicos. Embora isso resolva algo mais complicado e interessante, alguém seria tentado a pegar js.
morphles
A resposta aceita a esta pergunta tem> 30x mais votos positivos, apesar de impor uma limitação que essa resposta obvia totalmente. Ao contrário de muitas postagens com o mesmo estilo que pretendem informações alucinantes, isso realmente cumpre a reivindicação. Trabalho incrível, muito obrigado.
Naughtilus #
1
@naughtilus - esta resposta evita totalmente a limitação da resposta simples, porque define explicitamente os estilos para cada opção. isto é, o meu obriga a ter uma convenção de estrutura; este obriga a escrever css para cada botão de opção e resultado.
Stephen
@ morphles simple! = "super basic": esta solução é mais complicada, interessante e poderosa - para esse código exato; o meu funcionará em todas as páginas após 1 convenção
Stephen
1

Se sua entrada for um elemento filho do label e você tiver mais de um rótulo, poderá combinar o truque de @ Mike com Flexbox+ order.

insira a descrição da imagem aqui

html
<label class="switchLabel">
  <input type="checkbox" class="switch"/>
  <span class="left">Left</span>
  <span class="right">Right</span>
</label>
css
label.switchLabel {
  display: flex;
  justify-content: space-between;
  width: 150px;
}
.switchLabel .left   { order: 1; }
.switchLabel .switch { order: 2; }
.switchLabel .right  { order: 3; }

/* sibling selector ~ */
.switchLabel .switch:not(:checked) ~ span.left { color: lightblue }
.switchLabel .switch:checked ~ span.right { color: lightblue }

Veja no JSFiddle .

Nota: O seletor de irmãos funciona apenas no mesmo pai. Para contornar isso, você pode ocultar a entrada no nível superior usando o @Nathan Blair hack.

Qwerty
fonte
-1

Você poderia usar um pouco de jQuery:

$('input:radio').click(function(){
    $('label#' + $(this).attr('id')).toggleClass('checkedClass'); // checkedClass is defined in your CSS
});

Você precisaria garantir que os botões de opção marcados também tenham a classe correta no carregamento da página.

Dan Herd
fonte
3
Sim ... é claro que é possível fazer isso via javascript (frameworks), mas não é tão simples quanto parece. O que acontece se algo já tiver marcado a caixa? Qual script removerá essa classe se outro rádio no mesmo grupo for selecionado? Fica muito complicado muito rápido. Eu quero usar a funcionalidade interna do formulário + css do navegador, porque funcionará sempre.
Stephen
4
O seu seletor deve ser$('label[for="' + $(this).attr('id') + '"]').toggleClass();
Wesley Murch
-3

ATUALIZAR:

Isso só funcionou para mim porque nosso html gerado existente era maluco, gerando labels junto com radios e fornecendo a amboschecked atributo.

Não importa, e grandes ups para Brilliand por trazê-lo à tona!

Se seu rótulo é um irmão de uma caixa de seleção (que geralmente é o caso), você pode usar o ~seletor de irmãos e um label[for=your_checkbox_id]para endereçá-lo ... ou atribuir um ID ao rótulo se você tiver vários rótulos (como neste exemplo, onde eu use etiquetas para botões)


Vim aqui procurando o mesmo - mas acabei encontrando minha resposta nos documentos .

um labelelemento com checkedatributo pode ser selecionado da seguinte forma:

label[checked] {
  ...
}

Eu sei que é uma pergunta antiga, mas talvez ajude alguém lá fora :)

apprenticeDev
fonte
5
E como o rótulo deve ser verificado?
Brilliand
2
Ei, boa captura. Não faz. Aparentemente, temos um código muito maluco que gera rótulos junto com botões de opção e adiciona um atributo "marcado" a ambos ao gerar o html. Mas não é realmente válido ... Portanto, isso é totalmente inutilizável. Vou editar a resposta, não tenho idéia do motivo pelo qual recebi os votos positivos. Obrigado!
apprenticeDev