Escalonamento de fontes com base na largura do contêiner

1188

Estou tendo dificuldades para entender minha escala de fonte.

Atualmente, tenho este site com um corpo font-sizede 100%. 100% do que? Isso parece calcular em 16 pixels.

Fiquei com a impressão de que 100% de alguma forma se referiria ao tamanho da janela do navegador, mas aparentemente não porque sempre tem 16 pixels, se a janela é redimensionada para uma largura móvel ou área de trabalho widescreen completa.

Como posso fazer a escala do texto no meu site em relação ao seu contêiner? Eu tentei usar em, mas isso também não aumenta.

Meu raciocínio é que coisas como o meu menu ficam esmagadas quando você redimensiona, então preciso reduzir o px font-sizede .menuItementre outros elementos em relação à largura do contêiner. (Por exemplo, no menu em uma área de trabalho grande, 22pxfunciona perfeitamente. Mova para a largura da mesa gráfica e 16pxé mais apropriado.)

Estou ciente de que posso adicionar pontos de interrupção, mas realmente quero que o texto seja dimensionado, além de ter pontos de interrupção extras; caso contrário, acabarei com centenas de pontos de interrupção para cada 100pixels de diminuição na largura para controlar o texto.

Francesca
fonte
34
font-size: 100%;significa 100% do tamanho do texto (isto é, o que ele herda de seu pai). Por padrão, isso é 16px. Portanto, se você usasse 50%, seria o tamanho da fonte: 8px
Andy
31
O que você procura é chamado de tipografia responsiva ou do tamanho de uma janela de visualização. css-tricks.com/viewport-sized-typography
gearsdigital
8
Dê uma olhada no FitText .
precisa
12
@ Andy: Na verdade, "por padrão" é o que os usuários têm para o tamanho do texto do navegador definido, o que pode não ser necessariamente 16px.
Scotts
1
veja esta resposta stackoverflow.com/a/28485608/4251431
Basheer AL-MOMANI 15/17/17

Respostas:

1496

EDIT: Se o contêiner não for o corpo, o CSS Tricks cobre todas as suas opções em Ajustando texto a um contêiner .

Se o contêiner for o corpo, o que você está procurando é o tamanho da porcentagem da viewport :

Os comprimentos de porcentagem da viewport são relativos ao tamanho do bloco inicial . Quando a altura ou largura do bloco inicial é alterada, elas são dimensionadas de acordo. No entanto, quando o valor de estouro no elemento raiz é automático, presume-se que não exista nenhuma barra de rolagem.

Os valores são:

  • vw (% da largura da janela de visualização)
  • vh (% da altura da janela de visualização)
  • vi (1% do tamanho da viewport na direção do eixo embutido do elemento raiz)
  • vb (1% do tamanho da janela de exibição na direção do eixo do bloco do elemento raiz)
  • vmin(o menor de vwou vh)
  • vmax(o maior ou vwou vh)

1 v * é igual a 1% do bloco inicial.

Usá-lo é assim:

p {
    font-size: 4vw;
}

Como você pode ver, quando a largura da janela de exibição aumenta, o mesmo ocorre font-sizesem a necessidade de usar consultas de mídia.

Esses valores são uma unidade de dimensionamento, exatamente como pxou em, para que também possam ser usados ​​para dimensionar outros elementos, como largura, margem ou preenchimento.

O suporte ao navegador é muito bom, mas você provavelmente precisará de um substituto, como:

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

Confira as estatísticas de suporte: http://caniuse.com/#feat=viewport-units .

Além disso, confira Truques CSS para uma visão mais ampla: Tipografia de tamanho de viewport

Aqui está um bom artigo sobre como definir tamanhos mínimo / máximo e exercer um pouco mais de controle sobre os tamanhos: Controle preciso sobre tipografia responsiva

E aqui está um artigo sobre como definir seu tamanho usando calc () para que o texto preencha a janela de visualização: http://codepen.io/CrocoDillon/pen/fBJxu

Além disso, consulte este artigo, que usa uma técnica apelidada de 'derretido' para ajustar também a altura da linha. Liderança derretida em CSS

