• Jobs
  • About Us
  • Jobs
    • Home
    • Jobs
    • Courses and challenges
  • Businesses
    • Home
    • Post vacancy
    • Our process
    • Pricing
    • Assessments
    • Hire tech talent
    • Blog
    • Sales
    • Salary Calculator

0

422
Views
Mantenga los caracteres colgantes visibles a pesar de `line-height: 1` y `overflow: hidden`

Objetivo

ingrese la descripción de la imagen aquí

 <div class="Card"> <div class="Card-FullNameLabel">Gregg Sims</div> <div class="Card-OrganizationNameLabel">Compubotics</div> </div>
  1. El .Card-FullNameLabel tiene font-size: 16px y line-height: 1 .
  2. El .Card-OrganizationNameLabel tiene font-size: 12px y line-height: 1 .
  3. El espacio vertical entre .Card-FullNameLabel y .Card-OrganizationNameLabel debe ser exactamente 6px .
  4. La siguiente regla CSS debe funcionar y NO debe cambiarse.
 .Card-FullNameLabel + .Card-OrganizationNameLabel { margin-top: 6px; }
  1. Tanto .Card-FullNameLabel como .Card-OrganizationNameLabel deben tener tolerancia de desbordamiento (por ejemplo, si este contenido será algo así como ÀÇĤjgpfhjklbĜiEstosTreMalfaci , etc., no debe sobresalir del padre).
  2. Todas las letras deben ser completamente visibles a pesar line-height: 1 .
  3. La aritmética mental ( números mágicos y/o compensaciones codificadas y otros valores que deben calcularse previamente) en el código CSS no está permitida.

Qué está bien hacer: usar la funcionalidad del preprocesador Pug para marcado y los preprocesadores CSS para estilos.

🌎 El violín inicial no cumple con la condición número 5 : actualmente la tarjeta no es tolerante al desbordamiento.

ingrese la descripción de la imagen aquí

Acerca line-height: 1 , la mala práctica

Me han dicho repetidamente que debo establecer line-height en un valor superior a 1 .

Se vuelve obvio que establecer line-height: 1 es una mala práctica. Les recuerdo que los valores sin unidades son relativos al tamaño de fuente, no al área de contenido, y tratar con un área virtual más pequeña que el área de contenido es el origen de muchos de nuestros problemas.

CSS de inmersión profunda: métricas de fuente, altura de línea y alineación vertical

Bueno, no voy a discutir sobre eso. Todo lo que quiero es la solución de trabajo para alcanzar mi objetivo (descrito anteriormente). Su uso es mi responsabilidad y no recomendaré esta solución si acepta que line-height debe ser superior a 1 .

Pero, ¿por qué no quiero aumentar la line-height manera tan persistente?

Razón 1: La definición precisa del espacio vertical entre dos elementos será demasiado complicada

La regla .Card-FullNameLabel + .Card-OrganizationNameLabel { margin-top: 6px; } es claro, intuitivo y expresa las pautas (representadas en la imagen de arriba) por CSS. "La .Card-OrganizationNameLabel debe retirarse de .Card-FullNameLabel en 6 píxeles", y nada más.

Pero, ¿qué sucede si necesitamos definir el mismo espacio vertical entre .Card-FullNameLabel y .Card-OrganizationNameLabel cuando la altura de la línea es mayor que 1 (o tienen los rellenos superior e inferior)? El valor del margin-top (visualizado por un área rosa no superpuesta en la imagen a continuación) de .Card-FullNameLabel + .Card-OrganizationNameLabel ahora será la diferencia de:

  1. El rango deseado (6px)
  2. El espacio vertical adicional debajo .Card-FullNameLabel (designado como l_b )
  3. El espacio vertical adicional arriba .Card-OrganizationNameLabel (designado como l_a )

ingrese la descripción de la imagen aquí

Como dije anteriormente, la aritmética mental no está permitida porque devalúa la programación (capacidades de los preprocesadores CSS en el caso de CSS) y tiene un impacto en la flexibilidad/mantenibilidad (si cambiamos la line-height o font-size o el espacio vertical deseado entre etiquetas, todo necesita ser re-computado mentalmente).

Aunque las variables del preprocesador (hoy disponible en CSS nativo) pueden solucionar este problema, será demasiado complicado mantenerlo. Para calcular el rosa rojo que no se cruza en la imagen de arriba, necesitamos:

  1. Variablelizar el font-size de .Card-FullNameLabel
  2. Variablelizar la line-height de .Card-FullNameLabel
  3. Calcule el espacio adicional debajo .Card-FullNameLabel .
  4. Variablelizar el font-size de .Card-OrganizationNameLabel
  5. Variablelizar la line-height de .Card-OrganizationNameLabel
  6. Calcule el espacio adicional debajo .Card-OrganizationNameLabel
  7. Variablelice el rango deseado entre .Card-FullNameLabel y .Card-OrganizationNameLabel (6 píxeles en este ejemplo).

