Ridimensionamento dei caratteri in base alla larghezza del contenitore


1189

Non riesco a capire meglio il ridimensionamento dei caratteri.

Attualmente ho questo sito con un corpo font-sizedel 100%. Il 100% di cosa però? Questo sembra calcolare a 16 pixel.

Avevo l'impressione che il 100% si riferisse in qualche modo alle dimensioni della finestra del browser, ma apparentemente non perché è sempre 16 pixel se la finestra viene ridimensionata fino a una larghezza mobile o desktop widescreen completo.

Come posso rendere il testo sulla scala del mio sito in relazione al suo contenitore? Ho provato a usare em, ma neanche questo si ridimensiona.

Il mio ragionamento è che cose come il mio menu diventano schiacciati quando si ridimensiona, quindi ho bisogno di ridurre il px font-sizedi .menuItemtra gli altri elementi in relazione alla larghezza del contenitore. (Ad esempio, nel menu su un desktop di grandi dimensioni, 22pxfunziona perfettamente. Passa alla larghezza del tablet ed 16pxè più appropriato.)

Sono consapevole di poter aggiungere punti di interruzione, ma voglio davvero ridimensionare il testo oltre ad avere punti di interruzione aggiuntivi, altrimenti finirò con centinaia di punti di interruzione per ogni 100 pixel di larghezza ridotta per controllare il testo.


34
font-size: 100%;significa il 100% della dimensione che il testo sarebbe stato (cioè quello che eredita dal suo genitore). Di default è 16px. Quindi, se utilizzassi il 50%, sarebbe la dimensione del carattere: 8px
Andy,

31
Quello che stai cercando è chiamato tipografia responsive o viewport. css-tricks.com/viewport-sized-typography
gearsdigital


12
@Andy: In realtà, "per impostazione predefinita" è qualunque sia la dimensione del testo del browser impostata per gli utenti, che potrebbe non risolversi necessariamente a 16px.
ScottS,

1
dai un'occhiata a questa risposta stackoverflow.com/a/28485608/4251431
Basheer AL-MOMANI

Risposte:


1496

MODIFICA: Se il contenitore non è il corpo Trucchi CSS copre tutte le opzioni in Adatta testo a un contenitore .

Se il contenitore è il corpo, quello che stai cercando è la lunghezza in percentuale di Viewport :

Le lunghezze in percentuale della finestra sono relative alla dimensione del blocco contenente iniziale . Quando l'altezza o la larghezza del blocco contenitore iniziale viene modificata, vengono ridimensionate di conseguenza. Tuttavia, quando il valore di overflow sull'elemento radice è auto, si presume che non esistano barre di scorrimento.

