Escala de fuente basada en el ancho del contenedor


1189

Me está costando entender cómo escalar las fuentes.

Actualmente tengo este sitio con un cuerpo font-sizedel 100%. ¿100% de qué sin embargo? Esto parece calcularse a 16 píxeles.

Tenía la impresión de que el 100% de alguna manera se referiría al tamaño de la ventana del navegador, pero aparentemente no porque siempre es de 16 píxeles si la ventana se redimensiona a un ancho móvil o un escritorio de pantalla panorámica en toda regla.

¿Cómo puedo hacer que el texto en mi sitio se escale en relación con su contenedor? Intenté usarlo em, pero esto tampoco escala.

Mi razonamiento es que cosas como mi menú se aplastan cuando cambias el tamaño, por lo que necesito reducir el px font-sizede .menuItementre otros elementos en relación con el ancho del contenedor. (Por ejemplo, en el menú de un escritorio grande, 22pxfunciona perfectamente. Mover hacia abajo al ancho de la tableta y 16pxes más apropiado).

Soy consciente de que puedo agregar puntos de interrupción, pero realmente quiero que el texto se escale y que tenga puntos de interrupción adicionales, de lo contrario, terminaré con cientos de puntos de interrupción por cada 100 píxeles de disminución de ancho para controlar el texto.


34
font-size: 100%;significa el 100% del tamaño que tendría el texto (es decir, el que hereda de su padre). Por defecto eso es 16px. Entonces, si usó 50%, sería el tamaño de fuente: 8px
Andy

31
Lo que estás buscando se llama tipografía receptiva o de tamaño de ventana gráfica. css-tricks.com/viewport-sized-typography
gearsdigital

8
Dale un vistazo a FitText .
Patsy Issa

12
@Andy: En realidad, "por defecto" es lo que los usuarios tienen configurado el tamaño de texto de su navegador, lo que no necesariamente se resuelve en 16px.
ScottS

Respuestas:


1496

EDITAR: 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 está buscando son longitudes de porcentaje de ventana gráfica :

Las longitudes de porcentaje de 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 automático, se supone que las barras de desplazamiento no existen.

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 vista 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 de bloque del elemento raíz)
  • vmin(el menor de vwo vh)
  • vmax(el más grande vwo vh)

1 v * es igual al 1% del bloque contenedor inicial.

Usarlo se ve así:

p {
    font-size: 4vw;
}

Como puede ver, cuando aumenta el ancho de la ventana gráfica, también lo hace font-size, sin necesidad de usar consultas de medios.

Estos valores son una unidad de tamaño, al igual que pxo em, por lo que también se pueden usar para cambiar el tamaño de otros elementos, como el ancho, el margen o el relleno.

La compatibilidad con el navegador es bastante buena, pero es probable que necesite un respaldo, como:

p {
    font-size: 16px;
    font-size: 4vw;
}

Consulte las estadísticas de soporte: http://caniuse.com/#feat=viewport-units .

Además, echa un vistazo a CSS-Tricks para una apariencia más amplia: Tipografía de tamaño de ventana gráfica

Aquí hay un buen artículo sobre cómo establecer tamaños mínimos / máximos y ejercer un poco más de control sobre los tamaños: control preciso sobre la tipografía receptiva

Y aquí hay un artículo sobre cómo configurar su tamaño usando calc () para que el texto llene la ventana gráfica: http://codepen.io/CrocoDillon/pen/fBJxu

Además, vea este artículo, que utiliza una técnica denominada 'guía fundida' para ajustar también la altura de la línea. Fundido líder en CSS


548
Pero, ¿qué pasa si el contenedor no es la ventana gráfica (cuerpo)?
Alex

12
@ Alex, ese es el territorio de JS. Pruebe la FitText.jsalternativa provista al final del artículo que @jbenjohnson suministró.
Robbert el

10
Aquí es donde entran las llamadas consultas de elementos. A diferencia de las consultas de medios, las consultas de elementos dimensionarían las cosas según su bloque contenedor, no la ventana gráfica, ¡lo que sería increíble! Pero desafortunadamente aún no existe. Sin embargo, existen algunos polyfills y pruebas de conceptos si está interesado: coding.smashingmagazine.com/2013/06/25/… y filamentgroup.com/lab/element_query_workarounds
jbenjohnson el

139
Bajado de categoría porque esto no responde la pregunta. Preguntó por el contenedor, no por la ventana. Caso de uso completamente diferente.
SongBox

66
"bloque contenedor inicial" se refiere al elemento raíz. Esta no es la respuesta correcta a la pregunta formulada.
Glifo

320

Pero, ¿qué pasa si el contenedor no es la ventana gráfica (cuerpo)?

Esta pregunta se hace en un comentario de Alex bajo la respuesta aceptada .

