ridimensionare il carattere per adattarlo a un div (su una riga)

Ci sono state domande simili, ma le soluzioni si confondono con quello che sto cercando di fare. Fondamentalmente, ho un articolo con un titolo (

). Non voglio controllare la lunghezza del titolo, ma non voglio che il titolo appaia su più righe. C’è un modo con css o jQuery per ridimensionare il testo in base alla larghezza di un tag

?

So cosa farei con lo pseudocodice se potessi rilevare la sovrapposizione del testo sul bordo del

:

 var fontize = $("#title").css("font-size"); var i = /*remove unit from integer*/ while( /*text overlaps div*/ ){ $("#title").css("font-size", --i+"pt"); } 

Se c’è un attributo CSS che posso impostare sarebbe ancora più bello, ma non riesco a trovarne uno (l’overflow non funzionerebbe in questa situazione).

CSS no, Javascript sì

Non c’è modo di farlo usando i CSS, ma puoi farlo in javascript / jQuery. Per aiutarti con il tuo codice pseudo perché sai già cosa fare. È solo che non sai come rilevare la larghezza in eccesso.

Il modo migliore sarebbe avere un DIV con il seguente stile (almeno):

 position: absolute; visibility: hidden; white-space: nowrap; font-family: /* same as your title's */ 

quindi copi il tuo testo e imposta le dimensioni iniziali del carattere. Quindi puoi scorrere il tuo ciclo while e fermarti quando la larghezza del div è appropriata. Quindi imposta la dimensione del carattere calcasting sul titolo originale.

In questo modo questo controllo sarà nascosto agli occhi dell’utente e quindi funzionerà anche più velocemente.

BTW : Questo è il solito modo in cui funzionano gli script di area di lavoro in crescita automatica. Usano div dummy con le stesse impostazioni di stile dell’area di testo originale e regolano l’altezza dell’area mentre l’utente digita il testo. Quindi l’area di testo può essere piuttosto piccola all’inizio, ma se l’utente digita un sacco di testo, si espanderà automaticamente per accogliere il contenuto.

Mentre l’ottimizzazione del ciclo

È ansible ottimizzare il ciclo while per ridurre considerevolmente il numero di iterazioni:

  1. Imposta una dimensione del carattere iniziale.
  2. ottieni la DIV di prova.
  3. calcolare il fattore di larghezza tra orig_div e test_div.
  4. regola la dimensione del carattere per questo fattore piuttosto che aumentare / diminuire di un’unità
  5. test test_div width

Ho avuto un problema simile, che mi ha fatto scrivere il mio plugin per questo. Dai un’occhiata a jquery-quickfit (che è abbastanza simile alla soluzione di Robert Koritnik , che mi piace molto).

Per evitare che il titolo si estenda su più righe, basta aggiungere uno stile css di:

 white-space:nowrap; 

all’elemento

Dopo aver incluso jquery e quickfit nell’intestazione. Puoi triggersre Quickfit con:

 $('h1').quickfit(); 

Misura e calcola una misura invariabile della misura per ogni lettera del testo per adattarla e la utilizza per calcolare la successiva dimensione del font che meglio si adatta al testo nel contenitore.

I calcoli sono memorizzati nella cache, il che rende molto veloce quando si tratta di dover inserire più testo o dover inserire un testo più volte, come ad es. Ridimensionare le windows (non c’è quasi nessuna penalizzazione delle prestazioni sul ridimensionamento).

Demo per una situazione simile alla tua

Ulteriori documentazione, esempi e codice sorgente si trovano nella pagina del progetto.