Después de esto, finalmente podemos calcular el margin-top para la regla .Card-FullNameLabel + .Card-OrganizationNameLabel . ¡Y lo mismo para cada par de elementos como .Card-FullNameLabel y .Card-OrganizationNameLabel ! Tecnología demasiado pobre para el desarrollo web en la década de 2020.

Razón 2: No requiere para cada idioma

En el siguiente ejemplo, los símbolos japoneses se ajustan perfectamente a la línea con line-height: 1 (16 px):

ingrese la descripción de la imagen aquí

Supongo que lo mismo será para el chino, el coreano y muchos otros idiomas con caracteres no latinos.

Pero : en el pequeño porcentaje de casos, allí los símbolos extranjeros podrían estar mezclados:

ingrese la descripción de la imagen aquí

Si para hablar de alta calidad, este caso debe ser compatible.

No quiero aumentar la altura de la línea solo por esta excepción. Está bien que el espacio vertical entre las líneas en realidad no sea de 6px : las colas de j o À tienen poco peso y no romperán la estética geométrica.

Mis esfuerzos

Intento 1: uso de :before y :after

SASS-mixin TextTruncation acepta el parámetro $extraSpace que agrega rellenos superior e inferior. Los pseudo elementos :before y :after compensan estos rellenos con márgenes negativos.

 @mixin TextTruncation($extraSpace, $displayEllipsis: false) { overflow: hidden; white-space: nowrap; @if ($displayEllipsis) { text-overflow: ellipsis; } @else { text-overflow: clip; } padding-top: $extraSpace; padding-bottom: $extraSpace; &:before, &:after { content: ""; display: block; } &:before { margin-top: -$extraSpace; } &:after { margin-bottom: -$extraSpace; } } body { padding: 12px; } * { line-height: 1; font-family: Arial, sans-serif; } .Card { display: flex; flex-direction: column; align-items: center; width: 240px; height: 320px; padding: 6px 12px 12px; background: white; box-shadow: 0 0 3px rgba(0, 0, 0, 0.5); } .Card-FullNameLabel { max-width: 100%; /* Required when the flex parent has `align-items: center` */ @include TextTruncation($extraSpace: 2px, $displayEllipsis: true); font-size: 16px; color: #707070; } .Card-OrganizationNameLabel { max-width: 100%; /* Required when the flex parent has `align-items: center` */ @include TextTruncation($extraSpace: 2px, $displayEllipsis: true); font-size: 12px; color: #A2A2A2; } .Card-FullNameLabel + .Card-OrganizationNameLabel { margin-top: 6px; }

Desafortunadamente, no funciona: el efecto es el mismo que si no se hubieran definido márgenes ni rellenos:

ingrese la descripción de la imagen aquí

🌎 CodePen

Intento 2: uso del envoltorio

Si la combinación de overflow-x: hidden y overflow-y: visible funciona, era la solución. Pero no funciona y este problema se ha considerado en la pregunta CSS overflow-x: visible; y desbordamiento-y: oculto; causando problema de barra de desplazamiento .

Quiero ávido de los envoltorios como sea posible, pero aquí parece que el envoltorio será el último recurso. Para evitar escribir dos etiquetas cada vez, creé el mixin Pug:

 mixin SingleLineLabel span.SingleLineLabel&attributes(attributes) span.SingleLineLabel-Text block

Bueno, SingleLineLabel ahora es un componente. Además del mixin Pug, se requiere definir los estilos básicos y el mixin SASS permite personalizar la etiqueta individualmente:

 // Constant styles .SingleLineLabel { overflow-y: visible; &:before, &:after { content: ""; display: block; } &-Text { display: block; overflow-x: hidden; white-space: nowrap; } } // Variable styles @mixin SingleLineLabel($truncatedVerticalSpaceCompensation, $displayEllipsis: false) { &:before { margin-top: -$truncatedVerticalSpaceCompensation } &:after { margin-bottom: -$truncatedVerticalSpaceCompensation } .SingleLineLabel-Text { padding-top: $truncatedVerticalSpaceCompensation; padding-bottom: $truncatedVerticalSpaceCompensation; @if ($displayEllipsis) { text-overflow: ellipsis; } @else { text-overflow: clip; } } }

Ahora podemos aplicarlo:

 .Card-FullNameLabel { max-width: 100%; /* Required when the flex parent has `align-items: center` */ @include SingleLineLabel($truncatedVerticalSpaceCompensation: 1px, $displayEllipsis: true); font-size: 16px; color: #707070; } .Card-OrganizationNameLabel { max-width: 100%; /* Required when the flex parent has `align-items: center` */ @include SingleLineLabel($truncatedVerticalSpaceCompensation: 2px, $displayEllipsis: true); font-size: 12px; color: #A2A2A2; } .Card-FullNameLabel + .Card-OrganizationNameLabel { margin-top: 6px; }

Parece que se ha alcanzado el objetivo:

ingrese la descripción de la imagen aquí

🌎 CodePen

Desafortunadamente, tiene el error de que la regularidad de ocurrencia no está clara. A veces aparece la pequeña barra de desplazamiento vertical.

ingrese la descripción de la imagen aquí

Realmente no sé cómo reproducirlo, pero en el experimento pasado ocurrió, por ejemplo, cambiar el navegador al modo de simulación de dispositivo mediante herramientas de desarrollo y luego salir de este modo. Lo más probable es que no obtenga el mismo efecto si repite el mismo experimento en el violín.

Finalmente

La solución basada en sus excelentes respuestas se incluirá en la creciente biblioteca @yamato-daiwa/frontend .

Si tiene la lista completa de los símbolos problemáticos como g , p , À , Ĥ , etc., compártala. La usaré para las pruebas y también la agregaré a la futura funcionalidad pug para la prueba de tolerancia al desbordamiento.

about 4 years ago · Santiago Trujillo
1 answers
Answer question

0

Sé que usted declaró explícitamente que necesitaba mantener line-height: 1 y margin-top: 6px , pero como se identificó con el problema de CSS de desbordamiento documentado , está atascado con sus restricciones actuales.

Si es posible ser flexible con respecto a esas restricciones, tengo una solución que es visualmente idéntica a la que buscabas originalmente.

Estado original

Comencé con su violín inicial y agregué CSS de truncamiento de puntos suspensivos y texto problemático en el html.

 .Card-FullNameLabel, .Card-OrganizationNameLabel { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

El resultado es este estado que llamo "Original" ya que no modifica los valores line-height y margin . Tenga en cuenta que agregué un overflow: hidden en lugar de la mezcla problemática de las reglas de overflow-x y overflow-y .

Solución propuesta

Propongo los siguientes cambios de CSS. Esto aumenta line-height a 1.5 , lo que permite que todos los ascendentes y descendentes de la fuente sean visibles. Luego agregué márgenes de compensación negativos para compensar:

 .Card-FullNameLabel, .Card-OrganizationNameLabel { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; /* Shows all ascenders and descenders */ line-height: 1.5; } .Card-FullNameLabel { font-size: 16px; color: #707070; /* Compensates for line-height */ margin: -4px 0; } .Card-OrganizationNameLabel { font-size: 12px; color: #A2A2A2; /* Compensates for line-height */ margin: -3px 0; } .Card-FullNameLabel + .Card-OrganizationNameLabel { /* 6px visually (minus 3px) */ margin-top: 3px; }

El resultado se puede ver en acción aquí , al que me refiero como "Solución propuesta". He confirmado que los resultados son consistentes en las últimas versiones de escritorio de Chrome, Firefox y Safari en MacOS y Mobile Safari en iOS.

Comparación

Hice una animación simple a partir de capturas de pantalla de "antes" y "después" que demuestran que el resultado es visualmente idéntico, excepto que la solución propuesta no corta los ascendentes y descendentes de la fuente.

Tenga en cuenta que puede hacer clic en la animación para ver una versión de tamaño completo con una precisión de píxel de 1:1.

ingrese la descripción de la imagen aquí

Hice algunas pruebas adicionales con lo que llamo "elementos intermedios" para demostrar que la solución propuesta se comportaría igual que la original, incluso si hubiera elementos intermedios.

ingrese la descripción de la imagen aquí


Actualización: Automatización

Como quedó claro en los comentarios, uno de los requisitos es que no haya números "codificados" o "mágicos" en el CSS. Entonces, si bien la solución anterior funciona, requiere aritmética manual antes de tiempo.

Aquí hay un Codepen actualizado que puede producir automáticamente un CSS similar al que se mostró arriba mediante el uso de alguna lógica SCSS que calculará las compensaciones en función de estos valores de entrada:

Variable Valor actual
$globalLineHeight 1
$minLineHeight 1.5
$fullNameFontSize 16px
$fullNameLineHeight $globalLineHeight
$orgNameFontSize 12px
$orgNameLineHeight $globalLineHeight
$orgNameMarginTop 6px

Para fines de demostración, agregué un poco de código adicional que mostrará un efecto de desplazamiento "antes" y "después" para que pueda ver cómo se comporta la lógica SCSS en comparación con el CSS original. Como se indica tanto en HTML como en CSS, puede eliminar todo lo que esté debajo de las líneas que comienzan con #DELETE-ME .

about 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Our process Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!