Ese hecho no significa vwque no se pueda utilizar hasta cierto punto para dimensionar ese contenedor. Ahora, para ver cualquier variación, uno debe asumir que el contenedor de alguna manera es flexible en tamaño. Ya sea a través de un porcentaje directo widtho por ser 100% menos márgenes. El punto se convierte en "discutible" si el contenedor siempre se establece en, digamos, 200pxancho, luego simplemente configure un font-sizeque funcione para ese ancho.

Ejemplo 1

Sin embargo, con un contenedor de ancho flexible, debe tenerse en cuenta que de alguna manera el contenedor todavía se está dimensionando fuera de la ventana gráfica . Como tal, se trata de ajustar una vwconfiguración basada en esa diferencia de tamaño porcentual a la ventana gráfica, lo que significa tener en cuenta el tamaño de los contenedores primarios. Toma 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 que aquí dives un hijo del body, es 50%de ese 100%ancho, que es el tamaño de la ventana gráfica en este caso básico. Básicamente, desea establecer un vwque se vea bien para usted. 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 va a "flexionar" con el contenedor porque el contenedor se está flexionando con el tamaño de la ventana gráfica. ACTUALIZACIÓN: aquí hay un ejemplo de dos contenedores de diferentes tamaños .

Ejemplo 2

Puede ayudar a garantizar el tamaño de la vista 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 vista, pero en esencia se configura en función del tamaño del contenedor.

El tamaño del contenedor debería cambiar dinámicamente ...

Si el tamaño del elemento contenedor terminó cambiando dinámicamente su relación porcentual, ya sea a través de @mediapuntos de interrupción o mediante JavaScript, entonces cualquiera que sea el "objetivo" base necesitaría un nuevo cálculo para mantener la misma "relación" para el tamaño del texto.

Tome el ejemplo # 1 arriba. Si divse cambió al 25%ancho por cualquiera de ellos @mediao por JavaScript, al mismo tiempo, font-sizesería necesario ajustar en la consulta de medios o por JavaScript al nuevo cálculo de 5vw * .25 = 1.25. Esto pondría el tamaño del texto al mismo tamaño que hubiera 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 de porcentaje.

Un reto

Con la calc()función CSS3 en uso, sería difícil de ajustar dinámicamente, ya que esa función no funciona para font-sizefines en este momento. Por lo tanto, no podría hacer un ajuste CSS 3 puro si su ancho está cambiando calc(). Por supuesto, un pequeño ajuste de ancho para los márgenes puede no ser suficiente para garantizar cualquier cambio font-size, por lo que puede no importar.


(Hay un error de Chrome con longitudes de porcentaje de ventana gráfica y redimensionando la ventana: code.google.com/p/chromium/issues/detail?id=124331 )
thirtydot

@thirtydot: Eso es lamentable (pero es bueno tenerlo en cuenta, gracias). Espero que el error se resuelva pronto, pero parece que ha estado persistiendo por algún tiempo.
ScottS

20
Gran respuesta, sin embargo, no funcionará si el elemento contenedor tiene un ancho máximo.
Himmators

3
@KristofferNolgren: Eso se relaciona con dos puntos hechos en mi respuesta: (1) "suponiendo que el contenedor de alguna manera sea flexible en tamaño" (una vez que se alcanza el 'ancho máximo', ya no se flexiona, entonces hay un problema ) (2) Si uno puede determinar en qué punto se alcanzaría el 'ancho máximo', entonces, como señalé, podría establecer un @mediapunto de interrupción para cambiar la forma en que se dimensiona la fuente en ese punto (esencialmente dándole un tamaño fijo al llegar max-width) . Solo un pensamiento para trabajar con una max-widthsituación.
ScottS

¿Crees que puedes arrojar un violín cuando el elemento contenedor está cambiando dinámicamente a través de consultas de medios? No estoy seguro de entender.
J82

59

Solución con SVG:

<div style="width: 60px;">  
  <svg width="100%" height="100%" viewBox="0 -200 1000 300"
     xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <text font-size="300" fill="black">Text</text>
  </svg>
</div>

https://jsfiddle.net/qc8ht5eb/


Solución con SVG y ajuste de texto usando foreignObject:

<svg viewBox="0 0 100 100">
  <foreignObject width="100%" height="100%">
    <h1>heading</h1>

    lorem ipsum dolor sit amet
  </foreignObject>
</svg> 

https://jsfiddle.net/2rp1q0sy/


1
Esta idea se ve bien, al principio. Entonces te das cuenta de que no puedes controlar fácilmente la fuente en SVG dentro de <html>. La fuente es diferente en dispositivos móviles y de escritorio, lo que afecta el ancho final.
Stopi

@Stopi, ¿qué opinas sobre una solución iFrame? ejemplo
Dantio

10
Puede
diseñar

1
SVG se puede diseñar con css si el svg está en línea (no use una etiqueta img).

8
Esta es la mejor solución más predecible que se escala en función de un contenedor dinámico.
JoshuaDavid

35

En uno de mis proyectos, uso una "mezcla" entre vw y vh para ajustar el tamaño de fuente a mis necesidades, por ejemplo:

font-size: calc(3vw + 3vh);

Sé que esto no responde la pregunta del OP, pero tal vez pueda ser una solución para cualquier otra persona.


3
Puede que sea mejor usar vminy / o en su vmaxlugar.
sebastian_k

44
Chrome
Dev Tools lo

31

Solución de CSS puro con calc()unidades CSS y matemáticas

Esto no es precisamente lo que OP pregunta, pero puede alegrarle el día a alguien. Esta respuesta no es fácil de alimentar y necesita un poco de investigación sobre el desarrollo final.

Finalmente vine a obtener una solución de CSS puro para esto usando calc()diferentes unidades. Necesitará una comprensión matemática básica de las fórmulas para calcular su expresión calc().

Cuando resolví esto, tuve que obtener un encabezado receptivo de ancho de página completo con algunos rellenos para algunos padres en DOM. Usaré mis valores aquí, reemplácelos con los suyos.

A las matematicas

Necesitará:

  • Relación bien ajustada en alguna ventana gráfica. Usé 320 píxeles, por lo que obtuve 24 píxeles de alto y 224 píxeles de ancho, por lo que la relación es 9.333 ... o 28/3
  • El ancho del contenedor que tenía padding: 3emy el ancho completo, así que esto llegó a100wv - 2 * 3em

X es el ancho del contenedor, así que reemplácelo con su propia expresión o ajuste el valor para obtener texto de página completa. Res la proporción que tendrás Puede obtenerlo ajustando los valores en alguna ventana gráfica, inspeccionando el ancho y la altura del elemento y reemplazándolos con sus propios valores. Además, lo es width / heigth;)

x = 100vw - 2 * 3em = 100vw - 6em
r = 224px/24px = 9.333... = 28 / 3

y = x / r
  = (100vw - 6em) / (28 / 3)
  = (100vw - 6em) * 3 / 28
  = (300vw - 18em) / 28
  = (75vw - 4.5rem) / 7

Y bang! ¡Funcionó! escribí

font-size: calc((75vw - 4.5rem) / 7)

a mi encabezado y se ajustó muy bien en cada ventana gráfica.

pero como funciona?

Necesitamos algunas constantes aquí arriba. 100vwsignifica el ancho completo de la ventana gráfica, y mi objetivo era establecer un encabezado de ancho completo con algo de relleno.

El radio. Obtener un ancho y una altura en una ventana gráfica me dio una relación para jugar, y con la relación sé cuál debería ser la altura en el ancho de otra ventana gráfica. Calcularlos con la mano llevaría mucho tiempo y al menos tomaría mucho ancho de banda, por lo que no es una buena respuesta.

Conclusión

Me pregunto por qué nadie se ha dado cuenta de esto y algunas personas incluso dicen que sería imposible jugar con CSS. No me gusta usar JavaScript para ajustar elementos, por lo que no acepto las respuestas de JavaScript (y me olvido de jQuery) sin excavar más. En general, es bueno que esto se haya resuelto y este es un paso para las implementaciones de CSS puro en el diseño de sitios web.

Pido disculpas por cualquier convención inusual en mi texto, no soy hablante nativo en inglés y también soy bastante nuevo en escribir respuestas de desbordamiento de pila.

También debe tenerse en cuenta que tenemos barras de desplazamiento malvadas en algunos navegadores. Por ejemplo, al usar Firefox, noté que eso 100vwsignifica el ancho completo de la ventana gráfica, que se extiende debajo de la barra de desplazamiento (¡donde el contenido no se puede expandir!), Por lo que el texto de ancho completo debe ser marginado cuidadosamente y preferiblemente probado con muchos navegadores y dispositivos.


13
Esta solución solo funciona si (1) conoce la fuente, (2) la fuente está disponible en el dispositivo de un usuario y (3) el texto es siempre el mismo. Esto lo convierte en un caso de uso muy limitado.
Andrei Volgin

No entiendo qué pasa si mi contenedor está arreglado con, por ejemplo: 640 px y una relación de 16: 9. ¿Qué cálculos debo escribir?
pery mimon

1
El ancho de su contenedor xes de 640 px y relación r16: 9, entonces: x = 640px, r = 16 / 9, y = x / r = 640px / (16 / 9) = 360px
hegez

Nota: esto solo funciona si realmente tiene un texto con un tamaño de 16: 9, lo cual es una situación extraña. Quizás leer la respuesta por segunda vez pueda ayudar. Además, esto solo funciona para líneas simples.
hegez

Para ser sincero, no explicas "Relación bien ajustada en alguna ventana gráfica. Utilicé 320 píxeles, por lo tanto obtuve 24 píxeles de alto y 224 píxeles de ancho, por lo que la relación es 9.333 ... o 28/3" . Sugiero explicar la relación un poco más. ¿Qué representa la relación?
3limin4t0r

28

Hay una gran filosofía para este tema.

