Schriftskalierung basierend auf der Breite des Containers


1187

Es fällt mir schwer, mich mit der Skalierung von Schriftarten zu beschäftigen.

Ich habe derzeit diese Seite mit einem Körper font-sizevon 100%. 100% von was aber? Dies scheint bei 16 Pixeln zu rechnen.

Ich hatte den Eindruck, dass 100% sich irgendwie auf die Größe des Browserfensters beziehen würden, aber anscheinend nicht, weil es immer 16 Pixel sind, ob das Fenster auf eine mobile Breite oder einen ausgewachsenen Breitbild-Desktop verkleinert wird.

Wie kann ich den Text auf meiner Website in Bezug auf den Container skalieren? Ich habe es versucht em, aber das skaliert auch nicht.

Meine Argumentation ist, dass Dinge wie mein Menü beim Ändern der Größe zerquetscht werden, daher muss ich unter anderem die Anzahl px font-sizeder .menuItemElemente in Bezug auf die Breite des Containers reduzieren . (Funktioniert beispielsweise im Menü auf einem großen Desktop 22pxeinwandfrei. Gehen Sie auf die Tablet-Breite und 16pxist besser geeignet.)

Ich bin mir bewusst , ich Haltepunkte hinzufügen kann, aber ich mag wirklich den Text Skala als auch als mit zusätzlichen Haltepunkten, sonst, ich werde mit Hunderten von Breakpoints am Ende für all 100pixels in der Breite zu verringern , den Text zu steuern.


34
font-size: 100%;bedeutet 100% der Größe, die der Text gehabt hätte (dh die, die er von seinem übergeordneten Text geerbt hat). Standardmäßig ist das 16px. Wenn Sie also 50% verwenden würden, wäre es Schriftgröße: 8px
Andy

31
Was Sie suchen, wird als reaktionsfähige Typografie oder Typografie in Ansichtsfenstergröße bezeichnet. css-tricks.com/viewport-sized-typography
gearsdigital


12
@Andy: Eigentlich ist "standardmäßig" das, worauf die Benutzer ihre Browsertextgröße eingestellt haben, die möglicherweise nicht unbedingt auf 16px aufgelöst wird.
ScottS

1
Schauen Sie sich diese Antwort an stackoverflow.com/a/28485608/4251431
Basheer AL-MOMANI

Antworten:


1496

BEARBEITEN: Wenn der Container nicht der Hauptteil ist, deckt CSS Tricks alle Ihre Optionen unter Anpassen von Text an einen Container ab .

Wenn der Container der Körper ist, suchen Sie nach prozentualen Längen des Ansichtsfensters :

Die prozentualen Längen des Ansichtsfensters beziehen sich auf die Größe des anfänglichen enthaltenden Blocks . Wenn die Höhe oder Breite des anfänglich enthaltenen Blocks geändert wird, werden sie entsprechend skaliert. Wenn der Wert für den Überlauf des Stammelements jedoch automatisch ist, wird davon ausgegangen, dass keine Bildlaufleisten vorhanden sind.

Die Werte sind:

  • vw (% der Breite des Ansichtsfensters)
  • vh (% der Ansichtsfensterhöhe)
  • vi (1% der Größe des Ansichtsfensters in Richtung der Inline-Achse des Stammelements)
  • vb (1% der Größe des Ansichtsfensters in Richtung der Blockachse des Stammelements)
  • vmin(der kleinere von vwoder vh)
  • vmax(je größer oder vwoder vh)

1 v * entspricht 1% des anfänglich enthaltenden Blocks.

Die Verwendung sieht folgendermaßen aus:

p {
    font-size: 4vw;
}

Wie Sie sehen können, tun Sie dies mit zunehmender Breite des Ansichtsfensters font-size, ohne Medienabfragen verwenden zu müssen.

Diese Werte sind genau wie pxoder emeine Größeneinheit, sodass sie auch zur Größe anderer Elemente wie Breite, Rand oder Abstand verwendet werden können.

Die Browserunterstützung ist ziemlich gut, aber Sie benötigen wahrscheinlich einen Fallback, wie z.

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

Überprüfen Sie die Support-Statistiken: http://caniuse.com/#feat=viewport-units .

Schauen Sie sich auch CSS-Tricks an, um einen breiteren Überblick zu erhalten : Viewport Sized Typography

Hier ist ein schöner Artikel über das Festlegen von Minimal- / Maximalgrößen und etwas mehr Kontrolle über die Größen: Präzise Kontrolle über reaktionsschnelle Typografie

