it-swarm.com.de

CSS: Etwas Text wird ohne Änderung der Containergröße angezeigt

Ich habe ein horizontales Navigationsmenü, das im Grunde nur ein <ul> ist und die Elemente nebeneinander gesetzt sind. Ich definiere keine Breite, sondern verwende einfach das Auffüllen, weil ich möchte, dass die Breite durch die Breite des Menüelements definiert wird. Ich mache das aktuell ausgewählte Element fett.

Das Problem ist, dass das Wort bei Fettdruck etwas breiter wird, was dazu führt, dass sich die restlichen Elemente leicht nach links oder rechts verschieben. Gibt es eine clevere Möglichkeit, dies zu verhindern? Etwas in der Richtung, dass die Polsterung die zusätzliche Breite ignoriert, die durch die Fettung verursacht wird? Mein erster Gedanke war, einfach ein paar Pixel von der Auffüllung des "aktiven" Elements abzuziehen, aber diese Menge variiert.

Wenn möglich, möchte ich vermeiden, eine statische Breite für jeden Eintrag festzulegen und dann im Gegensatz zu meiner aktuellen Padding-Lösung zu zentrieren, um zukünftige Änderungen an den Einträgen einfach vorzunehmen.

68
Mala

Ich hatte das gleiche Problem, bekam aber mit einem kleinen Kompromiss einen ähnlichen Effekt, ich verwendete stattdessen Text-Schatten. 

li:hover {text-shadow:0px 0px 1px black;}

Hier ist ein Arbeitsbeispiel:

body {
  font-family: segoe ui;
}

ul li {
  display: inline-block;
  border-left: 1px solid silver;
  padding: 5px
}

.textshadow :hover {
  text-shadow: 0px 0px 1px black;
}

.textshadow-alt :hover {
  text-shadow: 1px 0px 0px black;
}

.bold :hover {
  font-weight: bold;
}
<ul class="textshadow">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li><code>text-shadow: 0px 0px 1px black;</code></li>
</ul>

<ul class="textshadow-alt">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li><code>text-shadow: 1px 0px 0px black;</code></li>
</ul>

<ul class="bold">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li><code>font-weight: bold;</code></li>
</ul>

jsfiddle Beispiel

111
Thorgeir

Die beste Arbeitslösung mit :: after

HTML

<li title="EXAMPLE TEXT">
  EXAMPLE TEXT
</li>

CSS

li::after {
  display: block;
  content: attr(title);
  font-weight: bold;
  height: 1px;
  color: transparent;
  overflow: hidden;
  visibility: hidden;
}

Es fügt ein unsichtbares Pseudoelement mit der Breite des fetten Textes hinzu, das vom title-Attribut stammt.

Die text-shadow-Lösung sieht auf dem Mac unnatürlich aus und nutzt nicht die ganze Schönheit, die das Text-Rendering auf dem Mac bietet .. :)

http://jsfiddle.net/85LbG/

Gutschrift: https://stackoverflow.com/a/20249560/5061744

Die tragbarste und visuell ansprechendste Lösung wäre die Verwendung von text-shadow . Dies wird überarbeitet und zeigt Beispiele für Thorgeirs Antwort unter Verwendung von Alexxalis und meine eigenen Optimierungen:

  li:hover { text-shadow: -0.06ex 0 black, 0.06ex 0 black; }

Auf diese Weise werden auf beiden Seiten jedes Buchstabens winzige "Schatten" in Schwarz angezeigt (verwenden Sie ggf. den Farbnamen/-code Ihrer Schriftart anstelle von black). Verwenden Sie dabei Einheiten, die mit der Schriftwiedergabe richtig skaliert werden.

warning  Warnung: px-Werte unterstützen Dezimalwerte, sehen jedoch nicht so gut aus, wenn sich die Schriftgröße ändert (z. B. wenn der Benutzer die Ansicht mit skaliert) Ctrl++). Verwenden Sie stattdessen relative Werte.

Diese Antwort verwendet Bruchteile von ex Einheiten, da sie mit der Schriftart skaliert werden.
In den meisten Browserstandards * , erwarte 1ex8px und damit 0.025ex0.1px.

Überzeugen Sie sich selbst:

li             { color: #000; } /* set text color just in case */
.shadow0       { text-shadow: inherit; }
.shadow2       { text-shadow: -0.02ex 0 #000, 0.02ex 0 #000; }
.shadow4       { text-shadow: -0.04ex 0 #000, 0.04ex 0 #000; }
.shadow6       { text-shadow: -0.06ex 0 #000, 0.06ex 0 #000; }
.shadow8       { text-shadow: -0.08ex 0 #000, 0.08ex 0 #000; }
.bold          { font-weight: bold; }
.bolder        { font-weight: bolder; }
.after span        { display:inline-block; font-weight: bold; } /* workaholic… */
.after:hover span  { font-weight:normal; }
.after span::after { content: attr(title); font-weight: bold; display:block; 
                     height: 0; overflow: hidden; }
.ltrsp         { letter-spacing:0; font-weight:bold; } /* @cgTag */
li.ltrsp:hover { letter-spacing:0.0125ex; }
li:hover       { font-weight: normal!important; text-shadow: none!important; }
<li class="shadow0">MmmIii123 This line tests shadow0 (plain)</li>
<li class="shadow2">MmmIii123 This line tests shadow2 (0.02ex)</li>
<li class="shadow4">MmmIii123 This line tests shadow4 (0.04ex)</li>
<li class="shadow6">MmmIii123 This line tests shadow6 (0.06ex)</li>
<li class="shadow8">MmmIii123 This line tests shadow8 (0.08ex)</li>
<li class="after"><span title="MmmIii123 This line tests [title]"
                   >MmmIii123 This line tests [title]</span> (@workaholic…)</li>
<li class="ltrsp"  >MmmIii123 This line tests ltrsp (@cgTag)</li>
<li class="bold"   >MmmIii123 This line tests bold</li>
<li class="bolder" >MmmIii123 This line tests bolder</li>
<li class="shadow2 bold">MmmIii123 This line tests shadow2 (0.02ex) + bold</li>
<li class="shadow4 bold">MmmIii123 This line tests shadow4 (0.04ex) + bold</li>
<li class="shadow6 bold">MmmIii123 This line tests shadow6 (0.06ex) + bold</li>
<li class="shadow8 bold">MmmIii123 This line tests shadow8 (0.08ex) + bold</li>

Bewegen Sie den Mauszeiger über die gerenderten Linien, um zu sehen, wie sie sich vom Standardtext unterscheiden.

Ändern Sie die Zoomstufe Ihres Browsers (Ctrl++ und Ctrl+-) um zu sehen, wie sie variieren.

Ich habe hier zum Vergleich zwei andere Lösungen hinzugefügt: @ cgTags Buchstabenabstandstrick , was nicht so gut funktioniert, da es darum geht, Schriftbreitenbereiche zu erraten, und @ workaholic_gangster911s :: nach dem Zeichnen , was unangenehmen zusätzlichen Platz lässt, so dass der fette Text erweitert werden kann, ohne benachbarte Textelemente anzustoßen (ich setze die Attribution nach dem fetten Text, damit Sie sehen können, wie er sich nicht bewegt).


In Zukunft werden wir mehr variable Schriftarten haben, die in der Lage sind, die Schriftgradstufe über font-variation-settings zu ändern. Browser-Unterstützung läuft an (Chrome 63+, Firefox 62+), aber dies erfordert immer noch mehr als nur Standard-Schriftarten, und nur wenige vorhandene Schriftarten unterstützen dies.

Wenn Sie eine variable Schriftart einbetten, können Sie CSS folgendermaßen verwenden:

/* Grade: Increase the typeface's relative weight/density */
@supports (font-variation-settings: 'GRAD' 150) {
  li:hover { font-variation-settings: 'GRAD' 150; }
}
/* Failover for older browsers: tiny shadows at right & left of the text
 * (replace both instances of "black" with the font color) */
@supports not (font-variation-settings: 'GRAD' 150) {
  li:hover { text-shadow: -0.06ex 0 black, 0.06ex 0 black; }
}

Es gibt eine Live-Demo mit einem Schieberegler zum Spielen mit verschiedenen Klassen im Mozilla-Handbuch für variable Schriftarten. Googles Einführung in variable Schriftarten im Web hat ein animiertes GIF, das einen Wechsel zwischen einer hohen und keiner Note demonstriert:

animated Amstelvar Alpha font demo with toggling grade axis

21
Adam Katz

Ich habe festgestellt, dass die meisten Schriftarten dieselbe Größe haben, wenn Sie den Buchstabenabstand um 1 Pixel anpassen.

a {
   letter-spacing: 1px;
}

a:hover {
   font-weight: bold;
   letter-spacing: 0px;
}

Ändern Sie dabei zwar die reguläre Schrift, sodass jeder Buchstabe einen zusätzlichen Pixelabstand hat. Für Menüs sind die Titel so kurz, dass sie kein Problem darstellen.

14
cgTag

Leider lässt sich die Breite nur ändern, wenn der Text fett dargestellt wird, indem die Breite des Listenelements festgelegt wird. Wie Sie jedoch bereits sagten, ist dies manuell zeitaufwändig und nicht skalierbar.

Das einzige, was mir einfällt, ist die Verwendung von Javascript, das die Breite des Tabs berechnet, bevor es fett ist, und dann die Breite zum selben Zeitpunkt anwendet, zu dem der Fettdruck erforderlich ist (entweder beim Schweben oder Klicken).

3
ajcw

Für eine aktuellere Antwort können Sie -webkit-text-stroke-width verwenden:

.element {
  font-weight: normal;
}

.element:hover {
  -webkit-text-stroke-width: 1px;
  -webkit-text-stroke-color: black;
}

Dies vermeidet Pseudoelemente (was für Bildschirmleser von Vorteil ist) und Textschatten (die unordentlich aussehen und dennoch einen leichten "Sprung" -Effekt hervorrufen können) oder das Festlegen fester Breiten (was unpraktisch sein kann).

Außerdem können Sie ein Element so einstellen, dass es kühner als 1 Pixel ist (theoretisch können Sie eine Schriftart so fett machen, wie Sie möchten, und es kann auch ein schäbiges Training sein, um eine fette Version einer Schriftart zu erstellen, die nicht fett ist Variante, wie benutzerdefinierte Schriftarten. Dies sollte jedoch vermieden werden, da dadurch wahrscheinlich einige Schriftarten kratzig und zackig erscheinen.)

Das funktioniert definitiv in den neuesten Versionen von Edge, Firefox, Chrome und Opera. Ich gehe davon aus, dass es in Safari funktioniert (Opera ist normalerweise ein gutes Barometer dafür), obwohl ich es nicht in Safari getestet habe. Es funktioniert NICHT in IE11 oder darunter.

Beachten Sie auch, dass das Präfix -webkit verwendet wird. Dies ist also kein Standard und die Unterstützung wird möglicherweise in Zukunft eingestellt. Verlassen Sie sich also nicht darauf, dass dies wirklich wichtig ist. Es ist am besten, diese Technik zu vermeiden, es sei denn, sie ist lediglich ästhetisch .

1
Oliver

Verwenden Sie JavaScript, um eine feste Breite des LI basierend auf dem ungefoldeten Inhalt festzulegen, und setzen Sie dann den Inhalt in Fettschrift, indem Sie dem <a>-Tag einen Stil zuweisen (oder fügen Sie einen Bereich hinzu, wenn der <li> keine untergeordneten Elemente enthält).

1
Dan Blows

Sie können dies wie das Hover-Menü "Einkaufen nach Abteilung" von Amazon.com implementieren. Es verwendet Wide Div. Sie können ein breites Div erstellen und den rechten Teil ausblenden

0
Andrus

UPDATE: Musste das B-Tag für den Titel verwenden, da in IE11 die Pseudo-Klasse i: after nicht angezeigt wurde, als ich Sichtbarkeit hatte: ausgeblendet.

In meinem Fall möchte ich ein (benutzerdefiniertes) Kontrollkästchen/Radio mit Beschriftungstext ausrichten, wobei der Text fett wird, wenn die Eingabe markiert ist.

Die hier bereitgestellte Lösung funktionierte für mich in Chrome nicht. .__ Die vertikale Ausrichtung von Eingabe und Label wurde mit der: after psuedo-Klasse und dem -margins-Problem nicht richtig gemacht.

Hier ist ein Fix, bei dem Sie mit vertikalen Ausrichtungen keine Probleme bekommen.

/* checkbox and radiobutton */
label
{
    position: relative;
    display: inline-block;
    padding-left: 30px;
    line-height: 28px;
}

/* reserve space of bold text so that the container-size remains the same when the label text is set to bold when checked. */
label > input + b + i
{
    font-weight: bold;
    font-style: normal;
    visibility: hidden;
}

label > input:checked + b + i
{
    visibility: visible;
}

/* set title attribute of label > b */
label > input + b:after
{
    display: block;
    content: attr(title);
    font-weight: normal;
    position: absolute;
    left: 30px;
    top: -2px;
    visibility: visible;
}

label > input:checked + b:after
{
    display: none;
}

label > input[type="radio"],
label > input[type="checkbox"]
{
    position: absolute;
    visibility: hidden;
    left: 0px;
    margin: 0px;
    top: 50%;
    transform: translateY(-50%);
}

    label > input[type="radio"] + b,
    label > input[type="checkbox"]  + b
    {
        display: block;
        position: absolute;
        left: 0px;
        margin: 0px;
        top: 50%;
        transform: translateY(-50%);
        width: 24px;
        height: 24px;
        background-color: #00a1a6;
        border-radius: 3px;
    }

    label > input[type="radio"] + b
    {
        border-radius: 50%;
    }

    label > input:checked + b:before
    {
        display: inline-block;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%) rotate(45deg);
        content: '';
        border-width: 0px 3px 3px 0px;
        border-style: solid;
        border-color: #fff;
        width: 4px;
        height: 8px;
        border-radius: 0px;
    }

    label > input[type="checkbox"]:checked + b:before
    {
        transform: translate(-50%, -60%) rotate(45deg);
    }

    label > input[type="radio"]:checked + b:before
    {
        border-width: 0px;
        border-radius: 50%;
        width: 8px;
        height: 8px;
    }
<label><input checked="checked" type="checkbox"/><b title="Male"></b><i>Male</i></label>
<label><input type="checkbox"/><b title="Female"></b><i>Female</i></label>

0
Erik

Dies ist eine sehr alte Frage, aber ich überarbeite sie noch einmal, weil ich dieses Problem in einer App hatte, die ich gerade entwickle und die Antworten hier zu wünschen übrig ließen.

(Überspringen Sie diesen Absatz für die TL; DR ...) Ich verwende den Gotham-Webfont von cloud.typography.com, und ich habe Schaltflächen, die hohl beginnen (mit weißem Rand/Text und transparentem Hintergrund). und eine Hintergrundfarbe beim Schweben erhalten. Ich stellte fest, dass einige der von mir verwendeten Hintergrundfarben keinen guten Kontrast zu dem weißen Text bildeten. Daher wollte ich den Text für diese Schaltflächen in Schwarz ändern, aber - entweder aufgrund eines visuellen Tricks oder aufgrund gängiger Anti-Aliasing-Methoden - dunkel Text auf hellem Hintergrund scheint immer leichter zu sein als weißer Text auf dunklem Hintergrund. Ich fand, dass die Erhöhung des Gewichts von 400 auf 500 für den dunklen Text fast genau dasselbe "visuelle" Gewicht beibehielt. Es vergrößerte jedoch die Breite der Knöpfe um einen winzigen Betrag - einen Bruchteil eines Pixels -, aber es genügte, um die Knöpfe etwas "jitter" erscheinen zu lassen, was ich loswerden wollte.

Lösung:

Offensichtlich ist dies ein sehr heikles Problem, so dass eine schwierige Lösung erforderlich war. Letztendlich habe ich einen negativen letter-spacing für den fetteren Text als cgTag oben empfohlen, aber 1px wäre viel zu viel gewesen, also habe ich genau die Breite berechnet, die ich brauche.

Bei der Überprüfung der Schaltfläche in Chrome devtools stellte ich fest, dass die Standardbreite meiner Schaltfläche 165,47 Pixel betrug und 165,69 Pixel im Schwebeflug eine Differenz von 0,22 Pixel. Der Button hatte 9 Zeichen, also:

0,22/9 = 0,024444px

Durch die Konvertierung dieser Einheiten in em-Einheiten konnte ich die Anpassung der Schriftgröße agnostisch machen. Meine Schaltfläche verwendete eine Schriftgröße von 16px.

0,024444/16 = 0,001527em

Für meinen speziellen Zeichensatz behält das folgende CSS die Schaltflächen genau bei Hover die gleiche Breite bei:

.btn {
  font-weight: 400;
}

.btn:hover {
  font-weight: 500;
  letter-spacing: -0.001527em;
}

Durch ein wenig Testen und Verwenden der obigen Formel können Sie genau den richtigen letter-spacing-Wert für Ihre Situation finden und er sollte unabhängig von der Schriftgröße funktionieren.

Der einzige Nachteil ist, dass verschiedene Browser leicht unterschiedliche Subpixelberechnungen verwenden. Wenn Sie also auf diese OCD-Ebene mit subpixelgenauer Präzision abzielen, müssen Sie den Test wiederholen und für jeden Browser einen anderen Wert einstellen. Browser-bezogene CSS-Stile sind aus gutem Grund generell verpönt , aber ich denke, dies ist ein Anwendungsfall, bei dem dies die einzige Option ist, die Sinn macht.

0
dannymcgee

Interessante Frage. Ich nehme an, Sie verwenden Schwimmer, richtig?

Nun, ich kenne keine Technik, mit der Sie diese Schrift vergrößern können. Daher versuchen sie, die erforderliche Mindestbreite anzupassen. Durch unterschiedliche Schriftstärken ändert sich dieser Wert.

Die einzige Lösung, die ich kenne, um diese Änderung zu vermeiden, ist eine, von der Sie sagten, dass Sie sie nicht wollen: Feste Größen auf li setzen.

0
Dave