soy Kseso y esto EsCSS

Centrar pequeños elementos menguantes: una de cal y otra de arena

Dos casos prácticos de centrado o alineación de pequeños elementos donde un solo píxel marca la diferencia.

Centrar pequeños elementos menguantes: una de cal y otra de arena

·Por Kseso ✎ 0
Centrar los pequeños elementos menguantes

En este último cambio de apariencia del blog (a la TweetDeck style) me encontré con dos casos concretos de centrado de pequeños elementos.

El primero se corresponde con el avatar y nombre del usuario en la columna de "Últimos Comentarios" y con el cuadro de color y título del artículo en el resto de columnas. El segundo con el "1" con fondo rojo sobre el sobre de la barra de iconos. Ambos, como te digo, en el índex del blog.

Vamos con el primero. En él a priori se desconoce la longitud del título que puede ir de ser una sola palabra a rellenar varias líneas sobrepasando incluso la altura del avatar o del recuadro de color. Imagen (o recuadro) cuyo alto en principio puede puede variar desde unos pocos píxeles hasta un máximo de 50px: max-width: 50px

Porque a diferencia de temas anteriores en los que sustituía con CSS la falta de avatar o avatar genérico de los usuarios, en este decidí mostrar el servido por Blogger. Aquí el cómo Reemplazar imágenes en el Html con Css

Este caso que parece complejo ya que la longitud texto como el tamaño de la imagen son desconocidas a priori, hoy por hoy es uno de los centrados* más sencillos de lograr.

*: hablo de centrado pero realmente es una alineación en la vertical de dos elementos

Todo está en esta última matización: dos elementos y usar un par de declaraciones del grupo del flexbox.

Lo de los dos elementos es un detalle vital. Recuerda que para que un contenido se convierta en un ítem del flexbox ha de ser eso, un elemento. O lo que es lo mismo, estar contenido entre alguna etiqueta.

Un texto sin marcado HTML hijo directo del flexbox no se convierte en ítem del flexbox.

Así que el primer paso es ese: tener 2 elementos HTML. Me centro en el caso de la columna de comentarios. El de los artículos básicamente es el miso. Sólo que la imagen se ve sustituida por el pseudoelemento ::before. Pero a efectos es lo mismo.

<h3> <img src='ruta_avatar_usuario.ext' alt='' /> <span>Nombre del Comentarista</span> </h3>

Todo lo que se necesita para que la imagen y el texto se alineen al centro entre ellos, con independencia de cuál sea el mayor (más alto) son este par de declaraciones CSS:

h3 { display: flex; align-items: center; }

El resto de declaraciones, como anchura del h3, tamaño del texto y su altura de línea... étc, no influyen. Si el texto es menor (en altura que la imagen) se coloca alineado con el centro de ella y si es la imagen la de menor altura hace lo mismo.

Doble centrado pequeños signos textuales

Centrar los pequeños elementos textuales menguantes

De todos los casos posibles de centrado quizás este sea el más complejo. El lograr posicionar en una pequeña caja un sólo carácter textual (letra o número da lo mismo). Tan difícil que en la mayoría de ocasiones es imposible lograrlo y que visualmente lo aparente.

Y si lo anterior no fuese suficiente, los valores para un signo posiblemente haya que retocarlos para otro.

Así que no hay una fórmula mágica y universal para este doble centrado.

Cuando se trata de centrar vertical y horizontalmente un sólo carácter textual en una pequeña caja, a diferencia del caso anterior, todo lo que puedas imagina y más influye en su posición. Entre otras:

  • Tamaño de la tipografía, altura de línea y alineación vertical
  • Características de la familia tipográfica elegida
  • Variante de la tipografía: normal, itálicas, negritas...
  • Carácter del que se trate: 'm' o 'M' o 'l' o...
  • Diferencia tamaños entre la caja contenedora y el símbolo

Recuerda que cada carácter textual se compone del grafo que se representa en pantalla y la caja anónima que genera. Y que las diferentes propiedades CSS que inciden en la colocación del texto lo hacen sobre la segunda: la caja. Otras, las menos, estéticas como text-shadow sí lo hacen sobre la representación visual o trazo.

Font-size, line-height, vertical-align

A las particularidades del interlineado CSS y cómo funciona le dediqué hace tiempo este artículo. Si lo recuerdas o lo visitas ahora verás que la línea utilizada para la alineación del texto no es el centro visual de cada carácter.

Como hay dos líneas de alineación, la línea base base inferior y la superior, y además la diferencia entre el tamaño del texto font-size y la altura de línea line-height influyen en dónde se ubican (por lo que se conoce como medio interlineado CSS) el uso de la propiedad vertical-align no sólo no ayuda si no que hasta es contraproducente utilizarla para estos menesteres.

Particularidades en cada familia tipográfica y text-align