Und hier ist ein Artikel über das Festlegen Ihrer Größe mit calc (), sodass der Text das Ansichtsfenster ausfüllt: http://codepen.io/CrocoDillon/pen/fBJxu

Lesen Sie auch diesen Artikel, in dem eine Technik verwendet wird, die als "geschmolzenes Führen" bezeichnet wird, um auch die Linienhöhe anzupassen. Geschmolzenes Blei in CSS


547
Was aber, wenn der Container nicht das Ansichtsfenster (Body) ist?
Alex

12
@ Alex, das ist JS Territorium. Probieren Sie die FitText.jsAlternative aus, die am Ende des Artikels @jbenjohnson angegeben ist.
Robbert

10
Hier kommen die sogenannten Elementabfragen ins Spiel. Im Gegensatz zu Medienabfragen würden Elementabfragen die Größe anhand des enthaltenen Blocks und nicht des Ansichtsfensters bestimmen, was erstaunlich wäre! Aber leider existiert es noch nicht. Es gibt jedoch einige Polyfills und Proof-of- Concepts ,
jbenjohnson

139
Herabgestuft, da dies die Frage nicht beantwortet. Er fragte nach dem Container, nicht nach dem Ansichtsfenster. Ganz anderer Anwendungsfall.
SongBox

6
"initialer enthaltender Block" bezieht sich auf das Wurzelelement. Dies ist nicht die richtige Antwort auf die gestellte Frage.
Glyphe

320

Was aber, wenn der Container nicht das Ansichtsfenster (Body) ist?

Diese Frage wird in einem Kommentar von Alex unter der akzeptierten Antwort gestellt .

Diese Tatsache bedeutet nicht, vwdass für diesen Behälter nicht in gewissem Umfang die Größe verwendet werden kann. Um überhaupt eine Variation zu sehen, muss man davon ausgehen, dass der Behälter in irgendeiner Weise flexibel ist. Ob durch einen direkten Prozentsatz widthoder durch 100% minus Margen. Der Punkt wird "streitig", wenn der Container immer auf beispielsweise 200pxbreit eingestellt ist - dann setzen Sie einfach einen font-size, der für diese Breite funktioniert.

Beispiel 1

Bei einem Container mit flexibler Breite muss jedoch erkannt werden, dass der Container in irgendeiner Weise immer noch außerhalb des Ansichtsfensters dimensioniert wird . Daher muss eine vwEinstellung basierend auf dem prozentualen Größenunterschied zum Ansichtsfenster angepasst werden. Dies bedeutet, dass die Größe der übergeordneten Wrapper berücksichtigt wird. Nehmen Sie dieses Beispiel :

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

Angenommen, hier divist das ein Kind von body, ist es 50%von dieser 100%Breite, die in diesem Grundfall die Größe des Ansichtsfensters ist. Grundsätzlich möchten Sie eine festlegen vw, die für Sie gut aussieht. Wie Sie in meinem Kommentar in dem obigen CSS Inhalt sehen können, können Sie „denken“ durch diese mathematisch in Bezug auf die volle Darstellungsgröße, aber Sie nicht brauchen , das zu tun. Der Text wird mit dem Container "gebogen", da sich der Container mit der Größe des Ansichtsfensters biegt. UPDATE: Hier ist ein Beispiel für zwei unterschiedlich große Container .

Beispiel 2

Sie können die Größe des Ansichtsfensters sicherstellen, indem Sie die darauf basierende Berechnung erzwingen. Betrachten Sie dieses Beispiel :

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

Die Größe basiert weiterhin auf dem Ansichtsfenster, wird jedoch im Wesentlichen basierend auf der Containergröße selbst eingerichtet.

Sollte sich die Größe des Containers dynamisch ändern ...

Wenn die Größe des Containerelements seine prozentuale Beziehung entweder über @mediaHaltepunkte oder über JavaScript dynamisch ändern würde, müsste unabhängig von der Basis "Ziel" neu berechnet werden, um dieselbe "Beziehung" für die Textgröße beizubehalten.

Nehmen Sie Beispiel 1 oben. Wenn das durch entweder oder JavaScript divauf 25%Breite umgestellt @mediawurde, font-sizemüsste das gleichzeitig entweder in der Medienabfrage oder durch JavaScript an die neue Berechnung von angepasst werden 5vw * .25 = 1.25. Dies würde die Textgröße auf die gleiche Größe bringen, die sie gewesen wäre, wenn die "Breite" des ursprünglichen 50%Containers gegenüber der Größe des Ansichtsfensters um die Hälfte verringert worden wäre, aber jetzt aufgrund einer Änderung der eigenen prozentualen Berechnung verringert wurde.