jbenjohnson
fonte
547
Mas e se o contêiner não for a porta de visualização (corpo)?
11283 Alex
12
@ Alex, esse é o território JS. Experimente a FitText.jsalternativa fornecida na parte inferior do artigo fornecida por @jbenjohnson.
9788 Robbert #
10
É aqui que entram as chamadas consultas de elemento. Diferentemente das consultas de mídia, as consultas de elemento dimensionariam as coisas com base em seu bloco contendo, não na viewport, o que seria incrível! Mas infelizmente ainda não existe. No entanto, existem algumas polyfills e prova-de-conceito se você estiver interessado: coding.smashingmagazine.com/2013/06/25/... e filamentgroup.com/lab/element_query_workarounds
jbenjohnson
139
Desclassificado porque isso não responde à pergunta. Ele perguntou sobre o contêiner, não sobre a janela de exibição. Caso de uso completamente diferente.
SongBox 23/07
6
"bloco contendo inicial" refere-se ao elemento raiz. Esta não é a resposta correta para a pergunta.
Glifo
320

Mas e se o contêiner não for a viewport (corpo)?

Esta pergunta é feita em um comentário por Alex sob a resposta aceita .

Esse fato não significa vwque não possa ser utilizado, até certo ponto, no tamanho desse contêiner. Agora, para ver qualquer variação, é preciso supor que o contêiner seja de alguma forma flexível em tamanho. Seja por porcentagem direta widthou por 100% menos margens. O ponto se torna "discutível" se o contêiner estiver sempre definido como, digamos, 200pxlargo - então apenas defina um font-sizeque funcione para essa largura.

Exemplo 1

Com um contêiner de largura flexível, no entanto, deve-se perceber que, de alguma forma, o contêiner ainda está sendo dimensionado para fora da viewport . Como tal, é uma questão de ajustar uma vwconfiguração com base nessa diferença percentual de tamanho na janela de visualização, o que significa levar em consideração o tamanho dos wrappers pai. Veja este exemplo :

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

Supondo que aqui divé filho do body, é 50%dessa 100%largura, que é o tamanho da janela de visualização neste caso básico. Basicamente, você deseja definir um vwque ficará bem para você. Como você pode ver no meu comentário no conteúdo CSS acima, você pode "pensar" matematicamente com relação ao tamanho total da janela de exibição, mas não precisa fazer isso. O texto vai "flexionar" com o contêiner porque ele está flexionando com o redimensionamento da viewport. UPDATE: veja um exemplo de dois contêineres de tamanhos diferentes .

Exemplo 2

Você pode ajudar a garantir o dimensionamento da viewport forçando o cálculo com base nisso. Considere este exemplo :

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

O dimensionamento ainda é baseado na janela de exibição, mas é essencialmente configurado com base no próprio tamanho do contêiner.

O tamanho do contêiner deve mudar dinamicamente ...

Se o dimensionamento do elemento do contêiner acabasse alterando dinamicamente sua relação percentual, seja por @mediapontos de interrupção ou por JavaScript, qualquer que fosse o "destino" base, seria necessário recalcular para manter o mesmo "relacionamento" para o tamanho do texto.

Veja o exemplo 1 acima. Se a largura divfoi alterada 25%por um @mediaou outro JavaScript, ao mesmo tempo, font-sizeseria necessário ajustar a consulta de mídia ou o JavaScript para o novo cálculo de 5vw * .25 = 1.25. Isso colocaria o tamanho do texto no mesmo tamanho que teria sido se a "largura" do 50%contêiner original tivesse sido reduzida pela metade do tamanho da janela de exibição, mas agora foi reduzida devido a uma alteração no seu próprio cálculo de porcentagem.

Um desafio

Com a calc()função CSS3 em uso, seria difícil ajustar dinamicamente, pois essa função não funciona para font-sizepropósitos no momento. Portanto, você não poderá fazer um ajuste puro do CSS 3 se a largura estiver mudando calc(). Obviamente, um pequeno ajuste de largura das margens pode não ser suficiente para justificar qualquer alteração font-size, por isso pode não ser importante.