Qui ci sono 3 funzioni che uso frequentemente per ottenere la larghezza del testo, l’altezza e regolare la dimensione alla larghezza del contenitore.

  • getTextWidth () ti restituirà la larghezza effettiva del testo contenuto nell’iniziatore .
  • getTextHeight (larghezza) restituirà l’altezza effettiva del testo inserito contenuto nell’iniziatore con una certa larghezza specificata.
  • autoTextSize (minSize, maxSize, truncate) ridimensiona il testo all’interno del contenitore in modo che si adatti, considerando una dimensione minima e massima.
  • autoTruncateText () mostrerà solo i caratteri che l’utente può effettivamente vedere e terminare il testo con ‘…’.
 (function ($) { $.fn.getTextWidth = function() { var spanText = $("BODY #spanCalculateTextWidth"); if (spanText.size() <= 0) { spanText = $(""); spanText.appendTo("BODY"); } var valu = this.val(); if (!valu) valu = this.text(); spanText.text(valu); spanText.css({ "fontSize": this.css('fontSize'), "fontWeight": this.css('fontWeight'), "fontFamily": this.css('fontFamily'), "position": "absolute", "top": 0, "opacity": 0, "left": -2000 }); return spanText.outerWidth() + parseInt(this.css('paddingLeft')) + 'px'; }; $.fn.getTextHeight = function(width) { var spanText = $("BODY #spanCalculateTextHeight"); if (spanText.size() <= 0) { spanText = $(""); spanText.appendTo("BODY"); } var valu = this.val(); if (!valu) valu = this.text(); spanText.text(valu); spanText.css({ "fontSize": this.css('fontSize'), "fontWeight": this.css('fontWeight'), "fontFamily": this.css('fontFamily'), "top": 0, "left": -1 * parseInt(width) + 'px', "position": 'absolute', "display": "inline-block", "width": width }); return spanText.innerHeight() + 'px'; }; /** * Adjust the font-size of the text so it fits the container. * * @param minSize Minimum font size? * @param maxSize Maximum font size? * @param truncate Truncate text after sizing to make sure it fits? */ $.fn.autoTextSize = function(minSize, maxSize, truncate) { var _self = this, _width = _self.innerWidth(), _textWidth = parseInt(_self.getTextWidth()), _fontSize = parseInt(_self.css('font-size')); while (_width < _textWidth || (maxSize && _fontSize > parseInt(maxSize))) { if (minSize && _fontSize <= parseInt(minSize)) break; _fontSize--; _self.css('font-size', _fontSize + 'px'); _textWidth = parseInt(_self.getTextWidth()); } if (truncate) _self.autoTruncateText(); }; /** * Function that truncates the text inside a container according to the * width and height of that container. In other words, makes it fit by chopping * off characters and adding '...'. */ $.fn.autoTruncateText = function() { var _self = this, _width = _self.outerWidth(), _textHeight = parseInt(_self.getTextHeight(_width)), _text = _self.text(); // As long as the height of the text is higher than that // of the container, we'll keep removing a character. while (_textHeight > _self.outerHeight()) { _text = _text.slice(0,-1); _self.text(_text); _textHeight = parseInt(_self.getTextHeight(_width)); _truncated = true; } // When we actually truncated the text, we'll remove the last // 3 characters and replace it with '...'. if (!_truncated) return; _text = _text.slice(0, -3); // Make sure there is no dot or space right in front of '...'. var lastChar = _text[_text.length - 1]; if (lastChar == ' ' || lastChar == '.') _text = _text.slice(0, -1); _self.text(_text + '...'); }; })(jQuery); 

@Clovis Sei grazie per la tua risposta. Mi risulta molto utile. Peccato, non posso ringraziarti più di un semplice voto.

Nota: Devo cambiare “$ J (” per “$ (” perché funzioni sulla mia configurazione.

evendo, questo fuori dallo scopo di questa domanda e non nell’uso di SO, ho esteso il tuo codice per farlo funzionare per box a più righe con altezza massima.

  /** * Adjust the font-size of the text so it fits the container * * support multi-line, based on css 'max-height'. * * @param minSize Minimum font size? * @param maxSize Maximum font size? */ $.fn.autoTextSize_UseMaxHeight = function(minSize, maxSize) { var _self = this, _width = _self.innerWidth(), _boxHeight = parseInt(_self.css('max-height')), _textHeight = parseInt(_self.getTextHeight(_width)), _fontSize = parseInt(_self.css('font-size')); while (_boxHeight < _textHeight || (maxSize && _fontSize > parseInt(maxSize))) { if (minSize && _fontSize <= parseInt(minSize)) break; _fontSize--; _self.css('font-size', _fontSize + 'px'); _textHeight = parseInt(_self.getTextHeight(_width)); } }; 

PS: So che questo dovrebbe essere un commento, ma i commenti non mi permettono di postare correttamente il codice.

Oggi ho creato un plugin jQuery chiamato jQuery Responsive Headlines che fa esattamente ciò che vuoi: aggiusta la dimensione del font di un titolo per adattarlo al suo elemento contenitore (un div, il corpo o qualsiasi altra cosa). Ci sono alcune buone opzioni che è ansible impostare per personalizzare il comportamento del plugin e ho anche preso la precauzione di aggiungere il supporto per la funzionalità Throttle / Debounce di Ben Altmans per aumentare le prestazioni e facilitare il carico sul browser / computer quando l’utente ridimensiona il finestra. Nel suo caso d’uso più semplice il codice sarebbe simile a questo:

 $('h1').responsiveHeadlines(); 

… che trasformsrebbe tutti gli elementi della pagina in elementi reattivi di una riga che adattano le loro dimensioni all’elemento padre / contenitore.

Troverai il codice sorgente e una descrizione più lunga del plugin su questa pagina GitHub .

In bocca al lupo!

Molto semplice. Crea un’estensione per il testo, ottieni la larghezza e riduci la dimensione del font fino a quando lo span ha la stessa larghezza del contenitore div:

 while($("#container").find("span").width() > $("#container").width()) { var currentFontSize = parseInt($("#container").find("span").css("font-size")); $("#container").find("span").css("font-size",currentFontSize-1); } 

Questo potrebbe essere eccessivo per quello che ti serve, ma ho trovato questa libreria molto utile:

http://fittextjs.com/

Però va bene solo per le singole linee, quindi non sono sicuro se questo si adatta alle tue esigenze.

Non ero innamorato delle altre soluzioni là fuori, quindi, ecco un altro. Richiede il tag che stai ridimensionando il testo all’interno di:

  1. Essere altezza fissa

  2. Non essere così lungo da oltrepassare i limiti a 10px – l’idea è che non vuoi che scatti al di sotto di questo e ridimensiona il testo per diventare illeggibile. Non è un problema nel nostro caso d’uso, ma se è ansible nel tuo, vorrai dare dei pensieri da troncare separatamente prima di eseguirlo.

Utilizza una ricerca binaria per trovare la dimensione migliore, quindi sospetto che superi le altre soluzioni qui e altrove, semplicemente aumentando la dimensione del carattere di un pixel più e più volte. La maggior parte dei browser oggi supporta i decimali anche nelle dimensioni dei caratteri, e questo script ha alcuni vantaggi in quanto può arrivare a una risoluzione migliore di .1px, qualunque esso sia, anche se è un decimale relativamente lungo. È ansible modificare facilmente max - fontSize < .1 in un valore diverso da .1 per ottenere una precisione minore con un utilizzo inferiore della CPU.

Uso:

 $('div.event').fitText(); 

Codice:

 (function() { function resizeLoop(testTag, checkSize) { var fontSize = 10; var min = 10; var max = 0; var exceeded = false; for(var i = 0; i < 30; i++) { testTag.css('font-size', fontSize); if (checkSize(testTag)) { max = fontSize; fontSize = (fontSize + min) / 2; } else { if (max == 0) { // Start by growing exponentially min = fontSize; fontSize *= 2; } else { // If we're within .1px of max anyway, call it a day if (max - fontSize < .1) break; // If we've seen a max, move half way to it min = fontSize; fontSize = (fontSize + max) / 2; } } } return fontSize; } function sizeText(tag) { var width = tag.width(); var height = tag.height(); // Clone original tag and append to the same place so we keep its original styles, especially font var testTag = tag.clone(true) .appendTo(tag.parent()) .css({ position: 'absolute', left: 0, top: 0, width: 'auto', height: 'auto' }); var fontSize; // TODO: This decision of 10 characters is arbitrary. Come up // with a smarter decision basis. if (tag.text().length < 10) { fontSize = resizeLoop(testTag, function(t) { return t.width() > width || t.height() > height; }); } else { testTag.css('width', width); fontSize = resizeLoop(testTag, function(t) { return t.height() > height; }); } testTag.remove(); tag.css('font-size', fontSize); }; $.fn.fitText = function() { this.each(function(i, tag) { sizeText($(tag)); }); }; })(); 

http://jsfiddle.net/b9chris/et6N6/1/

C’è un plugin jquery disponibile su github che probabilmente fa solo quello che vuoi. Si chiama jquery-quickfit. Usa Jquery per fornire un approccio rapido e sporco al assembly del testo nel contenitore circostante.

HTML:

 
Text to fit*

Javascript:

    

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

La mia soluzione, come estensione jQuery basata sulla risposta di Robert Koritnik :

 $.fn.fitToWidth=function(){ $(this).wrapInner("").each(function(){ var $t=$(this); var a=$t.outerWidth(), $s=$t.children("span"), f=parseFloat($t.css("font-size")); while($t.children("span").outerWidth() > a) $t.css("font-size",--f); $t.html($s.html()); }); } 

In questo modo viene creata una campata temporanea che eredita proprietà importanti e confronta la differenza di larghezza. Certo, il ciclo while deve essere ottimizzato (ridurre di una differenza percentuale calcasting tra le due dimensioni).

Esempio di utilizzo:

 $(function(){ $("h1").fitToWidth(); }); 

Ho fatto un po ‘di roba jQuery per regolare la dimensione del font del tuo div. Funziona anche con più linee, ma aumenterà solo la dimensione del font (puoi semplicemente impostare una dimensione predefinita di 1px se lo desideri). Aumento la dimensione del font fino a quando non ho un’interruzione di riga, set lo diminuisce di 1px. Niente altra roba stravagante, div nascosto o così. Aggiungi semplicemente la class quickfit al tuo div.

 $(".quickfit").each(function() { var jThis=$(this); var fontSize=parseInt(jThis.css("font-size")); var originalLines=jThis.height()/fontSize; for(var i=0;originalLines>=jThis.height()/fontSize && i<30;i++) { jThis.css("font-size",""+(++fontSize)+"px"); } jThis.css("font-size",""+(fontSize-1)+"px"); }); 

Capisco che a questa domanda sembra sia stata data una risposta abbastanza esauriente, ma ci sono stati alcuni casi in cui le soluzioni qui potrebbero causare altri problemi. Ad esempio, la libreria di tkahn sembrava essere molto utile, ma ha cambiato la visualizzazione dell’elemento a cui era collegato, il che potrebbe rivelarsi un problema. Nel mio caso, mi ha impedito di centrare il testo sia verticalmente che orizzontalmente. Dopo alcuni tentativi e sperimentazioni, ho trovato un metodo semplice che coinvolge jQuery per adattare il testo su una riga senza dover modificare alcun attributo dell’elemento genitore. Nota che in questo codice ho usato il suggerimento di Robert Koritnik per ottimizzare il ciclo while. Per utilizzare questo codice, è sufficiente aggiungere la class “font_fix” a qualsiasi div contenente testo che deve essere adattato ad esso in una riga. Per un’intestazione, potrebbe essere necessario un ulteriore div intorno all’intestazione. Quindi, chiamare questa funzione una volta per un div di dimensione fissa o impostarlo su un listener di ridimensionamento e / o orientamento per dimensioni diverse.

 function fixFontSize(minimumSize){ var x = document.getElementsByClassName("font_fix"); for(var i = 0; i < x.length; i++){ x[i].innerHTML = '
' + x[i].innerHTML + '
'; var y = x[i].getElementsByClassName("font_fix_inner")[0]; var size = parseInt($("#" + x[i].id).css("font-size")); size *= x[i].clientWidth / y.clientWidth; while(y.clientWidth > x[i].clientWidth){ size--; if(size <= minimumSize){ size = minimumSize; y.style.maxWidth = "100%"; y.style.overflow = "hidden"; y.style.textOverflow = "ellipsis"; $("#" + x[i].id).css("font-size", size + "px"); break; } $("#" + x[i].id).css("font-size", size + "px"); } } }

Ora, ho aggiunto un altro caso in cui il testo viene troncato se diventa troppo piccolo (al di sotto della soglia minima passata nella funzione) per comodità. Un'altra cosa che accade una volta raggiunta la soglia che può o non può essere desiderata è la modifica della larghezza massima al 100%. Questo dovrebbe essere cambiato per lo scenario di ciascun utente. Infine, l'intero scopo di pubblicare questa risposta come alternativa è la sua capacità di centrare il contenuto all'interno del div genitore. Questo può essere fatto facilmente aggiungendo gli attributi css alla class div interna come segue:

 .font_fix_inner { position: relative; float: center; top: 50%; -webkit-transform: translateY(-50%); transform: translateY(-50%); } 

Spero che questo abbia aiutato qualcuno!

Dai un’occhiata a questo esempio qui http://codepen.io/LukeXF/pen/yOQWNb , puoi usare una semplice funzione per caricare la pagina e ridimensionare le pagine per far sì che la magia avvenga. Tuttavia, fare attenzione a non ritardare il client da troppe chiamate di funzione. (L’esempio ha un ritardo).

 function resize() { $('.resize').each(function(i, obj) { $(this).css('font-size', '8em'); while ($(this).width() > $(this).parent().width()) { $(this).css('font-size', (parseInt($(this).css('font-size')) - 1) + "px"); } }); }