Eine Herausforderung

Mit der CSS3 - calc()Funktion in Gebrauch ist , würde es schwierig werden , dynamisch anzupassen, da diese Funktion für nicht funktioniert font-sizeZwecke zu diesem Zeitpunkt. Sie können also keine reine CSS 3-Anpassung vornehmen, wenn sich Ihre Breite ändert calc(). Natürlich reicht eine geringfügige Anpassung der Breite für die Ränder möglicherweise nicht aus, um eine Änderung zu rechtfertigen font-size, sodass dies möglicherweise keine Rolle spielt.


(Es gibt einen Chrome-Fehler mit prozentualen Längen des Ansichtsfensters und der Größenänderung des Fensters: code.google.com/p/chromium/issues/detail?id=124331 )
30.

@thirtydot: Das ist unglücklich (aber gut zu wissen, danke). Ich hoffe, der Fehler wird bald behoben, aber es sieht so aus, als ob er schon seit einiger Zeit besteht.
ScottS

20
Gute Antwort, es funktioniert jedoch nicht, wenn das enthaltende Element eine maximale Breite hat.
Himmators

3
@KristofferNolgren: Das bezieht sich auf zwei Punkte, die in meiner Antwort gemacht wurden: (1) "Unter der Annahme, dass der Container in irgendeiner Weise flexibel in der Größe ist" (sobald 'maximale Breite' erreicht ist, biegt er sich nicht mehr, so dass es dann ein Problem gibt ). (2) Wenn man bestimmen kann, an welchem ​​Punkt 'maximale Breite' erreicht werden würde, könnten Sie, wie bereits erwähnt, einen @mediaHaltepunkt festlegen , um die Schriftgröße an diesem Punkt zu ändern (im Wesentlichen eine feste Größe beim Erreichen max-width). . Nur ein Gedanke, um mit einer max-widthSituation zu arbeiten.
ScottS

Denken Sie, Sie können eine Frage stellen, wann sich das Containerelement durch Medienabfragen dynamisch ändert? Ich bin mir nicht sicher ob ich das verstehe.
J82

59

Lösung mit 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/


Lösung mit SVG und Textumbruch mit 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
Diese Idee sieht zunächst gut aus. Dann stellen Sie fest, dass Sie die Schriftart in SVG in <html> nicht einfach steuern können. Die Schriftart ist auf Mobilgeräten und Desktops unterschiedlich, was sich auf die endgültige Breite auswirkt.
Stopi

@Stopi Was denkst du über eine iFrame-Lösung? Beispiel
Dantio

10
Sie können SVG vollständig aus HTML / CSS
gman

1
SVG kann mit CSS gestaltet werden, wenn das SVG inline ist (verwenden Sie kein IMG-Tag).

8
Dies ist die beste und vorhersehbarste Lösung, die basierend auf einem dynamischen Container skaliert.
Joshua David

35

In einem meiner Projekte verwende ich eine "Mischung" zwischen vw und vh, um die Schriftgröße an meine Bedürfnisse anzupassen, zum Beispiel:

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

Ich weiß, dass dies die Frage des OP nicht beantwortet, aber vielleicht kann es eine Lösung für jeden anderen sein.


3
Möglicherweise ist es besser, wenn Sie vminund / oder vmaxstattdessen verwenden.
sebastian_k

4
Chrome Dev Tools nennt dies einen ungültigen Eigenschaftswert
Phil294

31

Pure-CSS-Lösung mit calc()CSS-Einheiten und Mathematik

Dies ist genau nicht das, was OP verlangt, aber es kann jemandes Tag machen. Diese Antwort ist nicht einfach zu füttern und erfordert einige Nachforschungen auf Entwicklerseite.

Ich bin endlich gekommen, um eine reine CSS-Lösung dafür calc()mit verschiedenen Einheiten zu bekommen. Sie benötigen ein grundlegendes mathematisches Verständnis der Formeln, um Ihren Ausdruck für zu erarbeiten calc().

Als ich das herausgefunden habe, musste ich einen reaktionsschnellen Header mit voller Seitenbreite erhalten, in dem einige Eltern in DOM aufgefüllt waren. Ich werde meine Werte hier verwenden und durch Ihre eigenen ersetzen.