ScottS
fonte
(Há um bug do Chrome com o tamanho da porcentagem da janela de exibição e o redimensionamento da janela: code.google.com/p/chromium/issues/detail?id=124331 )
30 de
@thirtydot: Isso é lamentável (mas é bom estar ciente, obrigado). Espero que o bug seja resolvido em breve, mas parece que ele persiste há algum tempo.
21713 Scott
20
Ótima resposta, no entanto, não funcionará se o elemento contido tiver uma largura máxima.
Himmators
3
@KristofferNolgren: Isso se refere a dois pontos apresentados na minha resposta: (1) "supondo que o contêiner seja de alguma forma flexível em tamanho" (uma vez que a 'largura máxima' é atingida, ela não se flexiona mais, existe um problema ) (2) Se alguém puder determinar em que ponto a 'largura máxima' seria atingida, como observei, você poderá definir um @mediaponto de interrupção para alterar a forma como a fonte é dimensionada nesse ponto (essencialmente, fornecendo um tamanho fixo no alcance max-width) . Apenas um pensamento para trabalhar com uma max-widthsituação.
Scotts
Você acha que pode lançar um violino quando o elemento container está mudando dinamicamente por meio de consultas de mídia? Eu não tenho certeza se entendi.
J82
59

Solução com 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/


Solução com SVG e quebra 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/

Dantio
fonte
1
Essa ideia parece boa, a princípio. Então você percebe que não pode controlar facilmente a fonte no SVG dentro de <html>. A fonte é diferente no celular e no computador, o que afeta a largura final.
Stopi 04/04
@ Stopi, o que você acha de uma solução iFrame? exemplo
Dantio 12/12
10
Você pode SVG totalmente estilo de HTML / CSS
gman
1
O SVG pode ser estilizado com css se o svg estiver embutido (não use uma tag img).
8
Essa é a melhor e mais previsível solução escalável com base em um contêiner dinâmico.
JoshuaDavid
35

Em um dos meus projetos, uso uma "mistura" entre vw e vh para ajustar o tamanho da fonte às minhas necessidades, por exemplo:

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

Sei que isso não responde à pergunta do OP, mas talvez possa ser uma solução para qualquer outra pessoa.

lsblsb
fonte
3
Pode ser melhor usar vmine / ou em vmaxvez disso.
sebastian_k
4
ferramentas dev Chrome chama isso de um valor de propriedade inválido
phil294
31

Solução Pure-CSS com calc(), unidades CSS e matemática

Isso não é exatamente o que o OP pede, mas pode tornar o dia de alguém. Essa resposta não é fácil e precisa de algumas pesquisas sobre o desenvolvedor.

Eu vim finalmente para obter uma solução de CSS puro para isso usando calc()unidades diferentes. Você precisará de algum entendimento matemático básico de fórmulas para definir sua expressão calc().

Quando resolvi isso, tive que obter um cabeçalho responsivo de largura de página inteira com alguns pais que preenchiam poucos pais no DOM. Vou usar meus valores aqui, substituí-los pelos seus.

Para matemática

Você precisará de:

  • Proporção bem ajustada em algumas janelas de exibição. Eu usei 320 pixels, então tenho 24 pixels de altura e 224 pixels de largura, então a proporção é 9.333 ... ou 28/3
  • A largura do contêiner, eu tinha padding: 3eme a largura total, então isso chegou a100wv - 2 * 3em

X é a largura do contêiner; portanto, substitua-o por sua própria expressão ou ajuste o valor para obter texto de página inteira. Ré a proporção que você terá. Você pode obtê-lo ajustando os valores em alguma viewport, inspecionando a largura e a altura do elemento e substituindo-os por seus próprios valores. Além disso, é 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

E bang! Funcionou! eu escrevi

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

para o meu cabeçalho e se ajustou bem em todas as janelas de exibição.

Mas como isso funciona?

Precisamos de algumas constantes aqui em cima. 100vwsignifica a largura total da janela de visualização, e meu objetivo era estabelecer um cabeçalho de largura total com algum preenchimento.

A proporção. Obter uma largura e altura em uma viewport me proporcionou uma proporção para brincar, e com a relação eu sei qual deve ser a altura na outra largura da viewport. Calculá-los com a mão levaria muito tempo e pelo menos muita largura de banda, portanto, não é uma boa resposta.

Conclusão

Eu me pergunto por que ninguém descobriu isso e algumas pessoas estão dizendo que isso seria impossível de mexer com CSS. Não gosto de usar JavaScript para ajustar elementos, por isso não aceito respostas em JavaScript (e esqueço o jQuery) sem precisar cavar mais. Em suma, é bom que isso tenha sido descoberto e este seja um passo para implementações de CSS puro no design de sites.

