Una vez más sobre la visualización de la casilla de verificación de tipos de entrada y radio. Para aquellos que han olvidado como

El tema es antiguo y, como resultó, ya se olvidó.



Recientemente tuve un trabajo corto en el desarrollo de especificaciones técnicas para la modernización de un proyecto de larga data. Y, en particular, el caso se refería al estilo del notorio <input type = "checkbox">. Resultó que el intérprete, un programador "de todos los oficios" ni siquiera entendía que le estaba explicando con palabras cómo hacerlo. Tuve que hacer ejemplos y, como resultado, apareció este texto.



Permítame recordarle que ahora la casilla de verificación y la casilla de radio se representan de manera diferente en diferentes sitios. Sucede que una entrada sin marcar no se puede discernir de inmediato, es tan "bellamente diseñada", y en las últimas versiones de Chrome, las casillas de verificación seleccionadas se han convertido en un color cian vil.



Entonces la situación



Hay tres empresas que utilizan un determinado producto de software relacionado con pedidos, contabilidad, almacén, etc. Trabajan con clientes, socios, ejecutores, etc.



Los comercializadores y anunciantes también lo utilizan. Lo que hace este sistema, no importa lo que diga, no importa.



Y es importante que el sitio de este producto tenga muchas páginas con formularios, en las que hay muchas casillas de verificación de entrada y radio.



Quejas de los empleados



Director : En la pantalla grande, los "kryzhiki" son difíciles de ver y no se notan.

Contador jefe : En mi computadora, el "kryzhiki" se ve así, en los empleados se ve diferente, en casa también es diferente, pero en la tableta es completamente diferente.

Comercializador : ¿Es posible que algunas posiciones no seleccionadas sean rojas y otras seleccionadas sean verdes?

Etc.



Entonces la tarea



  1. Arregle la apariencia de la casilla de verificación y la casilla de radio con costos mínimos y cambios mínimos.
  2. Realice un estilo de casilla de verificación y casilla de radio para diferentes usuarios. Importante: este es un sitio cerrado, hay "todos los nuestros", no se necesita "belleza", pero se necesita eficiencia de percepción.


Lo que no esta permitido



1. No se debe tocar el lado del servidor.

2. No puede tocar archivos javascript, no puede insertar su propio javascript.

3. Los archivos CSS no se pueden tocar.



Que esta permitido



1. Edite plantillas html.

2. Cree un archivo de estilo para todos los usuarios.

4. Cree un archivo de estilo para un usuario o grupo de usuarios específico.

Y lo que hiciste, puedes mirar inmediatamente codepen.io , pero es mejor seguir leyendo.



El estudio preliminar mostró



1. Casi todos los <input type = "checkbox"> tienen un campo de nombre y los que no tienen una identificación.

2. Todos los <input type = "radio"> tienen un campo de nombre, algunos tienen una identificación.

3. En consecuencia, en CSS se puede acceder a la casilla de verificación tanto por ID como por nombre. A la radio, ya sea por identificación o por el número del hijo de los padres.



Fragmentos de código fuente:



/*  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>


Arreglemos el 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>


Todo es igual para <input type = "radio">, la clase LABEL es la misma.



¿Que hiciste exactamente?



  1. Cada entrada (popa de la opción 3) ha sido envuelta con una etiqueta LABEL con nuestra clase. La opción 3 acaba de agregar una clase.
  2. Inmediatamente después de la entrada, se insertó una etiqueta vacía S. Dado que la entrada en sí no será visible, esta etiqueta representará esta entrada.
  3. El texto que lo acompaña estaba envuelto con la etiqueta SPAN (excepto para la opción 4). Esta etiqueta será necesaria cuando decidamos sobre la alineación de la entrada visual en relación con este texto.
  4. Se agregó a la opción 4 otra clase para evitar esta alineación, ya que el texto que lo acompaña está en otra celda de la tabla. Estrictamente hablando, sería necesario hacer lo contrario: agregar una clase responsable de la alineación a las opciones 1-3. Pero, hay muchas más opciones 1-3 que la cuarta, y para no inflar el html se hace así.


Preguntas retóricas y respuestas retóricas
1. S? , S – . , input.



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



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


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



Algunas consideraciones preliminares y ajustes css con respecto al tamaño de la caja: border-box, normalización LABEL, selectores A + B, A ~ B y [attr] ,: comprobado ,: desactivado y :: antes de las pseudoclases. Quien no esté seguro de lo que sabe o quiera actualizar sus conocimientos, mira debajo del corte.



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



Entonces, comencemos a renderizar la entrada



Ejemplo N 1. El más simple: usamos caracteres alfabéticos. El

código html es el mismo y el CSS será así:



/* 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%;
}


La etiqueta S representará la entrada. Pero lo "dividiremos" por funcionalidad: la propia etiqueta S será responsable de la ubicación en LABEL y la alineación con respecto al siguiente SPAN.



Y el pseudoelemento S :: before se colocará dentro de la etiqueta S y actuará como entrada.



La línea s1 define qué carácter se colocará en S :: antes cuando no se seleccione la entrada. Básicamente, sería necesario escribir ".new-input> INPUT: not (: comprobado) + S :: before", pero algunos navegadores (por ejemplo, IE) pueden no ejecutar dicha construcción.

La cadena s2 especifica el carácter cuando se selecciona la entrada.

Las líneas s3 y s4 hacen lo mismo para la radio de entrada.

Cadena s5describe lo que sucede si la entrada está bloqueada; en este caso, la etiqueta S será medio transparente.

La línea s6 define la alineación, en este caso da relleno a izquierda y derecha (solo en este ejemplo). Además, elimina el tachado regular.

La línea s7 forma un cuadrado, s8 lo convierte en un círculo para la entrada de radio.



El ejemplo n. ° 1 se puede ver en codepen.io . Hay insumos nativos y nuevos. El primero se puede eliminar.



Un poco más de detalle sobre la visualización: bloque en línea, tamaño de fuente, altura de línea
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 «» ( , , .), «» . .





Pregunta:



¿Puedes usar caracteres especiales? Como estos:

□ ■ ▢ ▣ ○ ● ◎ ◉

Dales el tamaño correcto y listo . ¿No?



Respuesta:



puedes. Pero no es necesario. Porque habrá grandes hemorroides y bailes con panderetas en la asignación del tamaño deseado, alineación vertical, recorte, etc. Además, los diferentes navegadores funcionan de manera diferente con estos símbolos.

Fuimos por el otro lado. Aunque el ejemplo final contiene una implementación de esta idea.



Ejemplo N 2. "Dibujar" elementos de entrada usando el



código html css es el mismo, pero css será así:



/* 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;
}


La línea s1 define S :: before para representar la entrada. Este será un bloque en línea cuyo ancho y alto se establecen en 0.75em, que es aproximadamente el alto de la letra mayúscula y depende del tamaño de fuente del padre. Se establece un borde delgado con el color actual, acolchado interior, pequeño redondeo de esquinas. ¡Y lo mas importante! - propiedad background-clip: se establece el cuadro de contenido. Esta es una propiedad muy interesante: si se establece el color de fondo, solo pintará la parte del contenido y no afectará el relleno. Lo que necesitamos.



La línea s2 para una entrada de radio hace S :: antes de la ronda.

La línea s3 para la entrada resaltada establece S :: antes del color de fondo en el color actual. Es decir, "dibuja" un cuadrado o un círculo en su interior.

Líneas4 desbloquea la entrada, la línea s5 proporciona relleno a la izquierda y a la derecha.



Las ventajas de este método



  1. Todo es muy sencillo. Funciona en todos los navegadores. Incluso IE10 (en emulación del 11).
  2. Puedes colorear como quieras.
  3. Dado que S :: before es un bloque en línea, entonces se ubica en la parte inferior de la línea de base exactamente y no se sale de ella en ningún lado. Si es más alto que el texto, simplemente aumentará la altura de la línea y permanecerá en la línea de base.
  4. Dado que la visualización de entrada está dentro de una etiqueta S, se puede colocar y alinear fácilmente.
  5. Las dimensiones de S :: before en em permiten establecer su tamaño en relación con el tamaño del texto de la leyenda. Puede, por ejemplo, establecer límites para la altura y el ancho.


Desventajas de este método



Principalmente en tamaños em. El hecho es que puede surgir una situación en la que el ancho y la altura al calcular (de em a px) tendrán un valor fraccionario. Es posible que el redondeo no funcione correctamente en computadoras normales con una pantalla normal. Por ejemplo, las dimensiones de 12,8 px por 12,8 px en el mismo Mozila pueden convertirse en 13 px por 12 px. Entonces necesitas establecer tamaños fijos. Aunque en monitores y tarjetas de video modernos, computadoras portátiles, tabletas y teléfonos inteligentes, esto no sucede debido a que el punto (píxel) del navegador consta de varios píxeles de pantalla.



El ejemplo n. ° 2 se puede ver en codepen.io . Hay insumos nativos y nuevos. El primero se puede eliminar.

Entonces, la primera tarea, renderizar la entrada, está lista. Pasamos al "colorante" seleccionado.



Entrada para colorear



html por ejemplo:



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


Nos referiremos a una entrada del tipo checkbox por nombre, a radio por id.



Pintamos todo 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;
}


Recuerde la especificidad en CSS, estos estilos serán más específicos que los básicos y definitivamente funcionarán. ¿En qué se diferencian de los descritos anteriormente? Aquellos que se aplican solo a entradas seleccionadas, aquellos que tienen el nombre y la identificación especificados.



Todo está bien aquí, excepto que las entradas no seleccionadas no se verán muy bien: el borde azul delgado apenas se nota.



Coloréalo de verde cuando se selecciona la entrada



/*  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;
}


La primera opción, en mi opinión, no es muy buena: tanto el marco como el cuadrado / círculo interior serán verdes. Solo puedes colorearlo.



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


Color en rojo cuando la entrada NO está seleccionada



/*  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;
}


¿Está clara la lógica? Puede seguir haciendo diseños más complejos.



Por ejemplo, si no se selecciona la entrada, el texto debe estar en rojo y en negrita, y si se selecciona el elemento de entrada interno y el texto, debe ser verde. ¡Elemental!



/* ,    */
.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;
}