Zur Mathematik

Du wirst brauchen:

  • Schön angepasstes Verhältnis in einigen Ansichtsfenstern. Ich habe 320 Pixel verwendet, also 24 Pixel hoch und 224 Pixel breit, also beträgt das Verhältnis 9,333 ... oder 28/3
  • Die Containerbreite hatte ich padding: 3emund die volle Breite damit das ging100wv - 2 * 3em

X ist die Breite des Containers. Ersetzen Sie ihn also durch Ihren eigenen Ausdruck oder passen Sie den Wert an, um ganzseitigen Text zu erhalten. Rist das Verhältnis, das Sie haben werden. Sie können es erhalten, indem Sie die Werte in einem Ansichtsfenster anpassen, die Breite und Höhe der Elemente überprüfen und durch Ihre eigenen Werte ersetzen. Auch ist es width / heigth;)

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

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

Und Knall! Es funktionierte! Ich hab geschrieben

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

zu meinem Header und es hat sich in jedem Ansichtsfenster gut angepasst.

Aber wie geht das?

Wir brauchen hier oben einige Konstanten. 100vwbedeutet die volle Breite des Ansichtsfensters, und mein Ziel war es, einen Header in voller Breite mit etwas Polsterung zu erstellen.

Das Verhältnis. Durch das Abrufen einer Breite und Höhe in einem Ansichtsfenster konnte ich mit einem Verhältnis spielen, und mit dem Verhältnis weiß ich, wie hoch die Höhe in einem anderen Ansichtsfenster sein sollte. Das Berechnen mit der Hand würde viel Zeit und zumindest viel Bandbreite in Anspruch nehmen, daher ist dies keine gute Antwort.

Fazit

Ich frage mich, warum niemand das herausgefunden hat und einige Leute sagen sogar, dass es unmöglich wäre, an CSS zu basteln. Ich verwende JavaScript nicht gerne zum Anpassen von Elementen, daher akzeptiere ich keine JavaScript-Antworten (und vergesse jQuery), ohne mehr zu graben. Alles in allem ist es gut, dass dies herausgefunden wurde und dies ein Schritt zu reinen CSS-Implementierungen im Website-Design ist.

Ich entschuldige mich für ungewöhnliche Konventionen in meinem Text, bin kein englischer Muttersprachler und auch ziemlich neu im Schreiben von Stack Overflow-Antworten.

Es sollte auch beachtet werden, dass wir in einigen Browsern böse Bildlaufleisten haben. Bei der Verwendung von Firefox ist mir beispielsweise aufgefallen, dass sich 100vwdie gesamte Breite des Ansichtsfensters unter der Bildlaufleiste erstreckt (wo der Inhalt nicht erweitert werden kann!). Daher muss der Text in voller Breite sorgfältig begrenzt und vorzugsweise mit vielen Browsern und Geräten getestet werden.


13
Diese Lösung funktioniert nur, wenn (1) Sie die Schriftart kennen, (2) die Schriftart auf dem Gerät eines Benutzers verfügbar ist und (3) der Text immer der gleiche ist. Dies macht es zu einem sehr begrenzten Anwendungsfall.
Andrei Volgin

Ich verstehe nicht, was passiert, wenn mein Container zum Beispiel mit 640px und einem Verhältnis von 16: 9 repariert ist. Welche Berechnungen sollte ich schreiben?
Pery Mimon

1
Ihre Containerbreite xbeträgt 640px und das Verhältnis r16: 9, also: x = 640px, r = 16 / 9, y = x / r = 640px / (16 / 9) = 360px
hegez

Hinweis: Dies funktioniert nur, wenn Sie tatsächlich einen Text mit einer Größe von 16: 9 haben, was eine seltsame Situation ist. Vielleicht hilft es, die Antwort zum zweiten Mal zu lesen. Dies funktioniert auch nur für Einzeiler.
Hegez

Um ehrlich zu sein, erklären Sie nicht "Schön angepasstes Verhältnis in einigen Ansichtsfenstern. Ich habe 320 Pixel verwendet, also 24 Pixel hoch und 224 Pixel breit, also ist das Verhältnis 9,333 ... oder 28/3". Ich schlage vor, das Verhältnis zu erklären ein bisschen mehr. Was bedeutet das Verhältnis?
3limin4t0r

28

Für dieses Problem gibt es eine große Philosophie.