Peço desculpas por qualquer convenção incomum no meu texto, não sou nativo em inglês e também sou bastante novo ao escrever respostas do Stack Overflow.

Também deve-se notar que temos barras de rolagem ruins em alguns navegadores. Por exemplo, ao usar o Firefox, notei que isso 100vwsignifica toda a largura da janela de exibição, estendendo-se sob a barra de rolagem (onde o conteúdo não pode ser expandido!); Portanto, o texto da largura total deve ser cuidadosamente marginado e, de preferência, testado em vários navegadores e dispositivos.

hegez
fonte
13
Essa solução funciona apenas se (1) você souber a fonte, (2) a fonte estiver disponível no dispositivo do usuário e (3) o texto for sempre o mesmo. Isso o torna um caso de uso muito limitado.
Andrei Volgin
Eu não entendo o que acontece se meu contêiner estiver corrigido, por exemplo: 640px e proporção de 16: 9. quais cálculos devo escrever?
Pery mimon
1
O seu recipiente de largura xé de 640 e a relação rde 16: 9, de modo que: x = 640px, r = 16 / 9, y = x / r = 640px / (16 / 9) = 360px
hegez
Nota: isso só funciona se você realmente tiver um texto com tamanho 16: 9, o que é uma situação estranha. Talvez ler a resposta pela segunda vez possa ajudar. Além disso, isso funciona apenas para one-liners.
hegez
Para ser sincero, você não explica "Proporção bem ajustada em algumas janelas de exibição. Eu usei 320 pixels, portanto tenho 24 pixels de altura e 224 pixels de largura, então a proporção é 9.333 ... ou 28/3" , sugiro explicar a proporção um pouco mais. O que a proporção representa?
3limin4t0r
28

Existe uma grande filosofia para esse problema.

A coisa mais fácil a fazer seria fornecer um determinado tamanho de fonte ao corpo (eu recomendo 10) e, em seguida, todo o outro elemento teria sua fonte em emou rem. Vou dar um exemplo para entender essas unidades. Emé sempre relativo ao seu pai:

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 é sempre relativo ao corpo:

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

E então você pode criar um script que modifique o tamanho da fonte em relação à largura do seu contêiner. Mas não é isso que eu recomendaria. Porque em um contêiner de 900 pixels de largura, por exemplo, você teria um pelemento com um tamanho de fonte de 12 pixels, digamos. E, na sua ideia, isso se tornaria um contêiner de 300 pixels de largura e tamanho de fonte de 4 pixels. Tem que haver um limite inferior.

Outras soluções seriam com consultas de mídia, para que você possa definir a fonte para diferentes larguras.

Mas as soluções que eu recomendaria é usar uma biblioteca JavaScript que o ajude com isso. E o fittext.js que encontrei até agora.

Dan Ovidiu Boncut
fonte
6
A remunidade é relativa ao elemento raiz, significando o htmlelemento, não o bodyelemento. O elemento raiz no DOM é a htmltag. developer.mozilla.org/pt-BR/docs/Web/CSS/length .. remsempre é relativo à htmltag, que é o elemento raiz, não a tag body. mas a boa resposta :)
Jonathan Marzullo
fittext.js faz o trabalho, recomendei essa solução!
Jacek Dziurdzikowski
FitText foi o vencedor para mim. Tentei algumas alternativas, mas essa parecia a mais simples e também bem integrada ao Drupal / Backdrop CMS. github.com/davatron5000/FitText.js
Joel auxiliar
23

Aqui está a função:

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

Em seguida, converta todos os tamanhos de fonte do elemento filho dos documentos em em's ou' %.

Em seguida, adicione algo assim ao seu código para definir o tamanho da fonte base.

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

http://jsfiddle.net/0tpvccjt/

