2014-09-14 11 views
13

Wenn Sie versuchen, Inhalt in einem Container zu zentrieren CSS-Tricks hat eine große Anleitung. Wenn Sie jedoch versuchen, einen Text vertikal zu zentrieren, der nur geringfügig kleiner als sein Container ist, ist eine andere Art der vertikalen Zentrierung von Text möglicherweise vorzuziehen. Statt die gesamte Höhe der Schriftart zu verwenden, würde ich eher auf der x-Höhe der Schriftart (im Grunde der Höhe eines Klein x) Zentrum basierendVertikale Ausrichtung basierend auf x-Höhe

Visual explanation of x-height

Und dieses Beispiel sehen, wo rot basiert auf der gesamte Höhe und grün ist auf der x-Höhe auf Basis

Difference between vertically centering

die einzige Option, die ich mit oben kommen könnte, ist ein Pseudo-Element auf den Text mit der gleichen Höhe wie der Behälter hinzuzufügen und vertikal zu verwenden -Ausrichtung: Mitte dazu.

.pseudo { 
    white-space: nowrap; 
} 

.pseudo:before { 
    content: ''; 
    display: inline-block; 
    vertical-align: middle; 
    height: 100px; 
    width: 0; 
} 

Dies funktioniert, aber leider nur für eine einzige Zeile. Ich habe mich gefragt, ob noch jemand versucht hat, dieses Problem zu lösen, und ob es vielleicht Best Practices gibt, denen man folgen sollte? Ich bin besonders daran interessiert, möglichst wenige "magische" Zahlen zu verwenden und ob es eine gute Lösung für die Multiline-Variante gibt.

Siehe Codepen für ein Beispiel, warum ich es basierend auf der x-Höhe und meine Lösung zentrieren möchte.

+0

jsfiddle Demo - http://jsfiddle.net/u64kwdod/ – Anonymous

+0

Leider, das nicht lösen es. Ich habe ein Bild hinzugefügt, das zeigt, was ich vorhabe. Im grünen Beispiel sehen Sie, dass der Abstand von der Spitze des x-Zeichens zu seinem Container der gleiche ist wie der Abstand von der Unterseite des x-Zeichens zu seinem Container. Im roten Beispiel, das nicht hält (hier hält es für den oberen und unteren Rand der roten Hintergrundfarbe zu seinem Behälter) – ckuijjer

+0

würde ich Anpassungen zu 'line-height' verwenden. Z.B. siehe http://jsfiddle.net/9gdttoyb/ –

Antwort

5

Die differece zwischen Positionstext Zentrum und dem kleinen Buchstaben Zentrum gleich (ascender height - x-height - descender height)/2 (im Grunde müssen wir irgendwie die Abseilgerät Höhe erhöhen, um es zu ascender height - x-height gleich machen die geometrische zu bewegen Mittelpunkt der Linienbox zur Position der kleinen Buchstabenmitte). Von diesen 3 Unbekannten ist nur x-height für CSS verfügbar (über ex Einheit). Andere Schriftmetriken können nicht gelesen werden und bleiben eine Art "magische Zahlen", so dass es nur möglich ist, einen bestimmten Wert für jede spezifische Schriftart auszuwählen. Aber mit dieser "font-specific magic number" können Sie beliebig viele Zeilen zentrieren - indem Sie das innere Element display:inline-block eingeben und das magic value seinem padding-bottom zuweisen.

Es scheint unmöglich zu sein, den benötigten Wert aus den Font-Metriken in reinem CSS zu erhalten. Solche vertical-align Werte wie text-top/text-bottom können die Position von Ascender oder Descender geben, aber nur einer von ihnen, exotische Werte wie sub scheinen völlig willkürlich zu sein, und ich fand keine Möglichkeit, den Unterschied zwischen zwei Font-Metriken für ein Element zu 'messen' .

Mein erfolgreichster Versuch war die Möglichkeit, die Linie (oder Linien) um die Hälfte des benötigten Unterschieds zu verschieben, so dass eine hybride Zentrierung möglich ist (weder Groß- noch Kleinbuchstaben sind genau zentriert, aber 'optisch' kann der Text gleichmäßig aussehen) besser zentriert). Dies kann durch eine anderes Pseudoelement durchgeführt werden hinzugefügt, um die letzte Zeile, die die Höhe der Zeilen-Box hat, aber sein mit dem Zentrum der kleinen Buchstaben ausgerichtet:

.blue:after { 
    content: ':'; /* must contain text to get the auto height of the line box */ 
    display: inline-block; 
    vertical-align: middle; 
    width: 0; /* making pseudo elenent invisible */ 
    overflow: hidden; 
} 

Edited CodePen example mit dem Ergebnis (ich habe nicht verstecken Pseudoelemente zur Visualisierung).

Für die Zentrierung des Inline-Blocks selbst kann jeder Ansatz verwendet werden, ich wähle den Ansatz mit zweitem Helfer-Pseudoelement, das immer 100% Höhe des Containers hat, so dass keine magischen Zahlen mehr benötigt werden.

Hope it :)

+0

Was für eine ausgezeichnete Antwort! Ich habe eine wiederverwendbare CSS-Klasse daraus gemacht: http://Stackoverflow.com/a/35697355/1049693 – pilau

2

Sorry kann nicht kommentieren.

Wie wäre es damit:

.green { 
    color: #6c6; 
    background-color: #cfc; 
    vertical-align: -16%; 
    line-height: 60px; 
} 

http://jsfiddle.net/hcn25psh/3/

und einige Informationen, die helfen könnten:

http://www.w3schools.com/cssref/pr_pos_vertical-align.asp

+0

Das Problem mit diesen Lösungen ist, dass sie alle magische Zahlen verwenden, ich mag nicht einmal meine eigene Option, die Höhe des Pseudoelements auf die Höhe des Elternelements zu setzen. Ich habe wirklich gehofft, dass es eine Lösung gibt, die funktioniert, ohne irgendeine Pixelgröße zu setzen. – ckuijjer

2

Ich glaube, der einzige Weg, um das gewünschte Ergebnis zu erhalten, ist Dinamyc zu verwenden CSS (DCSS).

Zuerst müssen Sie eine Funktion in Ihrer Website erstellen, die die Höhe des Textes (in Kleinbuchstaben) abruft.

Zweitens müssen Sie die CSS mit einer statischen Position ausgeben, die in Wirklichkeit dynamisch ist, da sie von Ihrem dynamischen Code gedruckt wird.

Hier ein Beispiel aus diesem Link eingefügt http://www.phpsnaps.com/snaps/view/get-text-height-width/, wie Sie Ihre Texthöhe in PHP abrufen:

define("F_SIZE", 8); 
define("F_FONT", "arial.ttf"); 


function get_bbox($text){ 
    return imagettfbbox(F_SIZE, 0, F_FONT, $text); 
} 

function text_height ($text) { 
    $box = get_bbox($text); 
    $height = $box[3] - $box[5]; 
    return $height; 
} 

function text_width ($text) { 
    $box = get_bbox($text); 
    $width = $box[4] - $box[6]; 
    return $width; 
} 

Und dann würden Sie (x) HTML mit CSS echo irgendwie so:

echo "<span style=\"YourStyleProperty=" . **Your line height/2 + your text height/2 (Hint: use the PHP or equivalent if other language)** . ";\" 

weitere Informationen über die imagettfbbox Funktion: http://php.net/manual/fr/function.imagettfbbox.php

Fühlen Sie sich frei zu posten, wenn Sie Probleme beim Finalisieren des Codes haben, ich werde froh sein, zu helfen, wenn Sie einige Anstrengungen zeigen :).

Für weitere Informationen über DCSS und vielleicht bessere Ideen/Beispiel zögern Sie nicht, DCSS zu googeln.

+0

Danke für deine Antwort. Obwohl es nicht genau das ist, was ich will (ich sehe es nicht, die x-Höhe abrufend oder berechnend), zeigt es das Denken aus der Schachtel heraus.Vielleicht die beste Lösung wäre zu sehen, ob JavaScript Informationen aus einer Schriftart abrufen kann und wenn ja, ein kleines jQuery-Plugin – ckuijjer

+0

Ich sehe, wenn niemand heute Abend antwortete, wenn ich zurückkomme, werde ich Ihnen einige andere Möglichkeiten zeigen. –

2

verwenden css

