CSS:コンテナーのサイズを変更せずにテキストを太字にする


119

水平ナビゲーションメニューがあります。これは基本的に<ul>、要素を並べて設定した単なるa です。幅は定義しませんが、メニュー項目の幅によって幅を定義したいので、単にパディングを使用します。現在選択されているアイテムを太字にします。

問題は、太字で単語が少し広くなり、残りの要素が少し左または右にシフトすることです。これを防ぐための賢い方法はありますか?太字によって引き起こされる余分な幅を無視するようにパディングに指示するという線に沿った何か?私の最初の考えは、「アクティブ」要素のパディングから数ピクセルを単に差し引くことでしたが、この量は異なります。

可能であれば、エントリへの将来の変更を簡単にするために、各エントリに静的な幅を設定してから、現在のパディングソリューションとは対照的に中央揃えを避けたいと思います。


サイズ変更が問題になるのはなぜですか?どういうわけかレイアウトをめちゃくちゃにしていますか?
Chaulky、2011

StackオーバーフローでWebプログラミングの質問をするのが一番だと思います。多分modはこれをそこに移行します。
Ciaran 2011

2
Chaulky:レイアウトで言うと、ボタンをクリックしてジャンプしようとするときよりも嫌いなものはほとんどないため
Mala

doejo.com/blog/…は、JohnとBlowskiがjscriptについて話していたこととまったく同じことを私が見つけた1つの解決策です。
ウシガエル

回答:


152

私は同じ問題を抱えていましたが、少し妥協しても同様の効果が得られたため、代わりにテキストシャドウを使用しました。

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

これが実際の例です:

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の例


51
私はこのソリューションが大好きですが、1px 0px 0pxにフリップすることをお勧めします。もう少し大胆に見えます。
M.ヘロルド2013年

CSSのみのソリューションが必要でしたが、これが答えです。
JCasso 2013年

あなたの本当の天才!シンプルさはそれをかっこいいものにします!
lufi 2014年

1
追加するだけli:hover {text-shadow: 1px 0 0 black;}で、文字間のスペースが小さすぎるテキストが生成されました。再びそれを改善するために、我々はまた設定しましたli {letter-spacing: 1px;}
Patrick Hammer

5
-0.5px 0 #fff, 0.5px 0 #fffテキスト自体と影の間に小さなギャップが見えるので、私はを使用しました。また、テキストが太字の場合、両側に重みが追加されます。
atorscho

101

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

title属性によって供給される太字のテキストの幅を持つ非表示の疑似要素を追加します。

このtext-shadowソリューションはMacでは不自然に見え、Macでのテキストレンダリングが提供するすべての美しさを利用していません。

http://jsfiddle.net/85LbG/

クレジット:https : //stackoverflow.com/a/20249560/5061744


11
これは最も信頼性が高くクリーンなソリューションであり、要素内の太字のテキスト用にスペースを予約するだけです。私の場合、追加の疑似要素によって高さが変化しました。ブロックにネガティブmargin-topを追加することで::after解決しました。
Vaclav Novotny

2
このソリューションは素晴らしいです!HTMLの変更を回避できるように、JSを使用して要素のテキストを含む「data-content」属性を追加しました。
mistykristie

1
驚くばかり。これが最良の答えです。liとは異なる要素の場合、display:blockを使用する必要があることに注意してください。:after親要素上。
Blackbam

素晴らしい解決策!:: beforeでも正常に機能します。私の場合、これにより下部の余白がなくなります。
トーマスチャンピオン

この解決策をありがとう。最初はテキストシャドウを使用しましたが、10進数値を四捨五入するため、Safariでは機能しません。私は0.1pxを使用していたので、これは0に四捨五入されていました。ソリューションは完璧に機能しました。ツールチップを表示したくないので、title属性を名前に置き換えただけです
Jonathan Cardoz

31

最もポータブルで視覚的に楽しいソリューションは、を使用することtext-shadowです。これは、Alexxaliと私の独自の微調整を使用して、Thorgeirの回答の例を修正して示しています。

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

これによりblack、フォントのレンダリングで適切に拡大縮小される単位を使用して、各文字の両側に小さな「影」が黒で(必要に応じてフォントの色名/コードを使用して)配置されます。

警告 警告: px値は10進値をサポートしますが、フォントサイズが変更された場合(たとえば、ユーザーがCtrl+でビューを拡大縮小する場合)は見栄えがよくありません+。代わりに相対値を使用してください。