tnt-rox
fonte
1
Até agora, este é o melhor solution.Short e leve
wp estudante
Práticas ruins e muito ineficiente
Jack Giffin
@tntrox Por mais ineficiente que seja hoje, era muito mais ineficiente há 4 anos. Rejeito esta resposta em vez de alternativas muito melhores. Sim, para suporte ao IE, seria necessário Javascript. Mas, não é necessário Javascript que seja tão terrível.
Jack Giffin
3
Acho que minha ignorância está aparecendo aqui. Mas por que o acima é terrível?
Eu não acho terrível. Eu recomendaria algumas pequenas alterações de formatação para torná-lo mais legível. Eu colocaria cada var em uma linha separada pelo menos. Pode não ser necessário return thisno final da função. Para o desempenho, você também pode querer renunciar ao redimensionamento para que não seja redesenhado à medida que você arrasta. É um código bastante simples, para que alguém possa basear sua solução aprimorada com pouco esforço.
Mnebuerquo 11/03/19
19

Existe uma maneira de fazer isso sem JavaScript!

Você pode usar uma imagem SVG embutida. Você pode usar CSS em um SVG se estiver embutido. Você deve se lembrar que o uso desse método significa que sua imagem SVG responderá ao tamanho do contêiner.

Tente usar a seguinte solução ...

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

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

Quer algo mais chamativo?

As imagens SVG também permitem fazer coisas legais com formas e lixo. Confira este ótimo caso de uso para texto escalável ...

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

Peter Mortensen
fonte
4
Essa solução não é diferente da aceita com vwdimensionamento. se você alterar o texto, tudo sairá do limite.
N69S 02/09/19
14

Isso pode não ser super prático, mas se você deseja que uma fonte seja uma função direta do pai, sem ter JavaScript que escute / faça um loop (intervalo) para ler o tamanho da div / página, existe uma maneira de fazê-lo. . Iframes.

Qualquer coisa dentro do iframe considerará o tamanho do iframe como o tamanho da viewport. Portanto, o truque é criar um iframe cuja largura seja a largura máxima que você deseja que o seu texto e cuja altura seja igual à altura máxima * a proporção de aspecto do texto específico.

Deixando de lado a limitação de que as unidades de janela de exibição também não podem aparecer nas unidades-mãe laterais para texto (como em ter o tamanho% se comportando como todo mundo), as unidades de janela de exibição fornecem uma ferramenta muito poderosa: conseguir a dimensão mínima / máxima . Você não pode fazer isso em nenhum outro lugar - você não pode dizer ... faça com que a altura dessa div seja a largura do pai *.

Dito isso, o truque é usar vmin e definir o tamanho do iframe para que [fração] * altura total seja um bom tamanho de fonte quando a altura for a dimensão limitadora e [fração] * largura total quando a largura for a dimensão limitadora. É por isso que a altura deve ser um produto da largura e da proporção.

Para o meu exemplo particular, você tem

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

O pequeno incômodo com esse método é que você precisa definir manualmente o CSS do iframe. Se você anexar o arquivo CSS inteiro, isso exigiria muita largura de banda para muitas áreas de texto. Então, o que faço é anexar a regra que desejo diretamente do meu CSS.

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

Você pode escrever uma função pequena que obtém a regra CSS / todas as regras CSS que afetariam a área de texto.

Não consigo pensar em outra maneira de fazer isso sem ter algum JavaScript de ciclismo / escuta. A solução real seria os navegadores fornecerem uma maneira de escalar o texto em função do contêiner pai e também fornecer a mesma funcionalidade do tipo vmin / vmax.

JSFiddle: https://jsfiddle.net/0jr7rrgm/3/ (clique uma vez para bloquear o quadrado vermelho do mouse e clique novamente para liberar)

A maior parte do JavaScript no violino é apenas a minha função de arrastar e clicar personalizada.

Roman Rekhler
fonte
@quemeful Não é assim quando trazemos o atributo 'new' e 'shiny' (drumroll, por favor ...) srcdoc: jsfiddle.net/wauzgob6/3
Jack Giffin
9

Usando vw, em& co. funciona com certeza, mas na IMO sempre precisa do toque de um humano para o ajuste fino.

Aqui está um script que eu escrevi com base na resposta @ tnt-rox ' que tenta automatizar o toque daquele 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>

Basicamente, reduz o tamanho da fonte 1eme começa a aumentar em 0,1 até atingir a largura máxima.

JSFiddle

WoodrowShigeru
fonte
1
+1 apenas para alguém que reconhece que emsexige um toque humano e um ritmo vertical não é algum tipo de feitiçaria.
serraosays 22/11/19
7

