Перемещение встроенных элементов при выделении жирным шрифтом при наведении курсора


Я создал горизонтальное меню, используя списки HTML и CSS. Все работает как надо только при наведении на ссылки. Видите ли, я создал полужирное состояние наведения для ссылок, и теперь ссылки меню сдвигаются из-за разницы в размере полужирного шрифта.

я сталкиваюсь с той же проблемой как это сообщение SitePoint. Однако сообщение не имеет надлежащего решения. Я искал везде и не могу найти. Конечно, я не могу быть единственным, кто пытается сделать этот.

у кого-нибудь есть идеи?

P. S: Я не знаю ширину текста в пунктах меню, поэтому я не могу просто установить ширину элементов li.

Это мой код:

HTML:

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

CSS:

.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: #ffffff; 
    margin-left: 8px; 
    margin-right: 5px; 
}
.nav li a:hover{ 
    text-decoration: none; 
    font-weight: bold; 
}
.nav li.first { border: none; }
21 147

21 ответ:

li, a {
    display:inline-block;
    text-align:center;
    font: normal 14px Open Sans;
    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 псевдо-элемент и использование тега заголовка в качестве источника контента.

Если вы не можете установить ширину, то это означает, что ширина будет меняться, так как текст становится полужирным. Нет никакого способа избежать этого, за исключением компромиссов, таких как изменение отступов/полей для каждого состояния.

скомпрометированное решение состоит в том, чтобы подделать жирный шрифт с помощью text-shadow, например:

a:hover{
  text-shadow:0 0 1px black, 0 0 1px black, 0 0 1px black
}

повторяя 3 раза тень делает его не так сильно размытым.

другая идея заключается в использовании letter-spacing

a {
  letter-spacing: 0.05px
}

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

один строка в jquery:

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

edit: Хотя это может привести к решению, следует упомянуть, что он не работает в сочетании с кодом в исходном сообщении. "display: inline" должен быть заменен плавающими параметрами для эффективной настройки ширины и горизонтального меню для работы по назначению.

вы могли бы использовать somehting как

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

а затем в вашем css просто установите содержимое span жирным шрифтом и скройте его с помощью visibility: hidden, чтобы он сохранял свои размеры. Затем вы можете настроить поля следующих элементов, чтобы они соответствовали должным образом.

Я не уверен, что этот подход является SEO дружественным, хотя.

Я только что решил проблему с "теневым" решением. Это кажется самым простым и эффективным.

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

Не нужно повторять тень три раза (результат был тот же для меня).

у меня была проблема, похожая на вашу. Я хотел, чтобы мои ссылки выделялись жирным шрифтом при наведении на них, но не только в меню, но и в тексте. Как вы догадываетесь, это будет настоящая рутина, выясняя все разные ширины. Решение довольно простое:

создайте поле, которое содержит текст ссылки полужирным шрифтом, но цветное, как ваш фон, но ваша реальная ссылка над ним. Вот пример с моей страницы:

CSS:

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

конечно нужно замените #FFFFE0 цветом фона вашей страницы. Z-индексы, похоже, не нужны, но я все равно их ставлю (поскольку элемент "hypo" будет происходить после элемента "hyper" в HTML-коде). Теперь, чтобы разместить ссылку на своей странице, включите следующее:

HTML:

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

второе "здесь" будет невидимым и скрытым под вашей ссылкой. Поскольку это статическая коробка с ваш текст ссылки выделен жирным шрифтом, остальная часть текста больше не будет смещаться, поскольку он уже смещен раньше вы наводите курсор на ссылку.

надеюсь, я смог помочь :).

так долго

Я бы посоветовал не переключать шрифты (°) при наведении. В этом случае это просто пункты меню немного перемещаются, но я видел случаи, когда полный абзац переформатируется, потому что расширение вызывает дополнительную перенос слов. Вы не хотите, чтобы это произошло, когда единственное, что вы делаете, это переместить курсор; если вы ничего не делаете, макет страницы не должен меняться.

сдвиг также может произойти при переключении между обычным и курсивом. Я бы попробовал изменить цвета или переключить подчеркните, если у вас есть место под текстом. (подчеркивание должно оставаться четким от нижней границы)

Я был бы boo'D, если бы я использовал переключение шрифтов для моего класса дизайна формы: -)

(°) шрифт слова часто используется неправильно. "Вердана" - это шрифт, "Verdana normal" и "Verdana bold" отличаются шрифты того же шрифта.

вы можете работать со свойством "margin":

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

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

просто убедитесь, что левое и правое поля достаточно большие, чтобы дополнительное пространство могло содержать жирный текст. Для длинных слов вы можете выбрать разные поля. Это просто еще один обходной путь, но делает работу для меня.

