web-dev-qa-db-ja.com

ホバーで太字にするとインライン要素が移動する

HTMLリストとCSSを使用して水平メニューを作成しました。リンクの上にマウスを置いたときを除き、すべてが正常に機能します。ご覧のように、リンクに太字のホバー状態を作成しましたが、太字のサイズの違いによりメニューリンクが移動します。

このSitePointの投稿 と同じ問題が発生します。ただし、投稿には適切な解決策がありません。私はどこでも解決策を探しましたが、見つけることができません。これをやろうとしているのは私だけではありません。

誰にもアイデアはありますか?

追伸:メニュー項目のテキストの幅がわからないので、li項目の幅を設定することはできません。

.nav { margin: 0; padding: 0; }
.nav li { 
    list-style: none; 
    display: inline; 
    border-left: #ffffff 1px solid; 
}
.nav li a:link, .nav li a:visited { 
    text-decoration: none; 
    color: #000; 
    margin-left: 8px; 
    margin-right: 5px; 
}
.nav li a:hover{ 
    text-decoration: none; 
    font-weight: bold; 
}
.nav li.first { border: none; }
<ul class="nav">
    <li class="first"><a href="#">item 0</a></li>
    <li><a href="#">item 1</a></li>
    <li><a href="#">item 2</a></li>
    <li><a href="#">item 3</a></li>
    <li><a href="#">item 4</a></li>
</ul>
173
Billy
li {
    display: inline-block;
    font-size: 0;
}
li a {
    display:inline-block;
    text-align:center;
    font: normal 16px Arial;
    text-transform: uppercase;
}
a:hover {
    font-weight:bold;
}
a::after {
    display: block;
    content: attr(title);
    font-weight: bold;
    height: 0;
    overflow: hidden;
    visibility: hidden;
}
<ul>
    <li><a href="#" title="height">height</a></li>
    <li><a href="#" title="icon">icon</a></li>
    <li><a href="#" title="left">left</a></li>
    <li><a href="#" title="letter-spacing">letter-spacing</a></li>
    <li><a href="#" title="line-height">line-height</a></li>
</ul>

JSfiddle の動作例を確認してください。アイデアは、:hover疑似要素の太字(または:after状態スタイル)コンテンツ用のスペースを確保し、コンテンツのソースとしてタイトルタグを使用することです。

349
350D

妥協した解決策は、テキストの影で太字を偽造することです、例えば:

text-shadow:0 0 0.01px黒;

より良い比較のために、これらの例を作成しました:

a, li {
  color: black;
  text-decoration: none;
  font: 18px sans-serif;
  letter-spacing: 0.03em;
}
li {
  display: inline-block;
  margin-right: 20px;
  color: gray;
  font-size: 0.7em;
}
.bold-x1 a.hover:hover,
.bold-x1 a:not(.hover) {
  text-shadow: 0 0 .01px black;
}
.bold-x2 a.hover:hover,
.bold-x2 a:not(.hover){
  text-shadow: 0 0 .01px black, 0 0 .01px black;
}
.bold-x3 a.hover:hover,
.bold-x3 a:not(.hover){
  text-shadow: 0 0 .01px black, 0 0 .01px black, 0 0 .01px black;
}
.bold-native a.hover:hover,
.bold-native a:not(.hover){
  font-weight: bold;
}

.bold-native li:nth-child(4),
.bold-native li:nth-child(5){
 margin-left: -6px;
 letter-spacing: 0.01em;
}
<ul class="bold-x1">
  <li><a class="hover" href="#">Home</a></li>
  <li><a class="hover" href="#">Products</a></li>
  <li><a href="#">Contact</a></li>
  <li><a href="#">About</a></li>
  <li>Bold (text-shadow x1)</li>
</ul>
<ul class="bold-x2">
  <li><a class="hover" href="#">Home</a></li>
  <li><a class="hover" href="#">Products</a></li>
  <li><a href="#">Contact</a></li>
  <li><a href="#">About</a></li>
  <li>Extra Bold (text-shadow x2)</li>
