Mais uma vez sobre a caixa de seleção de visualização de tipos de entrada e rádio. Para quem se esqueceu de como

O assunto é antigo e já, como se viu, esquecido.



Recentemente, tive um breve trabalho no desenvolvimento de especificações técnicas para a modernização de um projeto antigo. E, em particular, o caso dizia respeito ao estilo do notório <input type = "checkbox">. Acontece que o performer, um programador "para todos os negócios", nem mesmo entendeu que eu estava explicando em palavras como fazê-lo. Tive que dar exemplos e, como resultado, apareceu este texto.



Deixe-me lembrá-lo de que agora a caixa de seleção e a caixa de rádio são representadas de forma diferente por sites diferentes. Acontece que uma entrada não marcada não pode ser discernida imediatamente - ela é tão "bonita de design", e nas versões mais recentes do Chrome, as caixas de seleção selecionadas se tornaram uma cor ciano horrível.



Então a situação



Existem três empresas que usam um determinado produto de software relacionado a pedidos, contabilidade, depósito, etc. Trabalhar com clientes, parceiros, executores, etc.



Comerciantes e anunciantes também o usam. O que este sistema faz - não importa o que esteja escrito - não importa.



E é importante que o site deste produto tenha muitas páginas com formulários, nos quais existem muitos checkboxes de entrada e rádio.



Reclamações de funcionários



Diretor : Na tela grande, os "kryzhiki" são difíceis de ver e são invisíveis.

Contador-chefe : No meu computador, o "kryzhiki" é assim, nos funcionários é diferente, em casa também é diferente, mas em um tablet é completamente diferente.

Profissional de marketing : É possível que algumas posições não selecionadas fiquem vermelhas e outras selecionadas fiquem verdes?

Etc.



Então a tarefa



  1. Corrija a aparência da caixa de seleção e da caixa de rádio com custos mínimos e alterações mínimas.
  2. Crie um estilo de caixa de seleção e caixa de rádio para usuários diferentes. Importante: este é um site fechado, existem "todos nós", "beleza" não é necessária, mas é necessária eficiência de percepção.


O que não é permitido



1. O lado do servidor não deve ser tocado.

2. Você não pode tocar em arquivos javascript, não pode inserir seu próprio javascript.

3. Os arquivos css não podem ser tocados.



O que é permitido



1. Edite os modelos html.

2. Crie um arquivo de estilo para todos os usuários.

4. Crie um arquivo de estilo para um usuário ou grupo de usuários específico.

E o que você fez, você pode olhar imediatamente para codepen.io , mas é melhor ler mais.



Estudo preliminar mostrou



1. Quase todos os <input type = "checkbox"> têm um campo de nome e aqueles que não têm um id.

2. Todos os <input type = "radio"> têm um campo de nome, alguns têm um id.

3. Assim, no css, a caixa de seleção pode ser acessada tanto por id quanto por nome. Para o rádio - seja pelo id ou pelo número do filho dos pais.



Snippets de código-fonte:



/*  1 */
<tag><input type="checkbox">  </tag>

/*  2 */
<tag><input type="checkbox">  <br>
<input type="checkbox">  </tag>

/*  3 */
...<label><input type="checkbox">  </label>...

/*  4 */
<td><input id="idxxx" type="checkbox"></td>
<td><label for="idxxx"> </label></td>


Vamos consertar o código:



/*  1 */
<tag><label class="new-input"><input type="checkbox"><s></s><span> </span></label></tag>

/*  2 */
<tag><label class="new-input"><input type="checkbox"><s></s><span> </span></label><br>...</tag>

/*  3 */
...<label class="new-input"><input type="checkbox"><s></s><span> </span></label>...

/*  4 */
<td><label class="new-input new-input-one"><input id="idxxx" type="checkbox"><s></s></label></td>
<td><label for="idxxx"> </label></td>


Tudo é igual para <input type = "radio">, a classe LABEL é a mesma.