Lo más fácil sería darle un cierto tamaño de fuente al cuerpo (recomiendo 10), y luego todos los demás elementos tendrían su fuente en emo rem. Te daré un ejemplo para entender esas unidades. Emsiempre es relativo a su padre:

body{font-size: 10px;}
.menu{font-size: 2em;} /* That means 2*10 pixels  = 20 pixels */
.menu li{font-size: 1.5em;} /* That means 1.5*20 pixels = 30 pixels */

Rem siempre es relativo al cuerpo:

body{font-size: 10px;}
.menu{font-size: 2rem;} /* That means 2*10 pixels = 20 pixels */
.menu li{font-size: 1.5rem;} /* that means 1.5*10 pixels = 15 pixels */

Y luego puede crear una secuencia de comandos que modifique el tamaño de fuente en relación con el ancho de su contenedor. Pero esto no es lo que recomendaría. Porque en un contenedor de 900 píxeles de ancho, por ejemplo, tendría un pelemento con un tamaño de fuente de 12 píxeles, digamos. Y según su idea, se convertiría en un contenedor de 300 píxeles de ancho con un tamaño de fuente de 4 píxeles. Tiene que haber un límite inferior.

Otras soluciones serían con consultas de medios, para que pueda configurar la fuente para diferentes anchos.

Pero las soluciones que recomendaría es usar una biblioteca de JavaScript que lo ayude con eso. Y fittext.js que encontré hasta ahora.


66
La remunidad es relativa al elemento raíz, es decir, el htmlelemento, no el bodyelemento. El elemento raíz en el DOM es la htmletiqueta. developer.mozilla.org/en-US/docs/Web/CSS/length ... remsiempre es relativo a la htmletiqueta, que es el elemento raíz, no la etiqueta del cuerpo ... pero es una buena respuesta :)
Jonathan Marzullo

fittext.js hace el trabajo, ¡recomiendo esa solución!
Jacek Dziurdzikowski

FitText fue el ganador para mí. Intenté algunas alternativas, pero esta parecía la más simple y también se integró bien con Drupal / Backdrop CMS. github.com/davatron5000/FitText.js
Joel auxiliar

23

Aquí está la función:

document.body.setScaledFont = function(f) {
  var s = this.offsetWidth, fs = s * f;
  this.style.fontSize = fs + '%';
  return this
};

Luego convierta todos los tamaños de fuente del elemento hijo de sus documentos a em's o %.

Luego agregue algo como esto a su código para establecer el tamaño de fuente base.

document.body.setScaledFont(0.35);
window.onresize = function() {
    document.body.setScaledFont(0.35);
}

http://jsfiddle.net/0tpvccjt/


1
Hasta ahora, este es el mejor solution.Short y ligero
wp estudiante de

Malas prácticas y muy ineficientes
Jack Giffin

@tntrox Tan ineficiente como es hoy, fue mucho más ineficiente hace 4 años. Rechazo esta respuesta en lugar de alternativas mucho mejores. Sí, para el soporte de IE, uno necesitaría Javascript. Pero, uno no necesita Javascript que es tan terrible.
Jack Giffin

3
Supongo que mi ignorancia se muestra aquí. Pero ¿POR QUÉ es terrible lo anterior?

No creo que sea terrible. Recomiendo algunos cambios menores de formato para que sea más legible. Pondría cada var en una línea separada al menos. Puede que no sea necesario al return thisfinal de la función. Para el rendimiento, es posible que también desee eliminar el tamaño del onresize para que no se vuelva a dibujar al arrastrar. Es un código bastante simple, por lo que alguien podría basar su solución mejorada en él con poco esfuerzo.
Mnebuerquo

19

¡Hay una manera de hacer esto sin JavaScript!

Puede usar una imagen SVG en línea. Puede usar CSS en un SVG si está en línea. Debe recordar que usar este método significa que su imagen SVG responderá al tamaño de su contenedor.

Intente usar la siguiente solución ...

HTML

<div>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 360.96 358.98" >
      <text>SAVE $500</text>
  </svg>
</div>

CSS

div {
  width: 50%; /* Set your container width */
  height: 50%; /* Set your container height */

}

svg {
  width: 100%;
  height: auto;

}

text {
  transform: translate(40px, 202px);
  font-size: 62px;
  fill: #000;
}

Ejemplo: https://jsfiddle.net/k8L4xLLa/32/

¿Quieres algo más llamativo?

Las imágenes SVG también te permiten hacer cosas geniales con formas y basura. Mira este gran caso de uso para texto escalable ...

https://jsfiddle.net/k8L4xLLa/14/


44
Esta solución no es diferente a la aceptada con el vwdimensionamiento. Si cambia el texto, todo se saldrá del límite.
N69S

14

Esto puede no ser súper práctico, pero si desea que una fuente sea una función directa del padre, sin tener ningún JavaScript que escuche / bucles (intervalo) para leer el tamaño del div / página, hay una manera de hacerlo . Iframes