Am einfachsten wäre es, dem Körper eine bestimmte Schriftgröße zu geben (ich empfehle 10), und dann hätten alle anderen Elemente ihre Schrift in emoder rem. Ich gebe Ihnen ein Beispiel, um diese Einheiten zu verstehen. Emist immer relativ zu seinem Elternteil:

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 ist immer relativ zum Körper:

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

Und dann könnten Sie ein Skript erstellen, das die Schriftgröße relativ zu Ihrer Containerbreite ändert. Aber das würde ich nicht empfehlen. Denn in einem Container pmit einer Breite von 900 Pixel hätten Sie beispielsweise ein Element mit einer Schriftgröße von 12 Pixel. Und nach Ihrer Vorstellung würde dies zu einem 300 Pixel breiten Container mit einer Schriftgröße von 4 Pixel. Es muss eine Untergrenze geben.

Andere Lösungen wären Medienabfragen, sodass Sie die Schriftart für unterschiedliche Breiten festlegen können.

Ich würde jedoch empfehlen, eine JavaScript-Bibliothek zu verwenden, die Ihnen dabei hilft. Und fittext.js , die ich bisher gefunden habe.


6
Die remEinheit ist relativ zum Wurzelelement, dh das htmlElement, nicht das bodyElement. Das Stammelement im DOM ist das htmlTag. developer.mozilla.org/en-US/docs/Web/CSS/length .. remist immer relativ zum htmlTag, das das Wurzelelement ist, nicht das Body-Tag .. aber eine gute Antwort :)
Jonathan Marzullo

fittext.js erledigt die Arbeit, ich habe diese Lösung empfohlen!
Jacek Dziurdzikowski

FitText war der Gewinner für mich. Versuchte ein paar Alternativen, aber dies schien die einfachste und auch gut in Drupal / Backdrop CMS integriert. github.com/davatron5000/FitText.js
Hilfs Joel

23

Hier ist die Funktion:

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

Konvertieren Sie dann alle untergeordneten Schriftgrößen Ihrer Dokumente in em'oder %.

Fügen Sie dann Ihrem Code so etwas hinzu, um die Basisschriftgröße festzulegen.

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

http://jsfiddle.net/0tpvccjt/


1
Bisher ist dies die beste Lösung.
Kurz

Schlechte Praktiken und stark ineffizient
Jack Giffin

@tntrox So ineffizient es heute ist, es war vor 4 Jahren viel ineffizienter. Ich lehne diese Antwort anstelle von viel besseren Alternativen ab. Ja, für die IE-Unterstützung würde man Javascript benötigen. Aber man braucht kein so schreckliches Javascript.
Jack Giffin

3
Ich denke, meine Unwissenheit zeigt sich hier. Aber warum ist das oben genannte schrecklich?

Ich finde es nicht schrecklich. Ich würde einige kleinere Formatierungsänderungen empfehlen, um die Lesbarkeit zu verbessern. Ich würde jede Variable zumindest in eine separate Zeile setzen. Möglicherweise ist dies return thisam Ende der Funktion nicht erforderlich . Für die Leistung möchten Sie möglicherweise auch die Onresize entprellen, damit sie beim Ziehen nicht neu gezeichnet wird. Es ist ein ziemlich einfacher Code, sodass jemand seine verbesserte Lösung mit geringem Aufwand darauf aufbauen kann.
Mnebuerquo

19

Es gibt eine Möglichkeit, dies ohne JavaScript zu tun !

Sie können ein Inline-SVG-Bild verwenden. Sie können CSS in einem SVG verwenden, wenn es inline ist. Sie müssen sich daran erinnern, dass bei Verwendung dieser Methode Ihr SVG-Bild auf seine Containergröße reagiert.

Versuchen Sie es mit der folgenden Lösung ...

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

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

Willst du etwas auffälligeres?

Mit SVG-Bildern können Sie auch coole Sachen mit Formen und Müll machen. Schauen Sie sich diesen großartigen Anwendungsfall für skalierbaren Text an ...

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


4
Diese Lösung unterscheidet sich nicht von der akzeptierten mit vwDimensionierung. Wenn Sie den Text ändern, wird alles ungebunden.
N69S

14

Dies ist möglicherweise nicht besonders praktisch, aber wenn Sie möchten, dass eine Schriftart eine direkte Funktion des übergeordneten Zeichens ist, ohne dass JavaScript zum Ablesen der Schleife (Intervall) zum Lesen der Größe von div / page vorhanden ist, gibt es eine Möglichkeit, dies zu tun . Iframes.