この答えはex、フォントに合わせてスケーリングするため、単位の端数を使用しています。
〜ほとんどのブラウザのデフォルト設定では*、期待1ex8pxため、0.025ex0.1px

自分で見て:

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>

レンダリングされた線にカーソルを合わせると、標準のテキストとの違いを確認できます。

ブラウザーのズームレベル(Ctrl+ +およびCtrl+ -)を変更して、それらがどのように変化するかを確認します。

比較のために他に2つのソリューションを追加しました。@ cgTagの文字間隔トリック(フォント幅の範囲の推測を含むため、うまく機能しません)と、@ workaholic_gangster911 の::描画後のトリックです。隣接するテキスト項目を微調整することなく(どのように移動しないかわかるように、ボールドテキストの後に属性を配置します)。


将来的には、を使用してフォントグレードを変更するなどの機能を持つ可変フォントがさらに増える予定です。 ブラウザーのサポートは増加しています(Chrome 63以降、Firefox 62以降)が、これにはまだ標準フォント以上のものが必要であり、いくつかの既存のフォントがサポートしています。font-variation-settings

可変フォントを埋め込むと、次のようなCSSを使用できるようになります。

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

Mozilla可変フォントガイドには、さまざまなグレードでプレイできるスライダー付きのライブデモがあります。Googleのウェブ上の可変フォント概要には、高等級と無等級の切り替えを示すアニメーションGIFがあります。

グレード軸の切り替えが可能なAmstelvar Alphaフォントアニメーションのアニメーション


1
とてもシンプルでとても美しいです。
ランディホール

18

文字間隔を1px調整すると、ほとんどのフォントが同じサイズであることがわかりました。

a {
   letter-spacing: 1px;
}

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

これは通常のフォントを変更するので、各文字には余分なピクセル間隔があります。メニューの場合、タイトルは非常に短いため、問題にはなりません。


3
これは最良かつ最も過小評価されているソリューションですが、0から開始して太字のときに負の文字間隔になるように変更しました。また、フォントとフォントサイズごとに微調整する必要があります。@Thorgeir
dJcPn / 50

最近のブラウザーは、サブピクセル精度をサポートするようになりました。したがって0.98px、以下の分数を使用して間隔を微調整できます。
Reactgular

間隔アルゴリズムはまったく同じではありませんので、これは少し奇妙に見えます(一部の文字が少し周り踊り)やフォントがスケーリングされたときに、もっと重要なのは、これはあなたが変換した場合でも、仕事をしない1pxように相対値に0.025ex0.0125ex。ライブデモについては、私の回答を参照しください。
Adam Katz

@AdamKatzこの回答が投稿されてからフォントのレンダリングが変更されたのではないかと思います。これは、使用しているフォントに大きく依存します。
Reactgular 2017年

5

より最新の答えを得るには、以下を使用できます-webkit-text-stroke-width

.element {
  font-weight: normal;
}

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

これにより、疑似要素(スクリーンリーダーではプラス)とテキストシャドウ(乱雑に見え、わずかな「ジャンプ」効果が生じる可能性があります)や、固定幅の設定(実用的でない場合があります)を回避できます。

また、要素を1pxよりも太くするように設定することもできます(理論的には、フォントを好きなだけ太字にすることができ、太字のないフォントの太字バージョンを作成するための見掛け倒しのワークアウトにもなります。カスタムフォントのようなバリアント(編集:可変フォントはこの提案を無効にします)。ただし、一部のフォントがチクチクとギザギザに見える可能性があるため、これは避けてください)

私はこれがEdge、Firefox、Chrome、Opera(投稿時)およびSafari編集:@Lars Blumbergで確認できたことに感謝)で確実に機能します。IE11以前では機能しません。

また、-webkitプレフィックスを使用しているため、これは標準ではなく、将来的にサポートが中止される可能性があるため、これに依存しないでください。


1
Safari 13.0.5でも動作します。これまでのところ私にとって最もクリーンなソリューション。
Lars Blumberg

4

残念ながら、テキストが太字のときに幅が変化しないようにする唯一の方法は、リストアイテムの幅を定義することですが、これを手動で行うと時間がかかり、スケーラブルではありません。

私が考えることができる唯一のことは、太字になる前にタブの幅を計算し、太字が必要なときに(ホバーまたはクリックしたときに)幅を適用するJavaScriptを使用することです。