O que exatamente você fez?



  1. Cada entrada (popa da opção 3) foi envolvida com uma tag LABEL com nossa classe. A opção 3 acabou de adicionar uma classe.
  2. Imediatamente após a entrada, uma tag vazia foi inserida, uma vez que a entrada em si não estará visível, esta tag irá renderizar esta entrada.
  3. O texto que o acompanha foi empacotado com a marca SPAN (exceto para a opção 4). Essa tag será necessária quando decidirmos a questão de alinhar a entrada visual em relação a este texto.
  4. Na opção 4 foi adicionada outra classe para evitar esse alinhamento, já que o texto que a acompanha está em outra célula da tabela. A rigor, seria necessário fazer o oposto - adicionar uma classe responsável pelo alinhamento às opções 1-3. Porém, existem muito mais opções 1-3 do que a 4ª, e para não inflar o html é feito assim.


Perguntas retóricas e respostas retóricas
1. S? , S – . , input.



2. S SPAN ? , html? , , «» .



  .new-input > S { }
  .new-input > .new-input-S {}


3. , , «» html . – mni mnio. :-))



Algumas considerações preliminares e ajustes de CSS com relação ao tamanho da caixa: border-box, normalização LABEL, A + B, A ~ B e seletores [attr] ,: marcada ,: desativada e :: antes das pseudo classes. Quem não tem certeza do que sabe ou deseja atualizar seus conhecimentos, olha para baixo.



Considerações preliminares
1. , «» css (box-sizing:content-box) width height , padding border . box-sizing:border-box , padding border width height.



2. , , «» . «» LABEL , . LABEL.



LABEL {
    box-sizing:border-box; cursor:pointer; user-select:none;
}
LABEL *,
LABEL *::before,
LABEL *::after {
    box-sizing:inherit;
}


.., box-sizing:border-box LABEL, . ( ).



3. «A + B» , B, A, .. B. , «A ~ B» , B A, .. .

, «».



?



<label class="new-input"><input type="checkbox"><s></s><span> </span></label>
<label class="new-input"><input type="radio"><s></s><span> </span></label>


/* 1 */
.new-input > INPUT + S {}
.new-input > INPUT ~ SPAN {}

/* 2 */
.new-input > INPUT:not(:checked) + S {}
.new-input > INPUT:not(:checked) ~ SPAN {}

/* 3 */
.new-input > INPUT:checked + S {}
.new-input > INPUT:checked ~ SPAN {}

/* 4 */
.new-input > INPUT:disabled + S {}
.new-input > INPUT:disabled ~ SPAN {}

/* 5 */
.new-input > INPUT[type="radio"] + S {}


– S SPAN.

– INPUT .

– INPUT .

– INPUT .



, , – S , input radio.

, S SPAN input.



4. S input, input display:none, , LABEL , S . html hidden input? , hidden input «» , html .



Então, vamos começar a renderizar a entrada



Exemplo N 1. O mais simples - usamos caracteres alfabéticos. O

código html é o mesmo, e o css será assim:



/* s1 */
.new-input > INPUT + S::before {
  content: "c";
}
/* s2 */
.new-input > INPUT:checked + S::before {
  content: "V";
}
/* s3 */
.new-input > INPUT[type="radio"] + S::before {
  content: "r";
}
/* s4 */
.new-input > INPUT[type="radio"]:checked + S::before {
  content: "X";
}
/* s5 */
.new-input > INPUT:disabled + S::before {
  opacity: 0.5;
}
/* s6 */
.new-input > S {
  text-decoration: none;
  margin-left: 3px;
  margin-right: 6px;
}
/* s7 */
.new-input > S::before {
  display: inline-block;
  width: 1.25em;
  text-align: center;
  color: #fafafa;
  background-color: #37474f;
}
/* s8 */
.new-input > INPUT[type="radio"] + S::before {
  border-radius: 50%;
}


A tag S renderizará a entrada. Mas vamos "dividi-lo" por funcionalidade: a própria tag S será responsável pela colocação no LABEL e pelo alinhamento em relação ao próximo SPAN.



E o pseudo-elemento S :: before será colocado dentro da tag S e atuará como entrada.