100% é relativo ao tamanho da fonte base, que, se você não a definiu, seria o padrão de agente do usuário do navegador.

Para obter o efeito desejado, eu usaria um código JavaScript para ajustar o tamanho da fonte base em relação às dimensões da janela.

scoota269
fonte
7

Dentro do seu CSS, tente adicionar isso na parte inferior, alterando a largura de 320 pixels para onde quer que seu design comece a quebrar:

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

        body { font-size: 1em; }

    }

Em seguida, forneça o tamanho da fonte em "px" ou "em" como desejar.

Chunky
fonte
7

Minha própria solução, baseada em jQuery, funciona aumentando gradualmente o tamanho da fonte até que o contêiner obtenha um grande aumento de altura (o que significa que houve uma quebra de linha).

É bem simples, mas funciona muito bem e é muito fácil de usar. Você não precisa saber nada sobre a fonte que está sendo usada, tudo é tratado pelo navegador.

Você pode brincar com ele em http://jsfiddle.net/tubededentifrice/u5y15d0L/2/

A mágica acontece aqui:

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;
};
Vincent
fonte
1
Como esse script será executado em todos os eventos de redimensionamento e / ou alterações de orientação, não recomendo o uso. Em vez de usar uma solução baseada em javascript, procure uma solução baseada em css, como indicado acima.
Pilatus
1
Alterações de redimensionamento e orientação são eventos "raros", não há problemas de desempenho aqui. Se preferir, não vincule aos eventos (se eles não redimensionarem os contêineres, por exemplo, para sites não responsivos). As soluções CSS não funcionam em todos os casos sem ter que pensar em nada (como a largura da fonte ou mais) como esta solução.
Vincent
Envolvi sua resposta como uma função jQuery. Ele recebe a altura máxima permitida, os tamanhos mínimo e máximo de fonte. Veja jsfiddle.net/oriadam/qzsy760k
oriadam
6

Esse componente da Web altera o tamanho da fonte para que a largura do texto interno corresponda à largura do contêiner. Confira a demonstração .

Você pode usá-lo assim:

<full-width-text>Lorem Ipsum</full-width-text>
pomber
fonte
6

Eu preparei uma função de escala simples usando transformação CSS em vez de tamanho da fonte. Você pode usá-lo dentro de qualquer contêiner, não precisa definir consultas de mídia etc. :)

Postagem no blog: cabeçalho escalável em CSS e JS de largura total

O 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';
  }
}

Demonstração de trabalho: https://codepen.io/maciejkorsan/pen/BWLryj

Maciej Korsan
fonte
Eu acho que o OP está procurando uma solução CSS.
M02ph3u5
5

Usar variáveis ​​CSS

Ninguém mencionou variáveis ​​CSS ainda, e essa abordagem funcionou melhor para mim, então:

Digamos que você tenha uma coluna em sua página com 100% da largura da tela de um usuário móvel, mas com max-width800 px, portanto, na área de trabalho, há espaço nos dois lados da coluna. Coloque isso no topo da sua página:

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

E agora você pode usar essa variável (em vez da vwunidade embutida ) para definir o tamanho da sua fonte. Por exemplo

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

Não é uma abordagem CSS pura , mas é bem próxima.


fonte
5

Tente http://simplefocus.com/flowtype/ . É isso que eu uso nos meus sites e funcionou perfeitamente.

Pixel Reaper
fonte
Os links são voláteis. Por favor, explique a solução diretamente na sua resposta. Além disso, não quero clicar em um link aleatório com qualquer conteúdo.
lilalinux
5

Meu problema era semelhante, mas relacionado à escala de texto em um cabeçalho. Tentei o Fit Font, mas precisava alternar o compressor para obter resultados, pois estava resolvendo um problema um pouco diferente, como era o Text Flow.

Então, escrevi meu próprio pequeno plug-in que reduziu o tamanho da fonte para caber no contêiner, supondo que você tenha overflow: hiddene white-space: nowrap, mesmo que reduzir a fonte ao mínimo não permita exibir o cabeçalho completo, apenas corta o que pode ser mostrado.

(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);
Aram Kocharyan
fonte
5

Artisticamente, se você precisar ajustar duas ou mais linhas de texto na mesma largura, independentemente da contagem de caracteres, terá boas opções.