Alles innerhalb des Iframes berücksichtigt die Größe des Iframes als die Größe des Ansichtsfensters. Der Trick besteht also darin, einfach einen Iframe zu erstellen, dessen Breite die maximale Breite ist, die Ihr Text haben soll, und deren Höhe der maximalen Höhe * des Seitenverhältnisses des jeweiligen Textes entspricht.

Abgesehen von der Einschränkung, dass Ansichtsfenster-Einheiten nicht auch neben übergeordneten Einheiten für Text stehen können (wie in, wenn sich die% -Größe wie alle anderen verhält), bieten Ansichtsfenster-Einheiten ein sehr leistungsfähiges Werkzeug: Sie können die minimale / maximale Dimension ermitteln . Sie können das nirgendwo anders tun - Sie können nicht sagen ... machen Sie die Höhe dieses Divs zur Breite des übergeordneten * etwas.

Abgesehen davon besteht der Trick darin, vmin zu verwenden und die Iframe-Größe so einzustellen, dass [Bruch] * Gesamthöhe eine gute Schriftgröße ist, wenn die Höhe die Grenzabmessung ist, und [Bruch] * Gesamtbreite, wenn die Breite die ist Grenzmaß. Deshalb muss die Höhe ein Produkt aus Breite und Seitenverhältnis sein.

Für mein spezielles Beispiel haben Sie

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

Das kleine Ärgernis bei dieser Methode ist, dass Sie das CSS des Iframes manuell einstellen müssen. Wenn Sie die gesamte CSS-Datei anhängen, würde dies für viele Textbereiche viel Bandbreite beanspruchen. Ich füge also die gewünschte Regel direkt aus meinem CSS hinzu.

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

Sie können eine kleine Funktion schreiben, die die CSS-Regel / alle CSS-Regeln abruft, die sich auf den Textbereich auswirken würden.

Ich kann mir keinen anderen Weg vorstellen, dies zu tun, ohne JavaScript zum Radfahren / Hören zu haben. Die eigentliche Lösung wäre, dass Browser eine Möglichkeit bieten, Text als Funktion des übergeordneten Containers zu skalieren und dieselbe Funktionalität vom Typ vmin / vmax bereitzustellen.

JSFiddle: https://jsfiddle.net/0jr7rrgm/3/ (Klicken Sie einmal, um das rote Quadrat für die Maus zu sperren, und klicken Sie erneut, um es freizugeben.)

Der größte Teil des JavaScript in der Geige ist nur meine benutzerdefinierte Click-Drag-Funktion.


@quemeful Nicht so, wenn wir das Attribut 'neu' und 'glänzend' (Trommelwirbel bitte ...) einbringensrcdoc : jsfiddle.net/wauzgob6/3
Jack Giffin

9

Mit vw, em& co. funktioniert sicher, aber IMO braucht es immer eine menschliche Note für die Feinabstimmung.

Hier ist ein Skript, das ich gerade basierend auf der Antwort von @ tnt-rox geschrieben habe und das versucht, die Berührung dieses Menschen zu automatisieren:

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

Grundsätzlich wird die Schriftgröße auf 1em0,1 reduziert und dann um 0,1 erhöht, bis die maximale Breite erreicht ist.

JSFiddle


1
+1 nur für jemanden, der anerkennt, emsdass eine menschliche Berührung und ein vertikaler Rhythmus erforderlich sind, ist keine Art von Zauberei.
Serraosays

7

100% ist relativ zur Basisschriftgröße, die, wenn Sie sie nicht festgelegt haben, die Standardeinstellung des Benutzeragenten des Browsers ist.

Um den gewünschten Effekt zu erzielen, würde ich einen Teil des JavaScript-Codes verwenden, um die Basisschriftgröße relativ zu den Fensterabmessungen anzupassen.


7

Fügen Sie dies in Ihrem CSS unten hinzu und ändern Sie die Breite von 320 Pixel, wenn Ihr Design zu brechen beginnt:

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

        body { font-size: 1em; }

    }

Geben Sie dann die Schriftgröße in "px" oder "em" ein, wie Sie möchten.


7

Meine eigene Lösung, jQuery-basiert, erhöht die Schriftgröße schrittweise, bis der Container eine große Erhöhung der Höhe aufweist (was bedeutet, dass er einen Zeilenumbruch aufweist).