Cualquier cosa dentro del iframe considerará el tamaño del iframe como el tamaño de la ventana gráfica. Entonces, el truco es hacer un iframe cuyo ancho sea el ancho máximo que desea que sea su texto, y cuya altura sea igual a la altura máxima * de la relación de aspecto del texto en particular.

Dejando a un lado la limitación de que las unidades de ventana gráfica no pueden venir junto con las unidades primarias para el texto (como en el caso de que el% de tamaño se comporte como todos los demás), las unidades de ventana gráfica proporcionan una herramienta muy poderosa: poder obtener la dimensión mínima / máxima . No puedes hacer eso en ningún otro lado, no puedes decir ... haz que la altura de este div sea el ancho del padre * algo.

Dicho esto, el truco es usar vmin y establecer el tamaño del iframe para que [fracción] * altura total sea un buen tamaño de fuente cuando la altura es la dimensión límite, y [fracción] * ancho total cuando el ancho es el dimensión limitante Es por eso que la altura tiene que ser un producto del ancho y la relación de aspecto.

Para mi ejemplo particular, tienes

.main iframe{
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100%;
  height: calc(3.5 * 100%);
  background: rgba(0, 0, 0, 0);
  border-style: none;
  transform: translate3d(-50%, -50%, 0);
}

La pequeña molestia con este método es que debe configurar manualmente el CSS del iframe. Si adjunta todo el archivo CSS, eso ocuparía mucho ancho de banda para muchas áreas de texto. Entonces, lo que hago es adjuntar la regla que quiero directamente desde mi CSS.

var rule = document.styleSheets[1].rules[4];
var iDoc = document.querySelector('iframe').contentDocument;
iDoc.styleSheets[0].insertRule(rule.cssText);

Puede escribir una función pequeña que obtenga la regla CSS / todas las reglas CSS que afectarían el área de texto.

No puedo pensar en otra forma de hacerlo sin tener un poco de ciclismo / escuchar JavaScript. La solución real sería que los navegadores proporcionaran una forma de escalar texto en función del contenedor principal y también proporcionar la misma funcionalidad de tipo vmin / vmax.

JSFiddle: https://jsfiddle.net/0jr7rrgm/3/ (haga clic una vez para bloquear el cuadrado rojo en el mouse y haga clic nuevamente para liberarlo)

La mayor parte del JavaScript en el violín es solo mi función personalizada de hacer clic y arrastrar.


@quemeful No es así cuando traemos el atributo 'nuevo' y 'brillante' (redoble de tambores por favor ...) srcdoc: jsfiddle.net/wauzgob6/3
Jack Giffin

9

Usando vw, emy co. funciona con seguridad, pero en mi opinión siempre necesita un toque humano para afinar.

Aquí hay un script que acabo de escribir basado en la respuesta de @ tnt-rox que intenta automatizar el toque de ese humano:

$('#controller').click(function(){
    $('h2').each(function(){
        var
            $el = $(this),
            max = $el.get(0),
            el = null
        ;
        max =
            max
            ? max.offsetWidth
            : 320
        ;
        $el.css({
            'font-size': '1em',
            'display': 'inline',
        });
        el = $el.get(0);

        el.get_float = function(){
            var
                fs = 0
            ;
            if (this.style && this.style.fontSize) {
                fs = parseFloat(this.style.fontSize.replace(/([\d\.]+)em/g, '$1'));
            }
            return fs;
        };

        el.bigger = function(){
            this.style.fontSize = (this.get_float() + 0.1) + 'em';
        };

        while (el.offsetWidth < max) {
            el.bigger();
        }

        // Finishing touch.
        $el.css({
            'font-size': ((el.get_float() -0.1) +'em'),
            'line-height': 'normal',
            'display': '',
        });
    });  // end of (each)
});    // end of (font scaling test)
div {
  width: 50%;
  background-color: tomato;
  font-family: 'Arial';
}

h2 {
  white-space: nowrap;
}

