2017-04-22 3 views
2

Hinweis: Ich möchte keine Schriftgröße basierend auf der Größe des Ansichtsfensters skalieren - meine Frage ist anders.Schriftgröße basierend auf Inhalt skalieren (CSS oder JS)

Meine HTML/CSS/JS-App stellt dem Benutzer im Wesentlichen ein Zustandsdiagramm zur Verfügung. Es gibt eine Nachricht auf dem Bildschirm mit einer Reihe von Tasten. Das Drücken jeder Taste führt zu einem anderen Bildschirm - und so weiter - in der Tat sehr einfache Vorstellung.

Der Text für jeden Bildschirm als jede Schaltfläche stammt aus der Datenbank.

Das Design ist so, dass die Tastengrößen festgelegt sind (ich habe keine Kontrolle darüber). Sie sind groß genug, um so ziemlich alles zu ermöglichen, auf das die Anwendung stoßen kann - auf Englisch.

Kürzlich musste ich Swahili-Unterstützung hinzufügen - und plötzlich wurde etwas, das 2 Wörter, 15 Zeichen in Englisch ist 5 Wörter mit fast 50 Zeichen in Swahili - und es passt nicht in den Knopf. Das ist ziemlich schlecht - und doch gibt es nur eine Handvoll solcher langen Button-Labels. Leider, da sie dynamisch sind (von der DB), kann ich nicht viel in Bezug auf Vorhersagen tun, was es sein wird.

Die Sache, die ich tun kann, ist, die Schriftgröße zu verkleinern, um den Text innerhalb der Taste zu passen. Die Verwendung von vw, vh usw. Einheiten funktioniert nicht, da der Text unabhängig von der Größe des Darstellungsbereichs auf eine feste Größe skaliert werden sollte.

Ich kann mir keine CSS-Lösung vorstellen. Ich kann mir ein paar JS-Lösungen für das Problem vorstellen (z. B. den Text platzieren und dann weiter herunterskalieren, bis es passt - obwohl ich mir nicht ganz sicher bin, wie ich feststellen kann, dass es passt).

Ich kann das nicht einfach herausfinden. Irgendwelche Ideen? Ich bin mit CSS3 und HTML5 zufrieden und benötige dies nur für die neuesten Versionen von Chrome und Safari.

+0

wenn Sie den Text in ein SVG-Element setzen können - https://css-tricks.com/svg-text-typographic-designs/ – Aprillion

+0

@ Aprillion Hm, interessante Idee. Leider unterstützt SVG keinen automatischen Zeilenumbruch. Im Moment erlaubt die Schaltfläche bis zu 3 Textzeilen, automatische Umbruch, vertikal und horizontal zentriert. –

+0

Sind Sie in Ordnung, wenn Sie ein Dummy-Element für Berechnungszwecke verwenden? (Ich kann eine Lösung haben, wenn Sie sind) – treyhakanson

Antwort

0

Schauen Sie sich diese jsbin: http://jsbin.com/sunamej/1/edit?html,css,js,output

der Text skaliert nach einer Berechnung auf einem Dummy-Text Behälter getan mit white-space: nowrap. Dadurch kann die Gesamtbreite des Textes mit der des Buttons verglichen und proportional verkleinert werden. Beachten Sie, dass es einen Fehler gibt, weil nicht berücksichtigt wird, wo die Wörter eingefügt werden. Dies wird weitgehend durch den enthaltenen Fehlerfaktor gemildert, muss aber möglicherweise auf Ihre Anwendung abgestimmt werden. Es wäre mühsam, etwas zu berechnen, um den Ort des Wortumbruchs vollständig zu berücksichtigen, und die Zeit für eine Anwendung wie diese mit nur wenigen Wörtern/Zeilen nicht zu nutzen. Hier ist der Code aus dem Behälter in voller Höhe als auch:

HTML:

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8"> 
    <meta name="viewport" content="width=device-width"> 
    <title>JS Bin</title> 
</head> 
<body> 
    <button class="btn"> 
    <span class="dummy-text"> 
     Testing with some large text that should scale 
    </span> 
    <span class="text"> 
     Testing with some large text that should scale 
    </span> 
    </button> 
    <button class="btn"> 
    <span class="dummy-text"> 
     Testing with some 
    </span> 
    <span class="text"> 
     Testing with some 
    </span> 
    </button> 
    <button class="btn"> 
    <span class="dummy-text"> 
     Testing with some large text 
    </span> 
    <span class="text"> 
     Testing with some large text 
    </span> 
    </button> 
<script src="https://code.jquery.com/jquery-3.1.0.js"></script> 
</body> 
</html> 

CSS:

.btn { 
    /* hardcoded dimens */ 
    height: 35px; 
    width: 75px; 
} 

.dummy-text { 
    /* hide dummy, don't wrap */ 
    display: none; 
    white-space: nowrap; 
} 

Javascript:

console.clear(); 
// NOTE: use of jQuery is arbitrary; all functions 
// are available in vanilla js 

function scaleText(btn) { 
    // select the dummy text 
    var dtxt = btn.find('.dummy-text'); 
    // select the real text 
    var txt = btn.find('.text'); 

    // get te with of the button and the dummy 
    var tw = dtxt.width(); 
    var bw = btn.width(); 

    // number of lines of text the button allows 
    var lines = 2; 
    // factoring in error caused by wrapping; this 
    // may need fine tuning for your application 
    var err = 0.85; 
    // get the fonts scale 
    var scale = (bw * lines * err)/tw; 

    // get the current font size 
    var sz = parseInt(dtxt.css('font-size').replace('px', '')); 
    // scale appropiately 
    txt.css('font-size', sz * scale + 'px'); 
} 

// apply to each button 
var btns = $('.btn'); 
btns.each(function(i, btn) { 
    scaleText($(btn)); 
}); 
+0

Danke, ich werde es mir ansehen. Ich vermute, es wird viel Feinabstimmung nötig sein, da so ziemlich alle langen Texte aus Wörtern bestehen, die nur ein bisschen länger als die halbe Breite sind und zusätzliche Zeilenumbrüche erzwingen. Wenn ich den Text nur basierend auf Zeichen und der Breite der Zeile aufreiße, erhalte ich zwei Zeilen, aber bei richtigen Zeilenumbrüchen bekomme ich vier Zeilen. –

0

Inspiriert von Adjust size of an SVG-element to its content, würde es erfordern mehr Feinabstimmung und eine Möglichkeit, langen Text auf die entsprechende Anzahl von Zeilen zu teilen, möglicherweise mit 01 umwickelnWenn Sie die Breite/Höhe von der Länge des Textes erraten können ...Aber hier ist eine mögliche Start:

[...document.getElementsByTagName("svg")].forEach(svg => { 
 
    const bbox = svg.getBBox(); 
 
    svg.setAttribute("viewBox", [bbox.x, bbox.y, bbox.width, bbox.height].join(" ")); 
 
})
button { 
 
    width: 100px; 
 
    height: 50px; 
 
    padding: 0; 
 
} 
 

 
svg { 
 
    width: 100%; 
 
    height: 100%; 
 
}
<button> 
 
    <svg> 
 
    <text>Short</text> 
 
    </svg> 
 
</button> 
 
<button> 
 
    <svg> 
 
    <text>Longer text</text> 
 
    <text y='1em'>split externally</text> 
 
    <text y='2em'>to balanced lines</text> 
 
    </svg> 
 
</button>

Verwandte Themen