A linha s1 define qual caractere será colocado em S :: antes quando a entrada não for selecionada. Em princípio, seria necessário escrever ".new-input> INPUT: not (: selected) + S :: before", mas alguns navegadores (por exemplo, IE) podem não executar tal construção.

A string s2 especifica o caractere quando a entrada é selecionada.

As linhas s3 e s4 fazem o mesmo para o rádio de entrada.

String s5descreve o que acontece se a entrada for bloqueada - neste caso, a tag S será metade transparente.

A linha s6 define o alinhamento, neste caso fornece preenchimento à esquerda e à direita (apenas neste exemplo). Além disso, remove o tachado normal.

A linha s7 forma um quadrado, s8 o transforma em um círculo para o rádio de entrada.



O exemplo # 1 pode ser visto em codepen.io . Existem entradas nativas e novas. O primeiro pode ser removido.



Um pouco mais de detalhes sobre a exibição: bloco embutido, tamanho da fonte, altura da linha
font-size, line-height. line-height – font-size, line-height – , line-height – . line-height:1.25, S::before width:1.25em.



S::before display: inline-block – S::before «» ( , , .), «» . .





Pergunta:



Você pode usar caracteres especiais? Como estes:

□ ■ ▢ ▣ ○ ● ◎ ◉

Dê a eles o tamanho certo e é isso. Não?



Resposta:



você pode. Mas você não precisa. Pois haverá grandes hemorróidas e danças com pandeiros na atribuição do tamanho desejado, alinhamento vertical, corte e assim por diante. Além disso, navegadores diferentes funcionam de maneira diferente com esses símbolos.

Nós fomos por outro caminho. Embora o exemplo final contenha uma implementação dessa ideia.



Exemplo N 2. Os elementos de entrada "Desenhar" usando o



código css html são iguais, mas o css será assim:



/* s1 */
.new-input > S::before {
  content: "";
  display: inline-block;
  width: 0.75em;
  height: 0.75em;
  border: 1px solid currentColor;
  padding: 2px;
  background-clip: content-box;
  border-radius: 20%;
}
/* s2 */
.new-input > INPUT[type="radio"] + S::before {
  border-radius: 50%;
}
/* s3 */
.new-input > INPUT:checked + S::before {
  background-color: currentColor;
}
/* s4 */
.new-input > INPUT:disabled + S::before {
  opacity: 0.5;
}
/* s5 */
.new-input > S {
  text-decoration: none;
  margin-left: 3px;
  margin-right: 6px;
}


A linha s1 define S :: antes de renderizar a entrada. Este será um bloco embutido cuja largura e altura são definidas como 0,75em, que é aproximadamente a mesma altura da letra maiúscula e depende do tamanho da fonte do pai. Uma borda fina é definida com a cor atual, preenchimento interno e pequenos arredondamentos de cantos. E o mais importante! - propriedade background-clip: content-box está definido. Esta é uma propriedade muito interessante - se a cor de fundo for definida, ela pintará apenas a parte do conteúdo e não afetará o preenchimento. O que precisamos.



A linha s2 para uma entrada de rádio torna S :: antes da rodada.

A linha s3 para a entrada marcada define S :: antes da cor de fundo para a cor atual. Ou seja, ele "desenha" um quadrado ou círculo dentro.

Linhas4 desbloqueia a entrada, a linha s5 fornece preenchimento à esquerda e à direita.



As vantagens deste método



  1. Tudo é muito simples. Funciona em todos os navegadores. Até o IE10 (emulação do 11º).
  2. Você pode colorir como quiser.
  3. Como S :: before é um bloco embutido, ele fica exatamente na parte inferior da linha de base e não sai dela em lugar nenhum. Se for maior que o texto, ele simplesmente aumentará a altura da linha e permanecerá na linha de base.
  4. Como a visualização de entrada está dentro de uma tag S, ela pode ser posicionada e alinhada facilmente.
  5. As dimensões de S :: before in em permitem definir seu tamanho em relação ao tamanho do texto da legenda. Você pode, por exemplo, definir limites para a altura e largura.