h2:nth-child(2) {
  font-style: italic;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="button" id="controller" value="Apply" />
<div>
  <h2>Lorem ipsum dolor</h2>
  <h2>Test String</h2>
  <h2>Sweet Concatenation</h2>
  <h2>Font Scaling</h2>
</div>

Básicamente reduce el tamaño de la fuente 1emy luego comienza a aumentar en 0.1 hasta que alcanza el ancho máximo.

JSFiddle


1
+1 solo para alguien que reconoce que emsrequiere un toque humano y ritmo vertical no es una especie de hechicería.
serraosays

7

100% es relativo al tamaño de fuente base, que, si no lo ha configurado, sería el valor predeterminado de agente de usuario del navegador.

Para obtener el efecto que busca, usaría un fragmento de código JavaScript para ajustar el tamaño de fuente base en relación con las dimensiones de la ventana.


7

Dentro de su CSS, intente agregar esto en la parte inferior cambiando el ancho de 320 píxeles para donde su diseño comience a romperse:

    @media only screen and (max-width: 320px) {

        body { font-size: 1em; }

    }

Luego proporcione el tamaño de fuente en "px" o "em" como desee.


7

Mi propia solución, basada en jQuery, funciona aumentando gradualmente el tamaño de la fuente hasta que el contenedor obtenga un gran aumento de altura (lo que significa que tiene un salto de línea).

Es bastante simple, pero funciona bastante bien y es muy fácil de usar. No tiene que saber nada sobre la fuente que se está utilizando, el navegador se encarga de todo.

Puedes jugar con él en http://jsfiddle.net/tubededentifrice/u5y15d0L/2/

La magia sucede aquí:

var setMaxTextSize=function(jElement) {
    // Get and set the font size into data for reuse upon resize
    var fontSize=parseInt(jElement.data(quickFitFontSizeData)) || parseInt(jElement.css("font-size"));
    jElement.data(quickFitFontSizeData, fontSize);

    // Gradually increase font size until the element gets a big increase in height (i.e. line break)
    var i = 0;
    var previousHeight;
    do
    {
        previousHeight=jElement.height();
        jElement.css("font-size", "" + (++fontSize) + "px");
    }
    while(i++ < 300 && jElement.height()-previousHeight < fontSize/2)

    // Finally, go back before the increase in height and set the element as resized by adding quickFitSetClass
    fontSize -= 1;
    jElement.addClass(quickFitSetClass).css("font-size", "" + fontSize + "px");

    return fontSize;
};

1
Dado que este script se ejecutará en cada evento de cambio de tamaño y / o cambio de orientación, no recomiendo usar esto. En lugar de utilizar una solución basada en JavaScript, busque una solución basada en CSS como se indicó anteriormente.
Pilatus

1
Los cambios de tamaño y orientación son eventos "raros", no hay problemas de rendimiento aquí. Si lo prefiere, no se una a los eventos (si no cambian el tamaño de los contenedores, por ejemplo, para sitios web que no responden). Las soluciones CSS no funcionan en todos los casos sin tener que pensar en nada (como el ancho de la fuente más o menos) como lo hace esta solución.
Vincent

Envolví tu respuesta como una función jQuery. Recibe la altura máxima permitida, los tamaños de fuente mínimos y máximos. Ver jsfiddle.net/oriadam/qzsy760k
oriadam

6

Este componente web cambia el tamaño de la fuente para que el ancho del texto interno coincida con el ancho del contenedor. Mira la demo .

Puedes usarlo así:

<full-width-text>Lorem Ipsum</full-width-text>


6

He preparado una función de escala simple usando la transformación CSS en lugar del tamaño de fuente. Puede usarlo dentro de cualquier contenedor, no tiene que configurar consultas de medios, etc. :)

Entrada de blog: encabezado escalable CSS y JS de ancho completo

El código:

function scaleHeader() {
  var scalable = document.querySelectorAll('.scale--js');
  var margin = 10;
  for (var i = 0; i < scalable.length; i++) {
    var scalableContainer = scalable[i].parentNode;
    scalable[i].style.transform = 'scale(1)';
    var scalableContainerWidth = scalableContainer.offsetWidth - margin;
    var scalableWidth = scalable[i].offsetWidth;
    scalable[i].style.transform = 'scale(' + scalableContainerWidth / scalableWidth + ')';
    scalableContainer.style.height = scalable[i].getBoundingClientRect().height + 'px';
  }
}

Demostración de trabajo: https://codepen.io/maciejkorsan/pen/BWLryj


Creo que OP está buscando una solución CSS.
m02ph3u5

5

Usar variables CSS

Nadie ha mencionado aún las variables CSS, y este enfoque funcionó mejor para mí, así que:

Supongamos que tiene una columna en su página que tiene el 100% del ancho de la pantalla de un usuario móvil, pero tiene un max-widthtamaño de 800 px, por lo que en el escritorio hay espacio a cada lado de la columna. Pon esto en la parte superior de tu página:

<script> document.documentElement.style.setProperty('--column-width', Math.min(window.innerWidth, 800)+'px'); </script>

Y ahora puede usar esa variable (en lugar de la vwunidad integrada ) para establecer el tamaño de su fuente. P.ej

p {
  font-size: calc( var(--column-width) / 100 );
}

No es un enfoque CSS puro , pero está bastante cerca.


5

Pruebe http://simplefocus.com/flowtype/ . Esto es lo que uso para mis sitios, y ha funcionado perfectamente.


Los enlaces son volátiles. Por favor, explique la solución directamente en su respuesta. Además, no quiero hacer clic en algún enlace aleatorio con cualquier contenido.
lilalinux

5

Mi problema era similar, pero relacionado con el escalado de texto dentro de un encabezado. Probé Fit Font, pero necesitaba alternar el compresor para obtener algún resultado, ya que estaba resolviendo un problema ligeramente diferente, al igual que Text Flow.