Es ist ziemlich einfach, funktioniert aber ziemlich gut und ist sehr einfach zu bedienen. Sie müssen nichts über die verwendete Schriftart wissen , alles wird vom Browser erledigt.

Sie können damit auf http://jsfiddle.net/tubededentifrice/u5y15d0L/2/ spielen.

Die Magie passiert hier:

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
Da dieses Skript bei jedem Größenänderungsereignis und / oder bei jeder Änderung der Ausrichtung ausgeführt wird, empfehle ich die Verwendung dieses Skripts nicht. Anstatt eine Javascript-basierte Lösung zu verwenden, suchen Sie nach einer CSS-basierten Lösung wie oben angegeben.
Pilatus

1
Größenänderung und Orientierungsänderungen sind "seltene" Ereignisse. Hier gibt es keine Leistungsprobleme. Wenn Sie es vorziehen, binden Sie nicht an die Ereignisse (wenn die Größe der Container nicht geändert wird, z. B. für nicht reagierende Websites). CSS-Lösungen funktionieren nicht in allen Fällen, ohne an irgendetwas denken zu müssen (wie die Breite der Schriftart oder so), wie dies bei dieser Lösung der Fall ist.
Vincent

Ich habe Ihre Antwort als jQuery-Funktion verpackt. Es erhält die maximal zulässige Höhe, die minimale und die maximale Schriftgröße. Siehe jsfiddle.net/oriadam/qzsy760k
oriadam

6

Diese Webkomponente ändert die Schriftgröße so, dass die innere Textbreite mit der Containerbreite übereinstimmt. Überprüfen Sie die Demo .

Sie können es so verwenden:

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


6

Ich habe eine einfache Skalierungsfunktion mit CSS-Transformation anstelle der Schriftgröße vorbereitet. Sie können es in jedem Container verwenden, Sie müssen keine Medienabfragen usw. festlegen :) :)

Blog-Beitrag: Skalierbarer CSS & JS-Header in voller Breite

Der Code:

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

Arbeitsdemo: https://codepen.io/maciejkorsan/pen/BWLryj


Ich denke, dass OP nach einer CSS-Lösung sucht.
m02ph3u5

5

Verwenden Sie CSS-Variablen

Bisher hat noch niemand CSS-Variablen erwähnt, und dieser Ansatz hat für mich am besten funktioniert.

max-widthAngenommen, Sie haben eine Spalte auf Ihrer Seite, die 100% der Breite des Bildschirms eines mobilen Benutzers entspricht, aber eine Größe von 800 Pixel hat. Auf dem Desktop ist also auf beiden Seiten der Spalte etwas Platz. Fügen Sie dies oben auf Ihrer Seite ein:

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

Und jetzt können Sie diese Variable (anstelle der integrierten vwEinheit) verwenden, um die Größe Ihrer Schriftart festzulegen. Z.B

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

Es ist kein reiner CSS-Ansatz, aber es ist ziemlich nah.


5

Versuchen Sie es mit http://simplefocus.com/flowtype/ . Dies ist, was ich für meine Websites verwende, und es hat perfekt funktioniert.


Links sind volatil. Bitte erläutern Sie die Lösung direkt in Ihrer Antwort. Außerdem möchte ich nicht auf einen zufälligen Link mit irgendeinem Inhalt klicken.
Lilalinux

5

Mein Problem war ähnlich, bezog sich jedoch auf das Skalieren von Text innerhalb einer Überschrift. Ich habe Fit Font ausprobiert, musste aber den Kompressor umschalten, um Ergebnisse zu erzielen, da er ein etwas anderes Problem löste, ebenso wie Text Flow.

Also habe ich mein eigenes kleines Plugin geschrieben, das die Schriftgröße reduziert hat, um sie an den Container anzupassen, vorausgesetzt, Sie haben es overflow: hiddenund white-space: nowrapdamit, selbst wenn die Schrift auf das Minimum reduziert wird, nicht die vollständige Überschrift angezeigt wird, wird nur abgeschnitten, was angezeigt werden kann.

