Usando CSS3 para formatar radio buttons
Leia em 2 minutos
Quando você não precisa dar suporte para versões antigas do Internet Explorer, sua vida fica infinitamente mais simples. Muitas funcionalidades que antes exigiam JavaScript agora podem ser feitas com apenas CSS.
Estou fazendo o novo site do HOWTO e em uma das partes do formulário de inscrição eu exibo os meios de pagamento.
A ideia é que ele se comporte como um radio button comum, mas que adicione uma borda e um ícone indicando o pagamento selecionado. O markup que usei é bastante simples e sem elementos especiais.
<ul class="payment-methods">
<li class="payment-method paypal">
<input name="payment_methods" type="radio" id="paypal">
<label for="paypal">PayPal</label>
</li>
<li class="payment-method pagseguro">
<input name="payment_methods" type="radio" id="pagseguro">
<label for="pagseguro">PagSeguro</label>
</li>
<li class="payment-method bankslip">
<input name="payment_methods" type="radio" id="bankslip">
<label for="bankslip">Boleto</label>
</li>
</ul>
O CSS que define cada uma das caixas é bastante simples.
.payment-methods {
list-style: none;
margin: 0;
padding: 0;
}
.payment-methods:after {
content: "";
clear: both;
}
.payment-method {
border: 1px solid #ccc;
box-sizing: border-box;
float: left;
height: 70px;
position: relative;
width: 120px;
}
.payment-method + .payment-method {
margin-left: 25px;
}
Isso fará com que as caixas tenham essa aparência.
Agora, vamos fazer com que o label fique por cima do radio button. Para fazer isso, vamos adicionar uma cor de fundo e posicionar o elemento.
.payment-method label {
background: #fff no-repeat center center;
bottom: 1px;
cursor: pointer;
display: block;
font-size: 0;
left: 1px;
position: absolute;
right: 1px;
text-indent: 100%;
top: 1px;
white-space: nowrap;
}
.pagseguro label {
background-image: url(uol.png);
}
.paypal label {
background-image: url(paypal.png);
}
.bankslip label {
background-image: url(bankslip.png);
}
Agora, vamos fazer o elemento ser destacado quando é focado. Para isso nós iremos usar o pseudo-seletor :focus
.
.payment-methods input:focus + label {
outline: 2px dotted #21b4d0;
}
Para fazer o elemento selecionado ser marcado, basta adicionar uma regra semelhante usando o pseudo-seletor :checked
.
.payment-methods input:checked + label {
outline: 4px solid #21b4d0;
}
Só falta definir o ícone de “checked”. Para fazer isso, vamos definir um pseudo-elemento com uma imagem de fundo.
.payment-methods input:checked + label:after {
background: url(checked.png);
bottom: -10px;
content: "";
display: inline-block;
height: 20px;
position: absolute;
right: -10px;
width: 20px;
}
Infelizmente, isso não funcionou muito bem no Firefox, embora tenha funcionado em todos os outros navegadores, incluindo Internet Explorer 9. Aparentemente ele se perde por que o label
não tem suas dimensões especificadas; em vez de definir a altura e largura, posicionei o elemento com top
, right
, bottom
e left
, expandindo o elemento.
Como eu não quis definir as dimensões, mudei a abordagem e deixei o ícone com uma aparência quadrada somente no Firefox. E para fazer isso usei a instrução @-moz-document
.
@-moz-document url-prefix() {
.payment-methods input:checked + label:after {
bottom: 0;
right: 0;
background-color: #21b4d0;
}
}
A vantagem de ter feito tudo isso usando CSS é que todo o comportamento dos radios buttons permaneceu inalterado, como a seleção através de teclado e o foco no elemento, sem ter que usar nenhuma linha de JavaScript sequer. \m/
O resultado final pode ser visto no Codepen.