ええと、私はこれを実験しますが、JS以外のユーザーには少なくとも妥当な(太字の)見た目にします。多分私はそれを太字で送信し、JSを使用して太字を外し、幅を計算してから、もう一度太字にすることができますか?それともばかげていますか?
マラ

はい、JavaScript以外のユーザーに対応する最善の方法のように思えます。
ajcw 2011

2

JavaScriptを使用して太字でないコンテンツに基づいてliの固定幅を設定し、スタイルを<a>タグに適用してコンテンツを太字にします(またはに<li>子がない場合はスパンを追加します)。


おっと-繰り返し申し訳ありません:$
Dan Blows 2011

とにかく答えてくれてありがとう:)
マラ

@マラあなたは解決策を見つけましたか?おかしなことに、私は同様の問題を抱えています。
Dan Blows

1

これは非常に古い質問ですが、開発中のアプリでこの問題が発生し、ここですべての回答が必要であることがわかったので、もう一度質問します。

(TL; DRの場合はこの段落をスキップしてください...)私はcloud.typography.comのGotham webfontを使用しています。ボタンが白く(白い境界線/テキストと透明な背景で)始まり、ホバー時に背景色を取得します。使用している背景色の一部が白いテキストとうまく対照しないことがわかったので、それらのボタンのテキストを黒に変更したかったのですが、—視覚的なトリックのためか、一般的なアンチエイリアス方法のためか—暗い明るい背景にあるテキストは、暗い背景にある白いテキストよりも常に重く見えます。暗いテキストのウェイトを400から500に増やすと、ほぼ同じ「視覚的」ウェイトが維持されることがわかりました。ただし、ボタンの幅をごくわずか(ピクセルの数分の1)だけ増やしていましたが、ボタンをわずかに「ジッター」に見せるために十分でした。

解決:

明らかに、これは本当に気の利いた問題なので、気の利いた解決策が必要でした。最終的には、letter-spacing上記のcgTagで推奨されているように、太字のテキストにネガティブを使用しましたが、1pxはやり過ぎでした。

Chrome開発ツールでボタンを調べたところ、ボタンのデフォルトの幅は165.47ピクセルで、ホバー時の165.69ピクセルで、差は0.22ピクセルでした。ボタンは9文字だったので、

0.22 / 9 = 0.024444px

それをem単位に変換することで、フォントサイズの調整に依存しないようにすることができます。私のボタンは16pxのフォントサイズを使用していたので、

0.024444 / 16 = 0.001527em

したがって、特定のフォントでは、次のCSSはホバー時のボタンの幅をまったく同じに保ちます。

.btn {
  font-weight: 400;
}

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

少しテストして上記の数式を使用するletter-spacingと、状況にぴったり合った値を見つけることができ、フォントサイズに関係なく機能するはずです。

1つの注意点は、ブラウザーによって使用されるサブピクセルの計算がわずかに異なることです。このため、このOCDレベルのサブピクセルパーフェクトな精度を目指す場合は、テストを繰り返し、ブラウザーごとに異なる値を設定する必要があります。ブラウザーをターゲットにしたCSSスタイルは、正当な理由により、一般的には見当がつきませんが、これは、それが意味のある唯一のオプションである1つの使用例だと思います。


0

興味深い質問です。フロートを使っていると思いますよね?

さて、このフォントの拡大を取り除くために使用できるテクニックは知らないため、必要な最小幅に収まるように試みます。フォントの太さを変えると、この値が変わります。

この変更を回避するために私が知っているユニークなソリューションは、あなたが望まないことです:固定サイズをliに設定します。


0

これは、amazon.comの「部門別ショップ」ホバーメニューのように実装できます。ワイドdivを使用しています。あなたは広いdivを作成し、その正しい部分を隠すことができます


0

更新:IE11では、visibility:hiddenがあるときに疑似クラスi:afterが表示されなかったため、タイトルにBタグを使用する必要がありました。

私の場合、(カスタム設計された)入力チェックボックス/ラジオを、入力がチェックされたときにテキストが太字になるラベルテキストに揃えたいです。

ここで提供されるソリューションは、Chromeでは機能しませんでした。入力とラベルの垂直方向の配置が:after psuedoクラスに乱れ、-marginsはこれを修正しませんでした。

垂直方向の配置で問題が発生しないように修正します。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.