(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

Künstlerisch gesehen haben Sie nette Optionen, wenn Sie zwei oder mehr Textzeilen unabhängig von der Anzahl der Zeichen in derselben Breite einfügen müssen.

Es ist am besten, eine dynamische Lösung zu finden, damit jeder eingegebene Text eine schöne Anzeige ergibt.

Mal sehen, wie wir uns nähern können.

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>

Alles, was wir tun, ist, die Breite ( els[0].clientWidth) und die Schriftgröße ( parseFloat(window.getComputedStyle(els[0],null).getPropertyValue("font-size"))) der ersten Zeile als Referenz zu erhalten und dann einfach die Schriftgröße der nachfolgenden Zeilen entsprechend zu berechnen.


4

Versuchen Sie, das fitText- Plugin zu verwenden, da Viewport-Größen nicht die Lösung für dieses Problem sind.

Fügen Sie einfach die Bibliothek hinzu:

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

Ändern Sie die Schriftgröße, um den Textkoeffizienten zu korrigieren:

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

Sie können maximale und minimale Textwerte festlegen:

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

Dies ist nur für Text mit großer Anzeige nützlich und wird für Absätze nicht empfohlen.
Shiv

3

Schau dir meinen Code an. Es macht das font size smallerzu fitwas auch immer da.

Aber ich denke, das führt nicht zu einer guten Benutzererfahrung

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

Ergebnis


2

Als JavaScript-Fallback (oder als einzige Lösung) können Sie mein jQuery Scalem-Plugin verwenden , mit dem Sie durch Übergeben der referenceOption relativ zum übergeordneten Element (Container) skalieren können .


2

Falls es für jemanden hilfreich ist, haben die meisten Lösungen in diesem Thread Text in mehrere Zeilen, z.

Aber dann habe ich das gefunden und es hat funktioniert:

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

Anwendungsbeispiel:

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


2

Haben Sie immer Ihr Element mit diesem Attribut:

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

oder

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

Wenn Sie Vollbild zu gehen, sollten Sie bereits haben Skala Variable berechnet (Skala> 1 oder Skala = 1). Dann im Vollbildmodus:

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

Es funktioniert gut mit wenig Code.


2

Für dynamischen Text ist dieses Plugin sehr nützlich:

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

Fügen Sie einfach CSS hinzu:

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

Und das Drehbuch:

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

2

Das hat bei mir funktioniert:

Ich versuche, die Schriftgröße basierend auf einer Breite / Höhe zu approximieren, die sich aus der Einstellung "Schriftgröße: 10px" ergibt. Grundsätzlich lautet die Idee: "Wenn ich eine Breite von 20 Pixel und eine Höhe von 11 Pixel mit einer Schriftgröße von 10 Pixel habe, wie hoch wäre dann die maximale Schriftgröße, um einen Container mit einer Breite von 50 Pixel und einer Höhe von 30 Pixel zu berechnen?"

Die Antwort ist ein Doppelproportionssystem:

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

Jetzt ist X eine Schriftgröße, die der Breite entspricht, und Y ist eine Schriftgröße, die der Höhe entspricht. nimm den kleinsten Wert

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

Hinweis: Das Argument der Funktion muss ein span-Element oder ein Element sein, das kleiner als das übergeordnete Element ist. Andernfalls schlägt fehl, wenn untergeordnete Elemente und übergeordnete Elemente dieselbe Funktion für Breite / Höhe haben.


1

Ich sehe keine Antwort in Bezug auf die CSS-Flex-Eigenschaft, aber es kann auch sehr nützlich sein.


2
Können Sie das näher erläutern?
Peter Mortensen

1

Um die Schriftgröße an den Container und nicht an das Fenster anzupassen, lesen Sie die resizeFont()Funktion, die ich in dieser Frage geteilt habe (eine Kombination anderer Antworten, von denen die meisten bereits hier verlinkt sind). Es wird ausgelöst mit window.addEventListener('resize', resizeFont);.

Vanilla JavaScript: Passen Sie die Schriftgröße an den Container an

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

Sie können möglicherweise vw / vh als Fallback verwenden, sodass Sie mithilfe von JavaScript dynamisch emoder remEinheiten zuweisen oder sicherstellen, dass die Schriftarten auf das Fenster skaliert werden, wenn JavaScript deaktiviert ist.

Wenden Sie die .resizeKlasse auf alle Elemente an, die Text enthalten, den Sie skalieren möchten.

Lösen Sie die Funktion aus, bevor Sie den Ereignis-Listener zum Ändern der Fenstergröße hinzufügen. Dann wird jeder Text, der nicht in den Container passt, beim Laden der Seite sowie bei der Größenänderung verkleinert.

HINWEIS: Die Standardeinstellung font-sizemuss entweder eingestellt werden em, remoder die %richtigen Ergebnisse zu erzielen.


1

HTML

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

JavaScript-Code zur Maximierung der Schriftgröße:

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`;
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.