Встроенные элементы смещения, когда решился на Ховер

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

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

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

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 ответов


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. Идея состоит в том, чтобы зарезервировать место для bolded (или любого :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 жирным шрифтом и скройте его видимостью: скрыто, чтобы он сохранил свои размеры. Затем вы можете настроить поля следующих элементов, чтобы сделать его нужным.

Я не уверен, что этот подход является 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, вы можете установить правильную ширину после отображения страницы. Вот как я это сделал (используя Prototype):

$$('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 elements, но я просто исправил ту же проблему. У меня есть меню, состоящее из тегов div.

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

(Примечание: кажется, что он удаляет мой 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)

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