No hay dos tipografías iguales. Desde el grosor del trazo (font-weight, pasando por la relación entre el M-width y X-height (para intentar compensarlo se definió la cuasi ignota font-size-adjust) y sin olvidarnos de las variantes por font-stretch actúan para hacer más interesante si cabe este caso de doble centrado.

Sólo en las familias monospace las cajas anónimas generadas por cada carácter tienen la misma anchura.

Y el uso de la alineación horizontal del texto, text-align, descártala también. A todo lo anterior añade que en espacio ocupado por cada carácter hay que sumarle el espacio entre caracteres o letter-spacing que es inseparable de cada caja anónima generada por cada letra.

Y si estabas pensando compensarlo con leter-spacing: 0; es buen momento para recordar que:

  • El valor normal depende del diseño de cada tipografía. Varía de unas a otras.
  • El valor declarado en letter-spacing se resta del valor normal.
  • Aunque admite valores negativos como no está uniformado el valor 'normal'... en cada familia y variante se requiere una cifra distinta.

Otro detalle que influye es el carácter concreto mostrado. Hay diferencias notables entre que sea el '1' o el '8' y entre que sea una una 'M' o una 'i', por ejemplo. También en la misma familia y variante, incluidas las monospace.

Diferencia tamaños entre la caja contenedora y el símbolo

Como estamos hablando de un caso concreto donde un solo píxel se nota, para terminar esta relación de condicionales hay que tener presente que la diferencia entre los valores finales y visuales del tamaño de la caja donde queremos lograr el centrado y el tamaño del signo representado no siempre va a ser un número par para poder distribuirla exáctamente entre ambos extremos (superior / inferior y derecha / izquierda).

Es muy probable que si la caja tenga una altura de 'H' y el espacio vertical del símbolo es 'h' la diferencia sea un valor impar: H - h = 2n +1

Caso práctico doble centrado de pequeños en pequeños

Por todo lo anterior yo al menos desconozco una fórmula universal para lograr el doble centrado de un sólo signo textual en una pequeña caja contenedora.

Para cada caso particular se han de usar multitud de números mágicos para lograr centrar el carácter en su caja contenedora y que visualmente también lo parezca.

En el caso de excusa o base de este caso (imagen previa del 1 sobre fondo rojo del index del blog) estas son las declaraciones que a mi me resultan efectivas:

[for='b_e']::before { content: '1'; /*Genera el texto*/ /* Estética caja contenedora */ background: #f00; color: #fff; border-radius: 50%; border: 2px solid #fff; /* Presentación de esta caja */ position: absolute; top: -5px; right: -10px; width: 1.5rem; height: 1.5rem; overflow: hidden; z-index: 1; /* Texto centrado en la caja */ font-size: 1rem; font-weight: 900; line-height: 4px; padding-top: 8px; text-indent: 5.5px; }

Unos pequeños apuntes rápidos a esta regla para los menos versados en CSS:

  • El primer grupo de declaraciones establecemos la apariencia visual de la caja contenedora. Su finalidad es estética.
  • Con el segundo grupo definimos el tamaño y lugar (respecto a su caja padre que lógicamente está como position ≠ static) donde queremos que se visualice).
  • El tercer grupo de declaraciones es el que nos permite ubicar el carácter textual píxel a píxel en su caja contenedora:
    • font-size: 1rem;: Habrá que tener cuidado que el tamaño del texto no sea mayor que la caja que lo contiene.
    • font-weight: 900;: Antes de comenzar a mover el símbolo declara las particularidades del texto. Te evitarás tener que retocar los siguientes valores.
    • line-height: 4px;: He observado que una altura de línea con valor bajo ayuda. Pero si la hacemos excesivamente pequeña lo complica.
    • padding-top: 8px;: La declaración anterior "sube" el texto respecto al centro de la caja, así que la recolocación en la vertical la hago mediante el espaciado superior. Recuerda que la propiedad padding no admite valores negativos.
    • text-indent: 5.5px; la alineación horizontal al centro también puedes lograrla con el espaciado izquierdo (padding-left).

Estoy seguro que si has leído esta última relación de propiedades y sus valores prestando atención te has quedado con el medio píxel de la última declaración: text-indent: 5.5px;. Máxime si recuerdas la de veces que he mencionado en el blog que 1px es 1px y por definición es indivisible.

Sigue siendo cierta la afirmación pero hoy en día ya menos. Porque no he mencionado otro factor a tener en cuenta: las carácterísticas técnicas de la pantalla y SO del aparato. Que también aportan su granito de arena a este juego.

Con la llegada de las pantallas de "alta definición", HiDPI o nºX resulta que sí, que ese medio píxel y el cómo lo interpreta o distribuye el SO y aparato en cuestión ayudan a mover ligéramente el texto, un poco más que los 5px y menos que 6px en el caso de estudio.

Nunca nadie dijo que las cosas pequeñas fuesen más fáciles que las grandes. Pero ya sabes, el diablo y la diversión en los pequeños detalles que son los que marcan la diferencia

Y si este no es tu caso, hay otros muchos tipos de centrado CSS resueltos en este blog.

avatar del Editor del blog

the obCSServer ᛯ Ramajero Argonauta, Enredique Amanuense de CSS.
#impoCSSible inside
Dicen que, en español, EsCss es el mejor blog de CSS. Posíblemente exageren.
@Kseso EsCss Kseso