É melhor encontrar uma solução dinâmica para que, seja qual for o texto digitado, tenhamos uma boa exibição.

Vamos ver como podemos nos aproximar.

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>

Tudo o que fazemos é obter a largura ( els[0].clientWidth) e o tamanho da fonte ( parseFloat(window.getComputedStyle(els[0],null).getPropertyValue("font-size"))) da primeira linha como referência e, em seguida, apenas calcular o tamanho da fonte das linhas subsequentes de acordo.

Redu
fonte
4

Tente usar o plug- in fitText , porque o tamanho da Viewport não é a solução para esse problema.

Basta adicionar a biblioteca:

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

E altere o tamanho da fonte para corrigir por configurações o coeficiente de texto:

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

Você pode definir valores máximos e mínimos de texto:

$("#text_div").fitText(0.8, { minFontSize: '12px', maxFontSize: '36px' });
krolovolk
fonte
Isso é útil apenas para o texto de exibição grande e não é recomendado para parágrafos.
Shiv
3

Dê uma olhada no meu código. Faz o font size smallerque fitquer que esteja lá.

Mas acho que isso não leva a uma boa experiência do usuário

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

Basheer AL-MOMANI
fonte
2

Como fallback do JavaScript (ou sua única solução), você pode usar meu plug-in jQuery Scalem , que permite escalar em relação ao elemento pai (contêiner) passando a referenceopção

thdoan
fonte
2

Caso seja útil para qualquer pessoa, a maioria das soluções nesse segmento estava agrupando texto em várias linhas, formulário e.

Mas então eu encontrei isso e funcionou:

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

Exemplo de uso:

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

pk1557
fonte
2

Sempre tenha seu elemento com este atributo:

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

ou

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

Quando você entra em tela cheia, já deve ter uma variável de escala calculada (escala> 1 ou escala = 1). Em seguida, em tela cheia:

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

Funciona muito bem com pouco código.

marirena
fonte
2

Para texto dinâmico, este plugin é bastante útil:

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

Basta adicionar 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;
}

E o script:

$('#mydiv').slabText();
pajouk
fonte
2

Isso funcionou para mim:

Eu tento aproximar o tamanho da fonte com base em uma largura / altura obtida com a definição de `tamanho da fonte: 10 px '. Basicamente, a idéia é "se eu tiver 20 pixels de largura e 11 pixels de altura com` font-size: 10px`, então qual seria o tamanho máximo da fonte para calcular um contêiner de 50 pixels de largura e 30 pixels de altura? "

A resposta é um sistema de dupla proporção:

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

Agora X é um tamanho de fonte que corresponderá à largura e Y é um tamanho de fonte que corresponderá à altura; pegue o 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;
}

Nota: o argumento da função deve ser um elemento de amplitude ou um elemento menor que seu pai, caso contrário, se filhos e pai tiverem a mesma função largura / altura falharão.

Maurizio Ricci
fonte
1

Não vejo nenhuma resposta com referência à propriedade CSS flex, mas também pode ser muito útil.

Smart Coder
fonte
2
Você pode elaborar?
Peter Mortensen
1

Para ajustar o tamanho da fonte ao seu contêiner, e não à janela, veja a resizeFont()função que compartilhei nesta pergunta (uma combinação de outras respostas, a maioria das quais já está vinculada aqui). É acionado usando window.addEventListener('resize', resizeFont);.

Vanilla JavaScript: redimensionar fontes incríveis para caber no contêiner

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 + '%';
    }
  }
}

Talvez você possa usar vw / vh como um substituto, para atribuir dinamicamente emourem unidades usando JavaScript, assegurando que as fontes fazer escala para a janela se JavaScript está desativado.

Aplique a .resizeclasse a todos os elementos que contêm o texto que você deseja dimensionar.

Ative a função antes de adicionar o ouvinte de redimensionamento de janela. Em seguida, qualquer texto que não se encaixe no contêiner será reduzido quando a página for carregada e redimensionada.

NOTA: O padrão font-sizedeve ser definida para em, remou %para alcançar resultados adequados.

Joshua Flood
fonte
1

HTML

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

Código JavaScript para maximizar o tamanho da fonte:

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`;
Ramil Gilfanov
fonte