Y, por ejemplo, necesita procesar un grupo completo de entradas (10-15 piezas). Para no escribir un montón de líneas, puede encontrar su padre común (.parent_element) y acortar la condición.



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


Puedes ver todo en el ejemplo final en codepen.io



Eso parece, y eso es todo. Solo queda "rascar las marcas de nacimiento" del perfeccionista: los problemas de alineación.



Alinear la entrada visual y el texto que lo acompaña



Para empezar, permítame recordarle algunas cosas conocidas sobre la ubicación del texto, el formato y más. Todo está por debajo del corte.



Cosas comúnmente conocidas
, , 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 — , , , . !



¿Qué sucede si el texto que lo acompaña en SPAN se muestra en dos o tres líneas? Obviamente, "encajará" en la entrada. No es bonito, hay que arreglarlo.



Un método antiguo es este: la etiqueta S es float: left, y la etiqueta SPAN es display: block y overflow: hidden.



Esto creará una columna de texto. Se supone que algunos de ellos tendrán un margen adecuado, lo que dará un salto entre ellos. Bueno, también hay hemorroides agregadas con la terminación de flotación después de SPAN. Vamos a tomar la ruta moderna: usar flexbox. Está completamente fuera de lugar aquí.



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


En este caso, la etiqueta LABEL (que es .new-input) será flex, S y SPAN serán bloques, colocados en la parte superior de LABEL. El texto en SPAN estará en varias líneas si es necesario. Debido a esto, la entrada visual se describió en S :: antes. Independientemente de la altura, SPAN S :: before se alineará con la primera línea SPAN. Alternativamente, puede especificar align-items: center; luego, con un SPAN de una sola línea, la entrada visual estaría en la parte superior y con dos líneas, en el medio y con tres líneas, en la segunda línea. En el ejemplo final, puede cambiar la ubicación de la entrada.



Eso es todo



Espero que haya sido interesante y útil para alguien. Por favor, no me regañes mucho, esta es mi primera experiencia en Habr.



El ejemplo n. ° 1 es solo una demostración de la interacción entre el cambio de entrada y un elemento vecino.



Ejemplo N 2 : visualización de la entrada utilizando css como base de la solución.



El ejemplo final es todo lo que se describe en conjunto.



Sobre una implementación específica



Había formularios extensos, donde los bloques de campo que podían ser editados por usuarios específicos estaban resaltados con un fondo tenue, y el resto de la entrada tenía la propiedad deshabilitada y servía solo para información. Por lo tanto, no se aplicó el estilo ".new-input> INPUT: disabled + S :: before".



UPD



En respuesta a los comentarios Ejemplo N 3 .

Existe un soporte clave y focalizado para la entrada oculta en el trabajo.



All Articles