Así que escribí mi propio pequeño complemento que reducía el tamaño de la fuente para que se ajustara al contenedor, suponiendo que sí, overflow: hiddeny de white-space: nowrapmodo que incluso si reducir la fuente al mínimo no permite mostrar el encabezado completo, simplemente corta lo que puede mostrar.

(function($) {

  // Reduces the size of text in the element to fit the parent.
  $.fn.reduceTextSize = function(options) {
    options = $.extend({
      minFontSize: 10
    }, options);

    function checkWidth(em) {
      var $em = $(em);
      var oldPosition = $em.css('position');
      $em.css('position', 'absolute');
      var width = $em.width();
      $em.css('position', oldPosition);
      return width;
    }

    return this.each(function(){
      var $this = $(this);
      var $parent = $this.parent();
      var prevFontSize;
      while (checkWidth($this) > $parent.width()) {
        var currentFontSize = parseInt($this.css('font-size').replace('px', ''));
        // Stop looping if min font size reached, or font size did not change last iteration.
        if (isNaN(currentFontSize) || currentFontSize <= options.minFontSize ||
            prevFontSize && prevFontSize == currentFontSize) {
          break;
        }
        prevFontSize = currentFontSize;
        $this.css('font-size', (currentFontSize - 1) + 'px');
      }
    });
  };
})(jQuery);

5

Artísticamente, si necesita ajustar dos o más líneas de texto dentro del mismo ancho, independientemente de su recuento de caracteres, entonces tiene buenas opciones.

Es mejor encontrar una solución dinámica para que cualquier texto que ingrese termine con una buena visualización.

Veamos cómo podemos acercarnos.

var els     = document.querySelectorAll(".divtext"),
refWidth    = els[0].clientWidth,
refFontSize = parseFloat(window.getComputedStyle(els[0],null)
                               .getPropertyValue("font-size"));

els.forEach((el,i) => el.style.fontSize = refFontSize * refWidth / els[i].clientWidth + "px")
#container {
  display: inline-block;
  background-color: black;
  padding: 0.6vw 1.2vw;
}
.divtext {
  display: table;
  color: white;
  font-family: impact;
  font-size: 4.5vw;
}
<div id="container">
  <div class="divtext">THIS IS JUST AN</div>
  <div class="divtext">EXAMPLE</div>
  <div class="divtext">TO SHOW YOU WHAT</div>
  <div class="divtext">YOU WANT</div>
</div>

Todo lo que hacemos es obtener el ancho ( els[0].clientWidth) y el tamaño de fuente ( parseFloat(window.getComputedStyle(els[0],null).getPropertyValue("font-size"))) de la primera línea como referencia y luego simplemente calcular el tamaño de fuente de las líneas subsiguientes en consecuencia.


4

Intente usar el complemento fitText , porque los tamaños de Viewport no son la solución de este problema.

Simplemente agregue la biblioteca:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

Y cambie el tamaño de fuente para corregir mediante la configuración del coeficiente de texto:

$("#text_div").fitText(0.8);

Puede establecer valores máximos y mínimos de texto:

$("#text_div").fitText(0.8, { minFontSize: '12px', maxFontSize: '36px' });

Esto es útil solo para texto de pantalla grande y no se recomienda para párrafos.
Shiv

3

Mira mi código. Hace el font size smallera fitlo que sea ​​que haya.

Pero creo que esto no conduce a una buena experiencia de usuario

var containerWidth = $("#ui-id-2").width();
var items = $(".quickSearchAutocomplete .ui-menu-item");
var fontSize = 16;

items.each(function(){
    // Displaying a value depends sometimes on your case. You may make it block or inline-table instead of inline-block or whatever value that make the div take overflow width.
    $(this).css({"whiteSpace": "nowrap", "display": "inline-block"});
    while ($(this).width() > containerWidth){
         console.log("$(this).width()" + $(this).width() + "containerWidth" + containerWidth)
         $(this).css("font-size", fontSize -= 0.5);
    }
});

Resultado


2

Como alternativa de JavaScript (o su única solución), puede usar mi complemento jQuery Scalem , que le permite escalar en relación con el elemento primario (contenedor) pasando la referenceopción.


2

En caso de que sea útil para alguien, la mayoría de las soluciones en este hilo fueron envolver texto en varias líneas, forma e.

Pero luego encontré esto, y funcionó:

https://github.com/chunksnbits/jquery-quickfit

Ejemplo de uso:

$('.someText').quickfit({max:50,tolerance:.4})


2

Siempre tenga su elemento con este atributo:

JavaScript: element.style.fontSize = "100%";

o

CSS: style = "font-size: 100%;"

Cuando va a pantalla completa, ya debe tener una variable de escala calculada (escala> 1 o escala = 1). Luego, en pantalla completa:

document.body.style.fontSize = (scale * 100) + "%";

Funciona bien con poco código.


2

Para texto dinámico, este complemento es bastante útil:

http://freqdec.github.io/slabText/

Simplemente agregue CSS:

.slabtexted .slabtext
{
    display: -moz-inline-box;
    display: inline-block;
    white-space: nowrap;
}
.slabtextinactive .slabtext
{
    display: inline;
    white-space: normal;
    font-size: 1em !important;
    letter-spacing: inherit !important;
    word-spacing: inherit !important;
    *letter-spacing: normal !important;
    *word-spacing: normal !important;
}
.slabtextdone .slabtext
{
    display: block;
}

Y el guión:

$('#mydiv').slabText();

2

Esto funcionó para mí:

Intento aproximar el tamaño de fuente en función del ancho / alto obtenido de la configuración de `font-size: 10px`. Básicamente, la idea es "si tengo 20 píxeles de ancho y 11 píxeles de alto con` font-size: 10px`, entonces, ¿cuál sería el tamaño máximo de fuente para matemática un contenedor de 50 píxeles de ancho y 30 píxeles de alto? "

La respuesta es un sistema de doble proporción:

{20: 10 = 50: X, 11: 10 = 30: Y} = {X = (10 * 50) / 20, Y = (10 * 30) / 11}

Ahora X es un tamaño de fuente que coincidirá con el ancho, e Y es un tamaño de fuente que coincidirá con la altura; tomar el menor valor

function getMaxFontSizeApprox(el){
    var fontSize = 10;
    var p = el.parentNode;

    var parent_h = p.offsetHeight ? p.offsetHeight : p.style.pixelHeight;
    if(!parent_h)
        parent_h = 0;

    var parent_w = p.offsetHeight ? p.offsetWidth : p.style.pixelWidth;
    if(!parent_w)
        parent_w = 0;

    el.style.fontSize = fontSize + "px";

    var el_h = el.offsetHeight ? el.offsetHeight : el.style.pixelHeight;
    if(!el_h)
        el_h = 0;

    var el_w = el.offsetHeight ? el.offsetWidth : el.style.pixelWidth;
    if(!el_w)
        el_w = 0;

    // 0.5 is the error on the measure that JavaScript does
    // if the real measure had been 12.49 px => JavaScript would have said 12px
    // so we think about the worst case when could have, we add 0.5 to 
    // compensate the round error
    var fs1 = (fontSize*(parent_w + 0.5))/(el_w + 0.5);
    var fs2 = (fontSize*(parent_h) + 0.5)/(el_h + 0.5);

    fontSize = Math.floor(Math.min(fs1,fs2));
    el.style.fontSize = fontSize + "px";
    return fontSize;
}

NB: el argumento de la función debe ser un elemento span o un elemento que sea más pequeño que su padre, de lo contrario, si los hijos y los padres tienen la misma función de ancho / alto fallarán.



1

Para que el tamaño de fuente se ajuste a su contenedor, en lugar de la ventana, vea la resizeFont()función que he compartido en esta pregunta (una combinación de otras respuestas, la mayoría de las cuales ya están vinculadas aquí). Se activa usando window.addEventListener('resize', resizeFont);.

JavaScript de vainilla: cambie el tamaño de la fuente para que se ajuste al contenedor

JavaScript:

function resizeFont() {
  var elements  = document.getElementsByClassName('resize');
  console.log(elements);
  if (elements.length < 0) {
    return;
  }
  _len = elements.length;
  for (_i = 0; _i < _len; _i++) {
    var el = elements[_i];
    el.style.fontSize = "100%";
    for (var size = 100; el.scrollHeight > el.clientHeight; size -= 10) {
      el.style.fontSize = size + '%';
    }
  }
}

Tal vez podría usar vw / vh como respaldo, por lo que asigna emorem unidades usando JavaScript, asegurando que las fuentes se escalen a la ventana si JavaScript está deshabilitado.

Aplique la .resizeclase a todos los elementos que contienen texto que desea escalar.

Active la función antes de agregar el detector de eventos de cambio de tamaño de ventana. Luego, cualquier texto que no se ajuste a su contenedor se reducirá cuando se cargue la página, así como cuando se cambie su tamaño.

NOTA: El valor por defecto font-sizedebe establecerse en cualquiera em, remo %para lograr resultados adecuados.


1

HTML

<div style="height:100px; width:200px;">
  <div id='qwe'>
    test
  </div>
</div>

Código JavaScript para maximizar el tamaño de fuente:

var fontSize, maxHeight, maxWidth, textElement, parentElement;
textElement = document.getElementById('qwe');
parentElement = textElement.parentElement;    
maxHeight = parentElement.clientHeight;
maxWidth = parentElement.clientWidth;
fontSize = maxHeight;
var minFS = 3, maxFS = fontSize;
while (fontSize != minFS) {
  textElement.style.fontSize = `${fontSize}px`;
  if (textElement.offsetHeight < maxHeight && textElement.offsetWidth <= maxWidth) {
    minFS = fontSize;
  } else{
    maxFS = fontSize;
  }
  fontSize = Math.floor((minFS + maxFS)/2);
}
textElement.style.fontSize = `${minFS}px`;
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.