Desvantagens deste método



Principalmente nos tamanhos em. O fato é que pode surgir uma situação em que a largura e a altura no cálculo (de em a px) terão um valor fracionário. O arredondamento pode não funcionar corretamente em computadores comuns com uma tela normal. Por exemplo, as dimensões de 12,8 por 12,8 pixels no mesmo Mozila podem se tornar 13 por 12 pixels. Então você precisa definir tamanhos fixos. Embora em monitores e placas de vídeo modernos, laptops, tablets e smartphones, isso não acontece devido ao fato de o ponto (pixel) do navegador ser composto por vários pixels da tela.



O exemplo # 2 pode ser visto em codepen.io . Existem entradas nativas e novas. O primeiro pode ser removido.

Portanto, a primeira tarefa - renderizar a entrada - está concluída. Passamos para a "coloração" selecionada.



Entrada para colorir



html por exemplo:



<label class="new-input"><input name="chb1" type="checkbox" ...><s></s><span> </span></label>
<label class="new-input"><input id="rb1" type="radio" ...><s></s><span> </span></label>


Iremos nos referir a uma entrada do tipo de caixa de seleção por nome, para rádio por id.



Nós pintamos tudo de azul



/*  input */
.new-input > INPUT[name="chb1"] + S,
.new-input > INPUT#rb1 + S {
  color: #0091ea;
}
/*  text */
.new-input > INPUT[name="chb1"] ~ SPAN,
.new-input > INPUT#rb1 ~ SPAN {
  color: #0091ea;
}
/*   */
.new-input > INPUT[name="chb1"] ~ *,
.new-input > INPUT#rb1 ~ * {
  color: #0091ea;
}


Lembre-se da especificidade do CSS, esses estilos serão mais específicos do que os básicos e com certeza funcionarão. Como eles diferem daqueles descritos acima? Aqueles que se aplicam apenas para selecionar entradas - aqueles que têm o nome e id especificados.



Tudo está bem aqui, exceto que as entradas não selecionadas não parecerão muito boas - a fina borda azul é quase imperceptível.



Pinte-o de verde quando a entrada for selecionada



/*  input */
.new-input > INPUT[name="chb1"]:checked + S,
.new-input > INPUT#rb1:checked + S {
  color: #00c853;
}
/*  text */
.new-input > INPUT[name="chb1"]:checked ~ SPAN,
.new-input > INPUT#rb1:checked ~ SPAN {
  color: #00c853;
}
/*   */
.new-input > INPUT[name="chb1"]:checked ~ *,
.new-input > INPUT#rb1:checked ~ * {
  color: #00c853;
}


A primeira opção, na minha opinião, não é muito boa - tanto a moldura quanto o quadrado / círculo interno serão verdes. Você só pode colorir.



/*  input    */
.new-input > INPUT[name="chb1"]:checked + S::before,
.new-input > INPUT#rb1:checked + S::before {
  background-color: #00c853;
}


Cor em vermelho quando a entrada NÃO é selecionada



/*  input */
.new-input > INPUT[name="chb1"]:not(:checked) + S,
.new-input > INPUT#rb1:not(:checked) + S {
  color: #d50000;
}
/*  text */
.new-input > INPUT[name="chb1"]:not(:checked) ~ SPAN,
.new-input > INPUT#rb1:not(:checked) ~ SPAN {
  color: #d50000;
}
/*   */
.new-input > INPUT[name="chb1"]:not(:checked) ~ *,
.new-input > INPUT#rb1:not(:checked) ~ * {
  color: #d50000;
}


A lógica está clara? Você pode continuar a fazer designs mais complexos.



Por exemplo, se a entrada não for selecionada, o texto deve ser vermelho e em negrito, e se o elemento de entrada interno e o texto forem selecionados, devem ser verdes. Elementar!