решение 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.


просто для обмена некоторыми дополнительными вещами, вы можете использовать -webkit-text-stroke-width: 1px; если вы не хотите установить color для вашего удара.

Мне нравится использовать 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

Это решение я предпочитаю. Это требует немного JS, но вам не нужно, чтобы ваше свойство title было точно таким же, и ваш 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>

Как насчет этого? В 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>

не очень изящное решение, но "работает":

a
{
    color: #fff;
}

a:hover
{
    text-shadow: -1px 0 #fff, 0 1px #fff, 1px 0 #fff, 0 -1px #fff;
}

Я объединил кучу методов выше, чтобы обеспечить что-то, что не полностью сосать с 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>

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>

Если вы не прочь использовать Javascript, вы можете установить правильную ширину, как только страница будет показана. Вот как я это сделал (используя прототип):

$$('ul.nav li').each(this.setProperWidth);

setProperWidth: function(li)
{
  // Prototype's getWidth() includes padding, so we 
  // have to subtract that when we set the width.
  var paddingLeft = li.getStyle('padding-left'),
      paddingRight = li.getStyle('padding-right');

  // Cut out the 'px' at the end of each padding
  paddingLeft = paddingLeft.substring(0,paddingLeft.length-2);
  paddingRight = paddingRight.substring(0,paddingRight.length-2);

  // Make the li bold, set the width, then unbold it
  li.setStyle({ fontWeight: 'bold' });
  li.setStyle({ width: (li.getWidth() - paddingLeft - paddingRight) + 'px'});
  li.setStyle({ fontWeight: 'normal', textAlign: 'center' });
}

Я действительно терпеть не могу, когда кто-то говорит вам не делать что-то, когда есть простое решение проблемы. Я не уверен в элементах li, но я просто исправил ту же проблему. У меня есть меню, состоящее из тегов div.

просто установите тег div как "display: inline-block". Встроенные, чтобы они сидели рядом друг с другом и блокировали, чтобы вы могли установить ширину. Просто установите ширину достаточно широкую, чтобы разместить для полужирного текста и иметь текстовый центр выровненный.

(Примечание: кажется, что он удаляет мой html [ниже], но каждый пункт меню имел тег div, обернутый вокруг него с идентификатором corrasponding и именем класса SearchBar_Cateogory. т. е.: <div id="ROS_SearchSermons" class="SearchBar_Category">

HTML (У меня были теги привязки, обернутые вокруг каждого пункта меню, но я не смог отправить их в качестве нового пользователя)

<div id="ROS_SearchSermons" class="SearchBar_Cateogry bold">Sermons</div>|
<div id="ROS_SearchIllustrations" class="SearchBar_Cateogry">Illustrations</div>|
<div id="ROS_SearchVideos" class="SearchBar_Cateogry">Videos</div>|
<div id="ROS_SearchPowerPoints" class="SearchBar_Cateogry">PowerPoints</div>|
<div id="ROS_SearchScripture" class="SearchBar_Cateogry">Scripture</div>|

CSS:

#ROS_SearchSermons { width: 75px; }
#ROS_SearchIllustrations { width: 90px; }
#ROS_SearchVideos { width: 55px; }
#ROS_SearchPowerPoints { width: 90px; }
#ROS_SearchScripture { width: 70px; }

.SearchBar_Cateogry
{
    display: inline-block;
    text-align:center;
}

вы можете попробовать отрицательные поля тоже, если жирный текст шире, чем обычный. (не всегда) Поэтому идея состоит в том, чтобы использовать классы вместо стиля :hover state.

jQuery:

 $(".nav-main .navbar-collapse > ul > li > a").hover(function() {
    var originalWidth = $(this).outerWidth();

    $(this).parent().addClass("hover");
    $(this).css({
       "margin-left": -(($(this).outerWidth() - originalWidth) / 2),
       "margin-right": -(($(this).outerWidth() - originalWidth) / 2)
    });
 },
 function() {
    $(this).removeAttr("style");
    $(this).parent().removeClass("hover");
 });

CSS:

ul > li > a {
    font-style: normal;
}

ul > li > a.hover {
    font-style: bold;
}

Я надеюсь, что смогу помочь!

вот идея для плагина jquery:

for all of the elements that you want bold mouse-over:
    - on mouseover:
        - calculate the width W and center C of the element
        - copy the element and hide the original with visibility:hidden (so it still takes up the same space)
        - make the text of the copied element bold and calculate the new width W2
        - position the element absolute left at C-(W2/2)

вы можете легко расширить это для высоты, а также, что позволяет немного увеличить размер шрифта при наведении курсора мыши без необходимости беспокоиться о прыжках контента.