I valori sono:

  • vw (% della larghezza della finestra)
  • vh (% dell'altezza del viewport)
  • vi (1% della dimensione del viewport nella direzione dell'asse inline dell'elemento radice)
  • vb (1% della dimensione del viewport nella direzione dell'asse del blocco dell'elemento radice)
  • vmin(il più piccolo di vwo vh)
  • vmax(il più grande o vwo vh)

1 v * è uguale all'1% del blocco contenente iniziale.

Usandolo si presenta così:

p {
    font-size: 4vw;
}

Come puoi vedere, quando la larghezza della finestra aumenta, così fai font-size, senza la necessità di utilizzare le media query.

Questi valori sono un'unità di dimensionamento, proprio come pxo em, quindi possono essere utilizzati anche per dimensionare altri elementi, come larghezza, margine o riempimento.

Il supporto del browser è abbastanza buono, ma probabilmente avrai bisogno di un fallback, come:

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

Consulta le statistiche di supporto: http://caniuse.com/#feat=viewport-units .

Inoltre, dai un'occhiata ai trucchi CSS per un aspetto più ampio: Viewport Sized Typography

Ecco un bell'articolo sull'impostazione delle dimensioni minime / massime e sull'esercizio di un maggiore controllo sulle taglie: controllo preciso sulla tipografia reattiva

Ed ecco un articolo sull'impostazione delle dimensioni usando calc () in modo che il testo riempia il viewport: http://codepen.io/CrocoDillon/pen/fBJxu

Inoltre, leggi questo articolo, che utilizza una tecnica chiamata "piombo fuso" per regolare anche l'altezza della linea. Leader fuso nel CSS


548
Ma cosa succede se il contenitore non è il viewport (corpo)?
Alex

12
@Alex, questo è il territorio di JS. Prova l' FitText.jsalternativa fornita in fondo all'articolo @jbenjohnson in dotazione.
Robbert,

10
È qui che entrano in gioco le cosiddette query degli elementi. A differenza delle media query, le query degli elementi dimensionano le cose in base al loro blocco contenitore, non alla finestra, che sarebbe sorprendente! Ma sfortunatamente non esiste ancora. Tuttavia, esistono alcuni polyfill e prove di concetti se sei interessato: coding.smashingmagazine.com/2013/06/25/… e filamentgroup.com/lab/element_query_workarounds
jbenjohnson

139
Declassato perché questo non risponde alla domanda. Ha chiesto informazioni sul container, non sul viewport. Caso d'uso completamente diverso.
SongBox,

6
"blocco contenente iniziale" si riferisce all'elemento radice. Questa non è la risposta corretta alla domanda posta.
Glifo

320

Ma cosa succede se il contenitore non è il viewport (corpo)?

Questa domanda viene posta in un commento da Alex sotto la risposta accettata .

Questo fatto non significa che non vwpossa essere utilizzato in una certa misura per le dimensioni di quel contenitore. Ora per vedere qualsiasi variazione bisogna supporre che il contenitore sia in qualche modo flessibile nelle dimensioni. Sia attraverso una percentuale diretta widthsia attraverso il 100% meno i margini. Il punto diventa "controverso" se il contenitore è sempre impostato su, diciamo, 200pxlargo - quindi basta impostare un font-sizeche funziona per quella larghezza.

Esempio 1

Con un contenitore a larghezza flessibile, tuttavia, è necessario rendersi conto che in qualche modo il contenitore viene ancora ridimensionato dalla finestra . In quanto tale, si tratta di regolare vwun'impostazione basata sulla differenza di dimensione percentuale rispetto al viewport, il che significa tenere conto del dimensionamento dei wrapper principali. Prendi questo esempio :

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

Supponendo qui che divsia un figlio di body, è 50%di quella 100%larghezza, che è la dimensione del viewport in questo caso di base. Fondamentalmente, vuoi impostare un vwaspetto che ti stia bene. Come puoi vedere nel mio commento nel contenuto CSS sopra, puoi "pensarci" matematicamente rispetto alla dimensione completa della finestra, ma non è necessario farlo. Il testo "fletterà" con il contenitore perché il contenitore si flette con il ridimensionamento della finestra. AGGIORNAMENTO: ecco un esempio di due contenitori di dimensioni diverse .

Esempio 2

È possibile contribuire a garantire il dimensionamento delle finestre forzando il calcolo basato su quello. Considera questo esempio :

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

Il dimensionamento è ancora basato su viewport, ma è essenzialmente impostato in base alle dimensioni del contenitore stesso.

La dimensione del contenitore deve cambiare in modo dinamico ...

Se il dimensionamento dell'elemento contenitore finiva per cambiare dinamicamente la sua relazione percentuale tramite @mediapunti di interruzione o JavaScript, qualunque fosse la "destinazione" di base avrebbe bisogno di essere ricalcolata per mantenere la stessa "relazione" per il dimensionamento del testo.

Prendi l'esempio n. 1 sopra. Se il divparametro fosse impostato su 25%larghezza da uno @mediao da JavaScript, allo stesso tempo, font-sizesarebbe necessario adattarlo nella query media o da JavaScript al nuovo calcolo di 5vw * .25 = 1.25. Ciò porterebbe la dimensione del testo alla stessa dimensione che sarebbe stata se la "larghezza" del 50%contenitore originale fosse stata ridotta della metà dal dimensionamento della finestra, ma ora è stata ridotta a causa di una modifica del proprio calcolo percentuale.

Una sfida

Con la calc()funzione CSS3 in uso, sarebbe difficile adattarsi dinamicamente, poiché quella funzione non funziona allo font-sizescopo in questo momento. Quindi non potresti fare una pura regolazione CSS 3 se la tua larghezza sta cambiando calc(). Naturalmente, un piccolo aggiustamento della larghezza per i margini potrebbe non essere sufficiente per giustificare qualsiasi cambiamento font-size, quindi potrebbe non avere importanza.


(C'è un bug di Chrome con lunghezze percentuali delle finestre e ridimensionamento della finestra: code.google.com/p/chromium/issues/detail?id=124331 )
tredotto

@thirtydot: È un peccato (ma è bene esserne consapevoli, grazie). Spero che il bug venga risolto presto, ma sembra che persista da tempo.
ScottS,

20
Ottima risposta, tuttavia, non funzionerà se l'elemento contenente ha una larghezza massima.
Himmators

3
@KristofferNolgren: Ciò si riferisce a due punti formulati nella mia risposta: (1) "supponendo che il contenitore sia in qualche modo di dimensioni flessibili" (una volta raggiunta la "larghezza massima", non si flette più, quindi c'è un problema ). (2) Se si può determinare in quale punto verrà raggiunta la "larghezza massima", come ho notato, è possibile impostare un @mediapunto di interruzione per modificare la dimensione del carattere in quel punto (essenzialmente assegnandogli una dimensione fissa al raggiungimento max-width) . Solo un pensiero per lavorare con una max-widthsituazione.
ScottS,

Pensi di poter gettare un violino di quando l'elemento container cambia dinamicamente attraverso le query multimediali? Non sono sicuro di capire.
J82,

59

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


Soluzione con SVG e a capo automatico 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
Questa idea sembra carina, all'inizio. Quindi ti rendi conto che non puoi controllare facilmente il carattere su SVG in <html>. Il carattere è diverso su dispositivi mobili e desktop, il che influisce sulla larghezza finale.
Stopi,

@Stopi cosa ne pensi di una soluzione iFrame? esempio
Dantio il

10
Puoi personalizzare completamente SVG da HTML / CSS
gman

1
SVG può essere disegnato con css se lo svg è in linea (non usare un tag img).

8
Questa è la soluzione migliore e più prevedibile che si ridimensiona in base a un contenitore dinamico.
JoshuaDavid,

35

In uno dei miei progetti utilizzo una "miscela" tra vw e vh per adattare le dimensioni del carattere alle mie esigenze, ad esempio:

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

So che questo non risponde alla domanda del PO, ma forse può essere una soluzione per chiunque altro.


3
Potrebbe essere meglio usare vmine / o vmaxinvece.
sebastian_k,

4
chrome dev tools lo chiama un valore di proprietà non valido
phil294

31

Soluzione Pure-CSS con calc()unità CSS e matematica

Questo non è esattamente ciò che chiede OP, ma potrebbe rendere la giornata di qualcuno. Questa risposta non è facile da nutrire con il cucchiaio e necessita di alcune ricerche da parte dello sviluppatore.

Sono finalmente arrivato a ottenere una soluzione CSS puro per questo utilizzando calc()unità diverse. Avrai bisogno di una comprensione matematica di base delle formule per elaborare la tua espressione calc().

Quando ho risolto questo problema, ho dovuto ottenere un'intestazione reattiva a tutta la pagina con alcuni padding su alcuni genitori in DOM. Userò i miei valori qui, sostituirli con i tuoi.

Alla matematica

Avrai bisogno:

  • Rapporto ben regolato in alcune finestre. Ho usato 320 pixel, quindi avevo 24 pixel di altezza e 224 pixel di larghezza, quindi il rapporto è 9.333 ... o 28/3
  • La larghezza del contenitore, ho avuto padding: 3eme tutta la larghezza, quindi è arrivato100wv - 2 * 3em

X è la larghezza del contenitore, quindi sostituiscilo con la tua espressione o regola il valore per ottenere il testo a pagina intera. Rè il rapporto che avrai. Puoi ottenerlo regolando i valori in alcune finestre, ispezionando la larghezza e l'altezza degli elementi e sostituendoli con i tuoi valori. Inoltre, lo è 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! Ha funzionato! scrissi

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

alla mia intestazione e si è adattato bene in ogni viewport.

Ma come funziona?

Abbiamo bisogno di alcune costanti qui. 100vwindica l'intera larghezza del riquadro di visualizzazione e il mio obiettivo era stabilire un'intestazione a larghezza intera con alcune imbottiture.

Il rapporto. Ottenere una larghezza e un'altezza in un viewport mi ha dato un rapporto con cui giocare, e con il rapporto so quale altezza dovrebbe essere nella larghezza dell'altro viewport. Calcolarli a mano richiederebbe molto tempo e almeno richiederebbe molta larghezza di banda, quindi non è una buona risposta.

Conclusione

Mi chiedo perché nessuno l'abbia capito e alcune persone stanno persino dicendo che sarebbe impossibile armeggiare con i CSS. Non mi piace usare JavaScript per regolare gli elementi, quindi non accetto le risposte JavaScript (e dimentico di jQuery) senza scavare di più. Tutto sommato, è positivo che questo sia stato capito e questo è un passo verso le implementazioni pure-CSS nella progettazione di siti Web.

Mi scuso per qualsiasi convenzione insolita nel mio testo, non sono madrelingua inglese e sono anche abbastanza nuovo a scrivere risposte Stack Overflow.

Va anche notato che abbiamo barre di scorrimento malvagie in alcuni browser. Ad esempio, quando si utilizza Firefox, ho notato che 100vwsignifica che l'intera larghezza del viewport si estende sotto la barra di scorrimento (dove il contenuto non può espandersi!), Quindi il testo a larghezza intera deve essere accuratamente marginato e preferibilmente essere testato con molti browser e dispositivi.


13
Questa soluzione funziona solo se (1) conosci il carattere, (2) il carattere è disponibile sul dispositivo di un utente e (3) il testo è sempre lo stesso. Questo lo rende un caso d'uso molto limitato.
Andrei Volgin,

non capisco cosa succede se il mio contenitore è stato risolto, ad esempio: 640 px e rapporto di 16: 9. quali calcoli dovrei scrivere?
pery mimon,

1
La larghezza del tuo contenitore xè di 640 px e rapporto r16: 9, quindi: x = 640px, r = 16 / 9, y = x / r = 640px / (16 / 9) = 360px
hegez,

Nota: questo funziona solo se in realtà hai un testo di dimensioni 16: 9, il che è una situazione strana. Forse leggere la risposta una seconda volta può essere d'aiuto. Inoltre, questo funziona solo per una linea.
Hegez,

A dire il vero non spieghi "Rapporto ben regolato in qualche viewport. Ho usato 320 pixel, quindi ho 24 pixel in altezza e 224 pixel in larghezza, quindi il rapporto è 9.333 ... o 28/3" Suggerisco di spiegare il rapporto un po 'di più. Cosa rappresenta il rapporto?
3limin4t0r

28

C'è una grande filosofia per questo problema.

La cosa più semplice da fare sarebbe dare una certa dimensione del carattere al corpo (consiglio 10), e quindi tutti gli altri elementi avrebbero il loro carattere in emo rem. Ti faccio un esempio per capire quelle unità. Emè sempre relativo al suo genitore:

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 al 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 quindi è possibile creare uno script che modifichi la dimensione del carattere rispetto alla larghezza del contenitore. Ma questo non è ciò che consiglierei. Perché in un contenitore di 900 pixel di larghezza, ad esempio, avresti ap elemento con una dimensione del carattere di 12 pixel, diciamo. E sulla tua idea che diventerebbe un contenitore largo 300 pixel con una dimensione del carattere di 4 pixel. Ci deve essere un limite inferiore.

Altre soluzioni sarebbero con le query multimediali, in modo da poter impostare il carattere per diverse larghezze.

Ma la soluzione che consiglierei è usare una libreria JavaScript che ti aiuti in questo. E fittext.js che ho trovato finora.


6
L' remunità è relativa all'elemento radice, ovvero l' htmlelemento, non l' bodyelemento. L'elemento radice nel DOM è il htmltag. developer.mozilla.org/en-US/docs/Web/CSS/length .. remè sempre relativo al htmltag, che è l'elemento radice, non al tag body .. ma buona risposta :)
Jonathan Marzullo

fittext.js fa il lavoro fatto, ho raccomandato quella soluzione!
Jacek Dziurdzikowski il

FitText è stato il vincitore per me. Ho provato alcune alternative ma questo sembrava il più semplice e si integrava bene anche con il CMS Drupal / Backdrop. github.com/davatron5000/FitText.js
Joel ausiliario

23

Ecco la funzione:

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

Quindi converti tutte le dimensioni dei caratteri degli elementi figlio dei documenti in em's o %.

Quindi aggiungi qualcosa di simile al tuo codice per impostare la dimensione del carattere di base.

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

http://jsfiddle.net/0tpvccjt/


1
Finora questa è la soluzione migliore. Breve e leggera
studente wp il

Cattive pratiche e fortemente inefficienti
Jack Giffin,

@tntrox Per quanto inefficiente come lo è oggi, è stato molto più inefficiente 4 anni fa. Respingo questa risposta al posto di alternative molto migliori. Sì, per il supporto IE, sarebbe necessario Javascript. Ma non è necessario Javascript che è così terribile.
Jack Giffin,

3
Immagino che la mia ignoranza si manifesti qui. Ma PERCHÉ è quanto sopra terribile?

Non penso sia terribile. Consiglierei alcune piccole modifiche alla formattazione per renderlo più leggibile. Metterei ogni var almeno su una riga separata. Potrebbe non essere necessario return thisal termine della funzione. Per quanto riguarda le prestazioni, potresti anche voler rimbalzare la dimensione originale in modo che non venga ridisegnata mentre trascini. È un codice piuttosto semplice, quindi qualcuno potrebbe basare la propria soluzione migliorata su di esso con poco sforzo.
Mnebuerquo,

19

C'è un modo per farlo senza JavaScript!

È possibile utilizzare un'immagine SVG in linea. È possibile utilizzare CSS su un SVG se è in linea. Devi ricordare che l'uso di questo metodo significa che l'immagine SVG risponderà alle dimensioni del suo contenitore.

Prova a utilizzare la seguente soluzione ...

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

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

Vuoi qualcosa di più appariscente?

Le immagini SVG ti consentono anche di fare cose interessanti con forme e spazzatura. Dai un'occhiata a questo fantastico caso d'uso per testo scalabile ...

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


4
Questa soluzione non è diversa da quella accettata con il vwdimensionamento. se cambi il testo, tutto va oltre il limite.
N69S,

14

Questo potrebbe non essere super pratico, ma se vuoi che un font sia una funzione diretta del genitore, senza avere JavaScript che ascolti / esegua (intervallo) per leggere la dimensione del div / page, c'è un modo per farlo . Iframe.

Qualunque cosa all'interno dell'iframe considererà la dimensione dell'iframe come la dimensione della finestra. Quindi il trucco è semplicemente creare un iframe la cui larghezza è la larghezza massima che desideri sia il tuo testo e la cui altezza è uguale all'altezza massima * le proporzioni del testo particolare.

Mettendo da parte la limitazione che le unità viewport non possono anche trovare unità padre secondarie per il testo (come in, avendo la dimensione% si comportano come tutti gli altri), le unità viewport forniscono uno strumento molto potente: essere in grado di ottenere la dimensione minima / massima . Non puoi farlo altrove - non puoi dire ... rendere l'altezza di questo div essere la larghezza del genitore * qualcosa.

Detto questo, il trucco è usare vmin e impostare la dimensione dell'iframe in modo che [frazione] * l'altezza totale sia una buona dimensione del carattere quando l'altezza è la dimensione limitante e [la frazione] * larghezza totale quando la larghezza è la dimensione limitante. Questo è il motivo per cui l'altezza deve essere un prodotto della larghezza e delle proporzioni.

Per il mio esempio particolare, hai

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

Il piccolo fastidio con questo metodo è che devi impostare manualmente il CSS dell'iframe. Se si allega l'intero file CSS, ciò richiederebbe molta larghezza di banda per molte aree di testo. Quindi, quello che faccio è allegare la regola che desidero direttamente dal mio CSS.

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

È possibile scrivere una piccola funzione che ottiene la regola CSS / tutte le regole CSS che influirebbero sull'area di testo.

Non riesco a pensare a un altro modo di farlo senza avere JavaScript / ciclismo. La vera soluzione sarebbe che i browser fornissero un modo per ridimensionare il testo in funzione del contenitore principale e fornire anche la stessa funzionalità di tipo vmin / vmax.

JSFiddle: https://jsfiddle.net/0jr7rrgm/3/ (fare clic una volta per bloccare il quadrato rosso sul mouse e fare nuovamente clic per rilasciare)

La maggior parte del JavaScript nel violino è solo la mia funzione click-drag personalizzata.


@quemeful Non così quando introduciamo l' attributo 'nuovo' e 'lucido' ( rullo di tamburi per favore ...) srcdoc: jsfiddle.net/wauzgob6/3
Jack Giffin,

9

Utilizzando vw, em& co. funziona di sicuro, ma IMO ha sempre bisogno di un tocco umano per la messa a punto.

Ecco uno script che ho appena scritto basato sulla risposta di @ tnt-rox che cerca di automatizzare il tocco di quell'umano:

$('#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>

In pratica riduce la dimensione del carattere a 1eme quindi inizia a incrementare di 0,1 fino a raggiungere la larghezza massima.

JSFiddle


1
+1 solo per qualcuno che riconosce che emsrichiede un tocco umano e un ritmo verticale non è una sorta di stregoneria.
serraosays,

7

100% è relativo alla dimensione del carattere di base, che, se non lo hai impostato, sarebbe l'impostazione predefinita dell'agente utente del browser.

Per ottenere l'effetto che stai cercando, userei un pezzo di codice JavaScript per regolare la dimensione del carattere di base rispetto alle dimensioni della finestra.


7

All'interno del tuo CSS, prova ad aggiungere questo in basso modificando la larghezza di 320 pixel per ovunque il tuo design inizi a rompersi:

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

        body { font-size: 1em; }

    }

Quindi inserisci la dimensione del carattere in "px" o "em" come desideri.


7

La mia soluzione, basata su jQuery, funziona aumentando gradualmente la dimensione del carattere fino a quando il contenitore ottiene un grande aumento di altezza (il che significa che ha un'interruzione di riga).

È piuttosto semplice, ma funziona abbastanza bene ed è molto facile da usare. Non devi sapere nulla del carattere utilizzato, tutto è curato dal browser.

Puoi giocarci su http://jsfiddle.net/tubededentifrice/u5y15d0L/2/

La magia accade qui:

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
Poiché questo script verrà eseguito su ogni evento di ridimensionamento e / o modifica dell'orientamento, non è consigliabile utilizzarlo. Invece di utilizzare una soluzione basata su JavaScript, cerca una soluzione basata su CSS come indicato sopra.
Pilatus,

1
I cambiamenti di ridimensionamento e orientamento sono eventi "rari", non ci sono problemi di prestazioni qui. Se preferisci, non associarti agli eventi (se non ridimensionano i contenitori, ad esempio, per i siti Web non responsive). Le soluzioni CSS non funzionano in tutti i casi senza dover pensare a nulla (come la larghezza del carattere o giù di lì) come fa questa soluzione.
Vincent,

Ho racchiuso la tua risposta come funzione jQuery. Riceve l'altezza massima consentita, le dimensioni minime e massime dei caratteri. Vedi jsfiddle.net/oriadam/qzsy760k
oriadam,

6

Questo componente Web modifica la dimensione del carattere in modo che la larghezza del testo interno corrisponda alla larghezza del contenitore. Controlla la demo .

Puoi usarlo in questo modo:

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


6

Ho preparato una semplice funzione di ridimensionamento utilizzando la trasformazione CSS anziché la dimensione del carattere. Puoi usarlo all'interno di qualsiasi contenitore, non devi impostare query multimediali, ecc :) :)

Post di blog: intestazione scalabile CSS & JS a tutta larghezza

Il codice:

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

Demo funzionante: https://codepen.io/maciejkorsan/pen/BWLryj


Penso che OP stia cercando una soluzione CSS.
m02ph3u5

5

Usa variabili CSS

Nessuno ha ancora menzionato le variabili CSS e questo approccio ha funzionato meglio per me, quindi:

Supponiamo che tu abbia una colonna sulla tua pagina che è il 100% della larghezza dello schermo di un utente mobile, ma ha un max-width800px, quindi sul desktop c'è un po 'di spazio su entrambi i lati della colonna. Metti questo nella parte superiore della tua pagina:

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

E ora puoi usare quella variabile (invece vwdell'unità integrata) per impostare la dimensione del tuo carattere. Per esempio

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

Non è un puro approccio CSS, ma è piuttosto vicino.


5

Prova http://simplefocus.com/flowtype/ . Questo è quello che uso per i miei siti e ha funzionato perfettamente.


I collegamenti sono volatili. Spiega la soluzione direttamente nella tua risposta. Inoltre, non voglio fare clic su un collegamento casuale con qualsiasi contenuto.
lilalinux,

5

Il mio problema era simile, ma legato al ridimensionamento del testo all'interno di un'intestazione. Ho provato Fit Font, ma avevo bisogno di attivare o disattivare il compressore per ottenere risultati, poiché stava risolvendo un problema leggermente diverso, come lo era Text Flow.

Così ho scritto il mio piccolo plugin che ha ridotto la dimensione del carattere per adattarlo al contenitore, supponendo che tu lo abbia fatto overflow: hiddene in white-space: nowrapmodo che anche se ridurre il carattere al minimo non consente di mostrare l'intera intestazione, taglia solo ciò che può mostrare.

(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

Dal punto di vista artistico, se hai bisogno di adattare due o più righe di testo nella stessa larghezza, indipendentemente dal conteggio dei caratteri, hai delle belle opzioni.

È meglio trovare una soluzione dinamica in modo che qualunque testo sia inserito finiamo con un bel display.

Vediamo come possiamo avvicinarci.

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>

Tutto ciò che facciamo è ottenere la larghezza ( els[0].clientWidth) e la dimensione del carattere ( parseFloat(window.getComputedStyle(els[0],null).getPropertyValue("font-size"))) della prima riga come riferimento e quindi calcolare di conseguenza la dimensione del carattere delle righe successive.


4

Prova a utilizzare il plug-in fitText , perché le dimensioni di Viewport non sono la soluzione di questo problema.

Aggiungi la libreria:

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

E cambia la dimensione del carattere per correggere secondo le impostazioni il coefficiente di testo:

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

È possibile impostare i valori massimo e minimo del testo:

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

Ciò è utile solo per il testo di visualizzazione grande e non è raccomandato per i paragrafi.
Shiv,

3

Dai un'occhiata al mio codice. Rende la font size smallerdi fitqualunque cosa lì.

Ma penso che questo non porti a una buona esperienza utente

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

Risultato


2

Come fallback JavaScript (o la tua unica soluzione), puoi usare il mio plugin jQuery Scalem , che ti consente di ridimensionare rispetto all'elemento genitore (contenitore) passando l' referenceopzione.


2

Nel caso in cui sia utile a chiunque, la maggior parte delle soluzioni in questo thread sono state avvolgere il testo in più righe, forma e.

Ma poi ho trovato questo, e ha funzionato:

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

Esempio di utilizzo:

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


2

Avere sempre il tuo elemento con questo attributo:

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

o

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

Quando si va a schermo intero, si dovrebbe già avere una scala variabile calcolato (scala> 1 o scale = 1). Quindi, a schermo intero:

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

Funziona bene con poco codice.


2

Per il testo dinamico, questo plugin è abbastanza utile:

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

Aggiungi semplicemente 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 la sceneggiatura:

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

2

Questo ha funzionato per me:

Provo ad approssimare la dimensione del carattere in base a una larghezza / altezza ottenuta dall'impostazione di `font-size: 10px`. Fondamentalmente, l'idea è "se avessi 20 pixel di larghezza e 11 pixel di altezza con` font-size: 10px`, quindi quale sarebbe la dimensione massima del font per la matematica di un contenitore di 50 pixel di larghezza e 30 pixel di altezza? "

La risposta è un sistema a doppia proporzione:

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

Ora X è una dimensione del carattere che corrisponderà alla larghezza e Y è una dimensione del carattere che corrisponderà all'altezza; prendi il valore più piccolo

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: l'argomento della funzione deve essere un elemento span o un elemento più piccolo del suo genitore, altrimenti se i figli e il genitore hanno entrambi la stessa funzione larghezza / altezza falliranno.



1

Per adattare la dimensione del carattere al suo contenitore, piuttosto che alla finestra, vedere la resizeFont()funzione che ho condiviso in questa domanda (una combinazione di altre risposte, la maggior parte delle quali sono già collegate qui). Viene attivato utilizzando window.addEventListener('resize', resizeFont);.

Vanilla JavaScript: ridimensiona il font-fantastico per adattarlo al contenitore

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

Potresti forse usare vw / vh come fallback, quindi assegni dinamicamente emo remunità usando JavaScript, assicurandoti che i caratteri si ridimensionino alla finestra se JavaScript è disabilitato.

Applica la .resizeclasse a tutti gli elementi contenenti testo che desideri ridimensionare.

Attiva la funzione prima di aggiungere il listener di eventi ridimensionamento finestra. Quindi, qualsiasi testo che non si adatta al suo contenitore verrà ridimensionato quando la pagina viene caricata, nonché quando viene ridimensionata.

NOTA: Il valore di default font-sizedeve essere impostato su em, remo %per ottenere risultati adeguati.


1

HTML

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

Codice JavaScript per massimizzare la dimensione del carattere:

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`;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.