</ul>
<ul class="bold-native">
  <li><a class="hover" href="#">Home</a></li>
  <li><a class="hover" href="#">Products</a></li>
  <li><a href="#">Contact</a></li>
  <li><a href="#">About</a></li>
  <li>Bold (native)</li>
</ul>
<ul class="bold-x3">
  <li><a class="hover" href="#">Home</a></li>
  <li><a class="hover" href="#">Products</a></li>
  <li><a href="#">Contact</a></li>
  <li><a href="#">About</a></li>
  <li>Black (text-shadow x3)</li>
</ul>

text-shadowblur-radiusの非常に低い値を渡すと、ぼかし効果がそれほど目立たなくなります。

一般的に、text-shadowを繰り返すほど、テキストは太くなりますが、同時に文字の元の形状が失われます。

blur-radiusをfractionsに設定しても、すべてのブラウザーで同じレンダリングが行われるわけではないことに注意してください。たとえば、Safariでは、Chromeと同じ方法でレンダリングするために、より大きな値が必要です。

36
Stefan J

幅を設定できない場合、テキストが太字になると幅が変わることを意味します。これを回避する方法はありませんが、各状態のパディング/マージンを変更するなどの妥協による場合を除きます。

27
Andrew Vit

別のアイデアは、letter-spacingを使用することです

a {
  letter-spacing: 0.05px
}

a:hover, a:focus {
  font-weight: bold;
  letter-spacing: 0
}
19
John Magnolia

1 jqueryの行:

$('ul.nav li a').each(function(){
    $(this).parent().width($(this).width() + 4);
});

編集:これは解決策をもたらす可能性がありますが、元の投稿のコードと連携して機能しないことに言及する必要があります。 「display:inline」は、幅設定を有効にしてその水平メニューを意図したとおりに機能させるために、フローティングパラメータに置き換える必要があります。

18
Alex

CSS3ソリューション-実験的

ここでは誰も提案しなかった別のソリューションを共有することを考えました。これに便利なtext-strokeというプロパティがあります。

p span:hover {
  -webkit-text-stroke: 1px black;
}
<p>Some stuff, <span>hover this,</span> it's cool</p>

ここでは、spanタグ内のテキストをターゲットにし、blackを使用してピクセルでストロークします。これにより、特定のテキストのboldスタイルがシミュレートされます。

このプロパティは広くサポートされていないことに注意してください。現時点では(この回答を書いている間)、ChromeとFirefoxのみがこれをサポートしているようです。 text-strokeのブラウザサポートの詳細については、 CanIUse を参照できます。


余分なものを共有するために、ストロークにcolorを設定する必要がない場合は、-webkit-text-stroke-width: 1px;を使用できます。

5
Mr. Alien

あなたのようなsomehtingを使用することができます

<ul>
   <li><a href="#">Some text<span><br />Some text</span></a></li>
</ul>

そして、cssでspanコンテンツを太字に設定し、visibility:hiddenで非表示にするだけで、寸法が維持されます。次に、次の要素のマージンを調整して、適切に収まるようにします。

このアプローチがSEOに優しいかどうかはわかりませんが。

5
monk

「シャドウ」ソリューションで問題を解決しました。それは最もシンプルで効果的です。

nav.mainMenu ul li > a:hover, nav.mainMenu ul li.active > a {
    text-shadow:0 0 1px white;
}

影を3回繰り返す必要はありません(結果は私にとって同じでした)。

5
Daniele B

あなたと同様の問題がありました。メニュー上だけでなくテキスト内でもマウスをポイントするとリンクが太字になります。あなたが推測するように、それはすべての異なる幅を理解する本当の雑用になります。解決策は非常に簡単です。

太字のリンクテキストを含むボックスを作成しますが、背景のように色付けされ、実際のリンクはその上にあります。これが私のページの例です:

CSS:

.hypo { font-weight: bold; color: #FFFFE0; position: static; z-index: 0; }
.hyper { position: absolute; z-index: 1; }

もちろん、#FFFFE0をページの背景色に置き換える必要があります。 z-indicesは必要ないようですが、とにかくそれらを入れます(HTMLコードの「hyper」要素の後に「hypo」要素が発生するため)。次に、ページにリンクを配置するには、次を含めます。

HTML:

You can find foo <a href="http://bar.com" class="hyper">here</a><span class="hypo">here</span>

2番目の「ここ」は表示されず、リンクの下に隠れます。これはリンクテキストが太字で表示される静的なボックスであるため、リンクの上にカーソルを合わせる前にテキストが既に移動しているため、テキストの残りの部分は移動しません。

私が助けることができたことを願っています:)。

さよなら

4
kay

ホバー時にフォント(°)を切り替えないようにアドバイスします。この場合、メニュー項目が少し移動するだけですが、幅が広くなると余分なWordラップが発生するため、段落全体が再フォーマットされる場合があります。カーソルを移動するだけの場合は、これが発生するのは望ましくありません。何もしなければ、ページレイアウトは変更されません。

シフトは、通常とイタリックを切り替えるときにも発生する可能性があります。テキストの下にスペースがある場合は、色を変更するか、下線を切り替えます。 (下線は下の境界線からはっきり見えるはずです)

Form Designクラスでフォントの切り替えを使用した場合、私はブーイングされます:-)

(°)Wordフォントはよく誤用されます。 「Verdana」はtypeface、「Verdana normal」および「Verdana bold」は異なるfontsは同じ書体です。

2
stevenvh

「margin」プロパティを使用できます。

li a {
  margin: 0px 5px 0px 5px;
}

li a:hover {
  margin: 0;
  font-weight: bold;
}

余分なスペースに太字のテキストを含めることができるように、左右のマージンが十分に大きいことを確認してください。長い単語の場合、異なるマージンを選択できます。それは単なる別の回避策ですが、私のために仕事をしています。

2
Martin Horvath

代わりにtext-shadowを使用するのが好きです。特に、トランジションを使用してテキストシャドウをアニメーション化できるためです。

本当に必要なのは:

a {
  transition: text-shadow 1s;
}
a:hover {
  text-shadow: 1px 0 black;
}

完全なナビゲーションについては、このjsfiddleを確認してください。 https://jsfiddle.net/831r3yrb/

ブラウザのサポートとtext-shadowの詳細: http://www.w3schools.com/cssref/css3_pr_text-shadow.asp

1
Lightningsoul

これは私が好む解決策です。少しのJSが必要ですが、タイトルプロパティをまったく同じにする必要はなく、CSSは非常にシンプルなままです。

