Escala de fuente según el tamaño del contenedor
Me está costando entender la escala de fuente.
Actualmente tengo un sitio web con un cuerpo font-size
del 100%. ¿100% de qué? Esto parece calcularse en 16 píxeles.
Tenía la impresión de que 100% se referiría de alguna manera al tamaño de la ventana del navegador, pero aparentemente no porque siempre son 16 píxeles, ya sea que la ventana se redimensione a un ancho móvil o a un escritorio de pantalla ancha en toda regla.
¿Cómo puedo hacer que el texto de mi sitio escale en relación con su contenedor? Intenté usar em
, pero esto tampoco escala.
Mi razonamiento es que cosas como mi menú se reducen cuando cambias el tamaño, por lo que necesito reducir, px
font-size
entre .menuItem
otros elementos, en relación con el ancho del contenedor. (Por ejemplo, en el menú de un escritorio grande, 22px
funciona perfectamente. Bajar al ancho de una tableta y 16px
es más apropiado).
Soy consciente de que puedo agregar puntos de interrupción, pero realmente quiero que el texto se escale y tenga puntos de interrupción adicionales; de lo contrario, terminaré con cientos de puntos de interrupción por cada disminución de 100 píxeles en el ancho para controlar el texto.
Las consultas de contenedores son ahora probablemente la mejor opción, según su caso de uso, y son compatibles con los principales navegadores. Vea el nivel de soporte aquí: https://caniuse.com/mdn-css_properties_container
Ahora es muy fácil de controlar:
.module h2 {
font-size: 1em;
container-name: sidebar
}
@container sidebar (min-width: 700px) {
.module h2 {
font-size: 2em;
}
}
Consulte el artículo de MDN sobre consultas de contenedores para obtener más detalles: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries
Más ejemplos de lo que puede lograr: https://css-tricks.com/a-few-times-container-size-queries-would-have-helped-me-out/
Antigua respuesta
Si el contenedor no es el cuerpo, CSS Tricks cubre todas sus opciones en Ajustar texto a un contenedor .
Si el contenedor es el cuerpo, lo que busca es longitudes de porcentaje de ventana gráfica :
Las longitudes porcentuales de la ventana gráfica son relativas al tamaño del bloque contenedor inicial . Cuando se cambia la altura o el ancho del bloque contenedor inicial, se escalan en consecuencia. Sin embargo, cuando el valor de desbordamiento en el elemento raíz es
auto
, se supone que no existe ninguna barra de desplazamiento.
Los valores son:
vw
(% del ancho de la ventana gráfica)vh
(% de la altura de la ventana gráfica)vi
(1% del tamaño de la ventana gráfica en la dirección del eje en línea del elemento raíz)vb
(1% del tamaño de la ventana gráfica en la dirección del eje del bloque del elemento raíz)vmin
(el menor devw
ovh
)vmax
(el más grande ovw
ovh
)
1 v* es igual al 1% del bloque contenedor inicial.
Usarlo se ve así:
p {
font-size: 4vw;
}
Como puede ver, cuando el ancho de la ventana gráfica aumenta, también lo hace font-size
, sin necesidad de utilizar consultas de medios.
Estos valores son una unidad de tamaño, al igual que px
o em
, por lo que también se pueden usar para dimensionar otros elementos, como el ancho, el margen o el relleno.
La compatibilidad con el navegador es bastante buena, pero probablemente necesitarás un respaldo, como por ejemplo:
p {
font-size: 16px;
font-size: 4vw;
}
Consulte las estadísticas de soporte: https://caniuse.com/viewport-units .
Además, consulte Trucos de CSS para obtener una visión más amplia: Tipografía del tamaño de una ventana gráfica.
Aquí hay un buen artículo sobre cómo establecer tamaños mínimos y máximos y ejercer un poco más de control sobre los tamaños: Control preciso sobre la tipografía responsiva
Y aquí hay un ejemplo de cómo configurar su tamaño calc()
para que el texto llene la ventana gráfica: https://codepen.io/CrocoDillon/pen/wvdrBY
Además, consulte este artículo, que utiliza una técnica denominada 'líder fundido' para ajustar también la altura de la línea: Líder fundido en CSS
Pero ¿qué pasa si el contenedor no es la ventana gráfica (cuerpo)?
Alex hace esta pregunta en un comentario en la respuesta de 2507rkt3 .
Ese hecho no significa que vw
no se pueda utilizar hasta cierto punto el tamaño de ese contenedor. Ahora bien, para ver alguna variación hay que asumir que el contenedor de alguna manera es de tamaño flexible. Ya sea mediante un porcentaje directo width
o mediante un 100% menos márgenes. El punto se vuelve "discutible" si el contenedor siempre está configurado, digamos, 200px
en ancho; luego simplemente configure un font-size
que funcione para ese ancho.
Ejemplo 1
Sin embargo, con un contenedor de ancho flexible, se debe tener en cuenta que de alguna manera el tamaño del contenedor todavía se está reduciendo fuera de la ventana gráfica . Como tal, se trata de ajustar una vw
configuración en función de esa diferencia de tamaño porcentual en la ventana gráfica, lo que significa tener en cuenta el tamaño de los contenedores principales. Tome este ejemplo :
div {
width: 50%;
border: 1px solid black;
margin: 20px;
font-size: 16px;
/* 100 = viewport width, as 1vw = 1/100th of that
So if the container is 50% of viewport (as here)
then factor that into how you want it to size.
Let's say you like 5vw if it were the whole width,
then for this container, size it at 2.5vw (5 * .5 [i.e. 50%])
*/
font-size: 2.5vw;
}
Suponiendo aquí que div
es hijo de body
, tiene 50%
ese 100%
ancho, que es el tamaño de la ventana gráfica en este caso básico. Básicamente, desea configurar un diseño vw
que le parezca bien. Como puede ver en mi comentario en el contenido CSS anterior, puede "pensar" matemáticamente con respecto al tamaño completo de la ventana gráfica, pero no es necesario que lo haga. El texto se "flexionará" con el contenedor porque el contenedor se flexionará con el cambio de tamaño de la ventana gráfica. A continuación se muestra un ejemplo de dos contenedores de diferentes tamaños .
Ejemplo 2
Puede ayudar a garantizar el tamaño de la ventana gráfica forzando el cálculo basado en eso. Considere este ejemplo :
html {width: 100%;} /* Force 'html' to be viewport width */
body {width: 150%; } /* Overflow the body */
div {
width: 50%;
border: 1px solid black;
margin: 20px;
font-size: 16px;
/* 100 = viewport width, as 1vw = 1/100th of that
Here, the body is 150% of viewport, but the container is 50%
of viewport, so both parents factor into how you want it to size.
Let's say you like 5vw if it were the whole width,
then for this container, size it at 3.75vw
(5 * 1.5 [i.e. 150%]) * .5 [i.e. 50%]
*/
font-size: 3.75vw;
}
El tamaño todavía se basa en la ventana gráfica, pero en esencia se configura en función del tamaño del contenedor.
¿Debería el tamaño del contenedor cambiar dinámicamente...?
Si el tamaño del elemento contenedor terminó cambiando dinámicamente su relación porcentual, ya sea a través @media
de puntos de interrupción o mediante JavaScript, entonces, cualquiera que fuera el "objetivo" base, sería necesario volver a calcularlo para mantener la misma "relación" para el tamaño del texto.
Tome el ejemplo n.° 1 anterior. Si se div
cambió al 25%
ancho mediante @media
JavaScript, al mismo tiempo, font-size
sería necesario ajustarlo en la consulta de medios o mediante JavaScript al nuevo cálculo de 5vw * .25 = 1.25
. Esto colocaría el tamaño del texto en el mismo tamaño que habría tenido si el "ancho" del 50%
contenedor original se hubiera reducido a la mitad del tamaño de la ventana gráfica, pero ahora se ha reducido debido a un cambio en su propio cálculo porcentual.
Un reto
Con la función CSScalc()
en uso, sería difícil realizar ajustes dinámicos, ya que esa función no funciona para font-size
sus propósitos en este momento. Por lo tanto, no podrá realizar un ajuste de CSS puro si su ancho cambia calc()
. Por supuesto, un ajuste menor del ancho de los márgenes puede no ser suficiente para justificar ningún cambio en font-size
, por lo que puede que no importe.
Solución con SVG:
.resizeme {
resize: both;
margin: 0;
padding: 0;
height: 75px;
width: 500px;
background-color: lightblue;
overflow: hidden;
}
<div class="resizeme">
<svg
width="100%"
height="100%"
viewBox="0 0 500 75"
preserveAspectRatio="xMinYMid meet"
style="background-color:green"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<text
x="0"
y="75"
font-size="75"
fill="black"
>█Resize This█</text>
</svg>
</div>
Solución con SVG y ajuste de texto usando foreignObject
:
.resizeme {
resize: both;
margin: 0;
padding: 0;
height: 200px;
width: 500px;
background-color: lightblue;
overflow: hidden;
}
<div class="resizeme">
<svg
width="100%"
height="100%"
viewBox="0 0 500 200"
preserveAspectRatio="xMinYMin meet"
>
<foreignObject width="100%" height="100%" xmlns="http://www.w3.org/1999/xhtml">
<div xmlns="http://www.w3.org/1999/xhtml" style="background-color:lightgreen;">
<h1>heading</h1>
<p>Resize the blue box.</p>
</div>
</foreignObject>
</svg>
</div>