/* ,    */
.new-input > INPUT[name="chb1"]:not(:checked) ~ SPAN,
.new-input > INPUT#rb1:not(:checked) ~ SPAN {
  color: #d50000;
  font-weight: bold;
}
/*   input,   */ 
.new-input > INPUT[name="chb1"]:checked + S::before,
.new-input > INPUT#rb1:checked + S::before {
  background-color: #00c853;
}
/* ,   */ 
.new-input > INPUT[name="chb1"]:checked ~ SPAN,
.new-input > INPUT#rb1:checked ~ SPAN {
  color: #00c853;
}


E, por exemplo, você precisa processar todo um grupo de entrada (10-15 peças). Para não escrever um monte de linhas, você pode encontrar seu pai comum (.parent_element) e encurtar a condição.



.parent_element > .new-input > INPUT:not(:checked) ~ SPAN {
  color: #d50000;
  font-weight: bold;
}
.parent_element > .new-input > INPUT:checked + S::before {
  background-color: #00c853;
}
.parent_element > .new-input > INPUT:checked ~ SPAN {
  color: #00c853;
}


Você pode ver tudo no exemplo final em codepen.io



Isso, ao que parece, e é isso. Resta apenas "arranhar as marcas de nascença" do perfeccionista - os problemas de alinhamento.



Alinha a entrada visual e o texto que a acompanha



Para começar, deixe-me lembrá-lo de coisas bem conhecidas sobre posicionamento de texto, formatação e muito mais. Tudo está sob controle.



Coisas bem conhecidas
, , css . .



1. font-size , . (baseline), «» . «» – g – «» . (cap height) – «» () . «» – – «» . , , . «» 75% . , font-size:16px, Arial 12px. , «» .



2. line-height . , font-size, , . , .



3. , S SPAN font-size line-height - . font-size:16px line-height:1.25. N1 S::before 1.25em, . N2 ( ) – S::before 0.75em, . font-size . , .



4. - «», , . . , , 50%. , , 150%. -, / – -! , -.



? , , input — , , , . !



O que acontece se o texto que acompanha em SPAN for exibido em duas ou três linhas? Obviamente, ele "caberá" na entrada. Não é bonito, precisa ser consertado



Um método antigo é: a tag S float: left e a tag SPAN display: block e overflow: hidden.



Isso criará uma coluna de texto. Presume-se que alguns deles terão uma margem adequada, o que dará um salto entre eles. Bem, também há hemorróidas adicionadas com o término da flutuação após o SPAN. Vamos seguir o caminho moderno - use o flexbox. Ele está completamente deslocado aqui.



.new-input {
  display: flex;
  flex-direction: row;
  align-items: start;
}
.new-input > S {
  margin-right: 4px;
  flex: 0 0 auto;
}
.new-input > SPAN {
  flex: 0 1 auto;
}


Neste caso, a tag LABEL (que é .new-input) será flex, S e SPAN serão blocos, colocados no topo do LABEL. O texto em SPAN terá várias linhas, se necessário. Por causa disso, a entrada visual foi descrita em S :: antes. Independentemente da altura, o SPAN S :: antes será alinhado com a primeira linha do SPAN. Alternativamente, você poderia ter especificado os itens de alinhamento: centro - então com um SPAN de uma linha, a entrada visual estaria no topo e com duas linhas - no meio e com três linhas - na segunda linha. No exemplo final, você pode mudar a localização da entrada.



Isso é tudo



Espero que tenha sido interessante e útil para alguém. Por favor, não me repreenda muito - esta é minha primeira experiência no Habr.



O exemplo # 1 é apenas uma demonstração da interação entre a mudança de entrada e um elemento vizinho.



Exemplo N 2 - visualização da entrada usando css, como base da solução.



O exemplo final é tudo descrito em conjunto.



Sobre uma implementação específica



Havia formulários extensos, onde os blocos de campo que podiam ser editados por usuários específicos eram destacados com um fundo esmaecido, e o restante da entrada tinha a propriedade desabilitada e servia apenas para informação. Portanto, o estilo ".new-input> INPUT: disabled + S :: before" não foi aplicado.



UPD



Em resposta aos comentários Exemplo N 3 .

Há suporte chave e foco para informações ocultas no trabalho.



All Articles