.outer { 
    display: table; 
    width: 200px; 
    height: 200px; 
    background-color:blue; 
} 
.inner { 
    display: table-cell; 
    vertical-align: middle; 
    /*You can align center if you want as well*/ 
    /*text-align:center;*/ 
} 
.box { 
    position: relative; 
    display: inline-block; 
    background: orange; 
    color: black; 
    font-size: 60px; 
    background-color: yellow; 
} 

Und dieses Markup verwenden. Was auch immer in der "Box" div ist, wird zentriert. Es ist also nur eine äußere als Tabelle und innere als Zelle fungieren, so dass Sie die vertikale Ausrichtung Mitte für mehrere Zeilen verwenden können.

<div class="outer"> 
    <div class="inner"> 
     <div class="box"> 
      Texty</br> 
      Texty 
     </div> 
    </div> 
</div> 

hier ist ein codepen

+0

Danke für die Antwort, aber das löst es nicht. Dies zentriert es vertikal auf der Grundlage der gesamten Höhe des Textes (die gelbe Hintergrundfarbe) anstelle der x-Höhe des Textes (der Teil des Textes von der Unterseite eines "x" -Zeichens bis zur Spitze eines "x" Zeichen) – ckuijjer

+0

Sie meinen die Kante des "y" und die Kante des "T"? Ich glaube nicht, dass es eine Möglichkeit gibt, das ohne Festcodierung zu tun. Der Raum über dem T ist Teil der Schriftart. Ebenso ist der Abstand zwischen der unteren Kante eines normalen Buchstabens und dem "y" oder "g" –

+0

Ich habe die Frage bearbeitet, um ein Bild hinzuzufügen, das erklärt, was x-height ist. In meinem grünen Beispiel habe ich 'vertical-align: middle' und einen': before'-Text mit fester Höhe verwendet, um zu versuchen, zu lösen. – ckuijjer

1

hilft wahrscheinlich benötigen Sie eine dieser jQuery-Plugins:

  • FlowType: Web Typographie in seiner schönsten Form: font-size und line-height auf Basis von Elementbreite
  • Squishy: Ein Plugin für den Einbau Schriftentext zu seinem Container
  • Responsive Text: Set Schriftgrößen auf seiner Behälterbreite in Reaktion darauf basierend
  • TypeButter: Ermöglicht die optische Kerning für jede Schriftart auf Ihrer Webseite
  • FitText einzustellen: FitText macht Schriftgrößen flexibel
  • SlabText: Eine jQuery-Plugin für die Herstellung von großen, mutigen und reaktions Schlagzeilen
  • Auto Line-Height: Ein jQuery Plugin für flexible Layouts
1

Ilya Streltsyns Antwort (die akzeptierte) ist erstaunlich. Genau das, was ich an CSS mag - wenn Sie die Mechanik gut genug kennen, können Sie alles erreichen.

Ich habe die akzeptierte Antwort in eine wiederverwendbare Klasse verallgemeinert, getestet auf Chrome, Firefox und Edge. Ich habe auch Probleme damit behoben, wie es im Dokumentenfluss sitzt (der Container würde zusätzliche Breite von den ::after Elementen tragen und würde niedriger erscheinen als Geschwisterelemente). Sie können ganz einfach die Klasse wie folgt verwenden:

<any class="x-height"> 
    <span class="x-height"> 
    Centered text 
    </span> 
</any> 

Und unten ist die Sass Quelle (Also check it out on Codepen):

%x-height { 
    content: 'x'; 
    display: inline-block; 
    vertical-align: middle; 
    width: 0; 
} 

.x-height { 
    vertical-align: bottom; 

    &::after { 
    @extend %x-height; 

    content: ''; 
    height: 100%; 
    } 

    > .x-height { 
    display: inline-block; 
    vertical-align: baseline; 
    margin-left: -1ch; 
    margin-right: calc(-1ch/2); 
    white-space: nowrap; 

    @at-root { 
     @-moz-document url-prefix() { 
     & { 
      margin-left: auto; 
      margin-right: auto; 

      &::before { display: none; } 
     } 
     } 
    } 

    &::before, &::after { 
     @extend %x-height; 
     visibility: hidden; 
    } 

    &::after { 
     width: 1ch; 
     margin: 0 -1ch; 
    } 
    } 
}