$('ul a').each(function() {
  $(this).css({
    'padding-left': 0,
    'padding-right': 0,
    'width': $(this).outerWidth()
  });
});
li, a { display: inline-block; }
a {
  padding-left: 10px;
  padding-right: 10px;
  text-align: center; /* optional, smoother */
}
a:hover { font-weight: bold; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
  <li><a href="#">item 1</a></li>
  <li><a href="#">item 2</a></li>
  <li><a href="#">item 3</a></li>
</ul>
0
lurkit

上記の一連の手法を組み合わせて、jsをオフにしても完全に嫌なものではなく、少しjQueryを使用するとさらに優れたものを提供します。ブラウザがサブピクセルの文字間隔のサポートを改善している今、それを使用するのは本当に素晴らしいことです。

jQuery(document).ready(function($) {
  $('.nav a').each(function(){
      $(this).clone().addClass('hoverclone').fadeTo(0,0).insertAfter($(this));
    var regular = $(this);
    var hoverclone = $(this).next('.hoverclone');
    regular.parent().not('.current_page_item').hover(function(){
      regular.filter(':not(:animated)').fadeTo(200,0);
      hoverclone.fadeTo(150,1);
    }, function(){
      regular.fadeTo(150,1);
      hoverclone.filter(':not(:animated)').fadeTo(250,0);
    });
  });
});
ul {
  font:normal 20px Arial;
  text-align: center;
}
li, a {
  display:inline-block;
  text-align:center;
}
a {
  padding:4px 8px;
  text-decoration:none;
  color: #555;
}

.nav a {
  letter-spacing: 0.53px; /* adjust this value per font */
}
.nav .current_page_item a,
.nav a:hover {
  font-weight: bold;
  letter-spacing: 0px;
}
.nav li {
  position: relative;
}
.nav a.hoverclone {
  position: absolute;
  top:0;
  left: 0;
  white-space: nowrap;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul class="nav">
  <li><a href="#">Item 1</a></li>
  <li><a href="#">Item 2</a></li>
  <li class="current_page_item"><a  href="#">Item 3</a></li>
  <li><a href="#">Item 4</a></li>
  <li><a href="#">Item 5</a></li>
</ul>
0
squarecandy

別のアプローチは、テキストシャドウを介して太字のテキストを「エミュレート」することです。これには、フォントアイコンでも機能するボーナス(/ malus、場合によって)があります。

   nav li a:hover {
      text-decoration: none;
      text-shadow: 0 0 1px; /* "bold" */
   }

ちょっとハッキーですが、テキストを複製する手間が省けます(私の場合のように、大量にある場合に便利です)。

0
EdoardoSchnell

代わりにa :: beforeを使用するほうがよいa :: afterのようにこの:

.breadcrumb {
  margin: 0;
  padding: 0;
  list-style: none;
  overflow: hidden;
}

.breadcrumb li, 
.breadcrumb li a {
  display: inline-block;
}

.breadcrumb li:not(:last-child)::after {
  content: '>'; /* or anything else */
  display: inline-block;
}

.breadcrumb a:hover {
  font-weight: bold;
}

.breadcrumb a::before {
  display: block;
  content: attr(data-label);
  font-weight: bold;
  height: 0;
  overflow: hidden;
  visibility: hidden;
}
<ul class="breadcrumb">
  <li><a data-label="one" href="https://www.google.fr/" target="_blank">one</a></li>
  <li><a data-label="two" href="https://duckduckgo.com/" target="_blank">two</a></li>
  <li><a data-label="three" href="#">three</a></li>
</ul>

詳細: https://jsfiddle.net/r25foavy/

0
clisima
ul {
  list-style-marker: none;
  padding: 0;
}

li {
  display: inline-block;
}

li + li {
  margin-left: 1em;
}

a {
  display: block;
  position: relative;
  text-align: center;
}

a:before, a:after {
  content: attr(aria-label);
  text-decoration: inherit;
}

a:before {
  font-weight: bold;
  visibility: hidden;
}

a:after {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
}

a:hover:before {
  visibility: visible;
}

a:hover:after {
  display: none;
}
<ul>
  <li>
    <a href="" aria-label="Long-long-long"></a>
  </li><li>
    <a href="" aria-label="or"></a>
  </li><li>
    <a href="" aria-label="Short"></a>
  </li><li>
    <a href="" aria-label="Links"></a>
  </li><li>
    <a href="" aria-label="Here"></a>
  </li>
</ul>
0
Qwertiy

非常にエレガントなソリューションではありませんが、「機能する」:

a
{
    color: #fff;
}

a:hover
{
    text-shadow: -1px 0 #fff, 0 1px #fff, 1px 0 #fff, 0 -1px #fff;
}
0
Świeżu

これはどうですか? JavaScript-CSS3フリーのソリューション。

http://jsfiddle.net/u1aks77x/1/

ul{}
li{float:left; list-style-type:none; }
a{position:relative; padding-right: 10px; text-decoration:none;}
a > .l1{}
a:hover > .l1{visibility:hidden;}
a:hover > .l2{display:inline;}
a > .l2{position: absolute; left:0; font-weight:bold; display:none;}

<ul>
  <li><a href="/" title="Home"><span class="l1">Home</span><span class="l2">Home</span></a></li>
  <li><a href="/" title="Contact"><span class="l1">Contact</span><span class="l2">Contact</span></a></li>
  <li><a href="/" title="Sitemap"><span class="l1">Sitemap</span><span class="l2">Sitemap</span></a></li>
</ul>
0
user10099

ここで言及した他のいくつかのように、私はテキストシャドウソリューションを使用します:

text-shadow: 0 0 0.01px;

違いは、シャドウカラーを指定しないことです。したがって、このソリューションはすべてのフォントカラーに共通です。

0
jabko87