Элемент с дисплеем CSS: нет; разбивка макета - причина несоосности

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

Menu bar

Один из <li> содержит дополнительное изображение с display: none; так что значок может быть переключен (от зеленого до красного перца, в этом примере). Проблема в том, что он не выравнивается правильно в некоторых браузерах, как показано на рисунке выше. Я понял, что в отличие от visibilty: hidden;, элемент с display: none; не должен влиять на положение любого другого элемента и должен отображаться так, как будто его нет?

Браузеры, где он не отображается правильно, - это Google Chrome и Safari, но только в MacOS (!?) И IE7 (я знаю, знаю...) в Windows. Каждая другая комбинация браузера/ОС, которую я тестировал, отлично работает.

Здесь HTML:

<ul class="menu">
    <li><img alt="Green Pepper" src="/green.png">li</li>
    <li><img alt="Green Pepper" src="/green.png">li</li>
    <li><img alt="Green Pepper" src="/green.png">li</li>
    <li id="change">
        <img alt="Red Pepper" src="/red.png" style="display: none;">
        <img alt="Green Pepper" src="/green.png"> 
        li
    </li>
    <li><img alt="Green Pepper" src="/green.png">li</li>
</ul>

Здесь CSS:

.menu li {
    cursor: default;
    font-family: Verdana, Arial, Helvetica, sans-serif;
    font-size: 10pt;
    list-style-type: none; 
    position: relative; 
    text-align:center; 
    margin: 0 0 0 -25px; 
    padding: 8px 0 0 0;
    width: 144px;
    height: 35px;
    display: inline-block;
    background-image: url(../bct-white.png);
    background-repeat: no-repeat;
    color: #0091c1;
}

И для изображений значков:

.menu img {
    display: inline;
    vertical-align: -25%;
    padding-right: 6px;
}

Я также должен был включить браузер для IE7, потому что он не распознает встроенный блок, исходящий из отдельной таблицы стилей на основе условного импорта (<!--[if lte IE 7]>):

.menu li {
    zoom: 1;
    display: inline;
}

Хотя, очевидно, что стиль не загружается в Chrome и Safari независимо от ОС, поэтому не может быть причиной моей проблемы на компьютерах Mac.

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


Обновить

Я отследил причину. В принципе, стиль элемента display: none; на элементе <img> переопределяет .menu img inline из .menu img. Удалив это, переключение между block и inline позволяет воспроизвести проблему. Очевидно, это ошибка браузера, и пока элемент не отображается, поскольку элемент в строке или блоке не должен влиять на макет.


jsFiddles

Проблема с Chrome и Safari только на компьютерах Mac

Проблема с дополнительным CSS для IE7 только

Заметка! Для меня страница Fiddle неправильно загружалась с использованием IE7, но прямая ссылка для результата iFrame - http://fiddle.jshell.net/z4dU7/3/show/

Обновление Bounty !!!

Я опубликовал одно исправление ниже, но на самом деле он вводит ту же макетную проблему в IE9! Пожалуйста, не стесняйтесь меняться или улучшать свой ответ - или приходите к столу с чем-то совершенно другим! :)

Ответ 1

Лом-подход и использование фоновых изображений

http://jsfiddle.net/P5CKC/2/

<ul class="menu">
    <li><span>Li</span></li>
    <li><span>Li</span></li>
    <li><span>Li</span></li>
    <li class="change"><span>Li</span></li>
    <li><span>Li</span></li>
</ul>

CSS

ul.menu {
    overlflow: hidden;
}
ul.menu li {
    float: left;
    font-family: Verdana, Arial, Helvetica, sans-serif;
    font-size: 10pt;
    text-align:center; 
    margin: 0 0 0 -25px; 
    width: 152px;
    line-height: 35px;
    height: 35px;
    background: url(../bct-white.png) no-repeat;
    color: #0091c1;
}
ul.menu li span {
    background: url(/green.png) no-repeat 5px 6px;
    display: block;
}
ul.menu li.change span {
    background-image: url(/red.png);
}

Совместимость CSS2.0 и браузера

Приложение кода, которое я предоставил, является Css2.0 и должно легко работать в IE7 и выше.

  1. Удалены теги img и реализованы эстетика (изображения) в качестве фона
  2. Дополнительный span должен был быть добавлен, потому что CSS2 допускает только 1 фоновое изображение на элемент
  3. Знак Li держит фон стрелки; тег span держит фон перца
  4. Обновлен id="change" to class="change". ЕСЛИ вы на 100% уверены, что у вас будет только один элемент #change, используйте класс. Это чисто стилизация, и это мешает вам иметь два списка меню на одной странице.
  5. Измените свой стиль CSS немного следующим образом:

Удалено верхнее заполнение и увеличена высота. Таким образом, ваши элементы li имеют одинаковую высоту, но затем добавили line-height: 35px → это лучший способ вертикального центра текста. Утилизация верхнего заполнения работает, но она подвержена плохой несогласованности браузера.

Измените элементы li на float. Плавающие элементы - самый удобный для IE7 метод! Даже IE6 не будет ошибкой, но у меня нет этой старой версии, чтобы протестировать вашу веб-страницу. FYI - ul.menu должен иметь overflow: hidden чтобы очистить поплавки.

position: relative; 
cursor: default;

Если вы не изменили значения по умолчанию, вы можете сохранить эти два свойства. курсор должен быть по умолчанию. Позиция: относительная не нужна - вы не используете абсолютное позиционирование или что-либо, что оправдывает его потребность. Теперь вы можете сохранить их в своей декларации. Мне просто нравится код как "тонкий", насколько это возможно.

заключительные слова:

Взгляните на мой CSS. Обратите внимание, как я использовал ul.menu во всей моей декларации. Вы можете захотеть привыкнуть к тому же; это дает разработчику некоторое представление о том, как выглядит HTML и что более важно - ваш css не будет отменен, если вы решите добавить <div class=menu> позже. В частности .menu img будет применяться к любому тегу изображения в меню div.

Хорошо, это так. Дайте мне знать, если есть какие-либо разъяснения.

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

Ответ 2

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

Если это так, это просто означает, что ваш HTML анализирует содержимое вашего <li> как имеющее разрыв строки - вот почему вы видите проблему. Чтобы решить эту проблему, оберните текст в <li> с помощью <span>. Когда ваш браузер анализирует HTML, он автоматически обрезает пробелы между тегами HTML и автоматически исправляет проблему (без потери форматирования)

Ответ 3

Это странно, но я могу воссоздать проблему в Firefox v22. Очень странная часть заключалась в том, что в jsFiddle, если я просто ударил "Tidy Up", а затем ударил "Run", и проблема была решена. Как заметил Мэтью R, это, вероятно, связано с удалением дополнительного белого пространства.

Сломанный: enter image description here

Tidy Up, Run и Fixed enter image description here

Здесь альтернативный метод с использованием фоновых изображений:

Рабочий пример

.menu li {
  cursor: default;
  font-family: Verdana, Arial, Helvetica, sans-serif;
  font-size: 10pt;
  list-style-type: none;
  position: relative;
  text-align: center;
  margin: 0 0 0 -25px;
  padding: 8px 0 0 10px;
  width: 118px;
  height: 20px;
  display: inline-block;
  background-image: url(http://modmyi.com/attachments/forums/iphone-4-4s-new-skins-themes-launches/465481d1282224308-classified-hd-cydia-released-goldborder.png), url(http://i.stack.imgur.com/dmHl0.png);
  background-position: 0% 0%, 44% 75%;
  background-size: 128px, 18px;
  background-repeat: no-repeat;
  color: #0091c1;
}

.menu img {
  display: inline;
  vertical-align: -25%;
  padding-right: 6px;
}

#change:hover {
  background-image: url(http://modmyi.com/attachments/forums/iphone-4-4s-new-skins-themes-launches/465481d1282224308-classified-hd-cydia-released-goldborder.png), url(http://www.chiletownhotsauce.com/images/stories/Red%20bell%20pepper.jpg);
  background-repeat: no-repeat;
  background-position: 0% 0%, 44% 75%;
  background-size: 128px, 18px;
}
<ul class="menu">
  <li>li</li>
  <li>li</li>
  <li>li</li>
  <li id="change">li</li>
  <li>li</li>
</ul>

Ответ 4

Я думаю, что ваша проблема связана с box model и display:inline-block. Когда я использую display:inline-block в горизонтальных меню, я также использую четкое исправление для родителя и float:left; с детьми.
В этом примере css я помещаю некоторые значения в .menu которые могут быть унаследованы, и я использовал overflow:hidden; для устранения ясного исправления. Затем я использовал float:left; в li чтобы принудительно их закрыть и избежать каких-либо странных интервалов, вызванных настройками браузеров по умолчанию. И затем я изменил значение vertical-align на middle для изображения. При переключении display:none; с inline, все это выглядело правильно для меня. Я не тестировал во всех перечисленных браузерах. Я также использовал первый кусок CSS для css reset, который может быть избыточным, но я всегда нахожу его полезным для JSFiddle.

* {
    margin:0;
    padding:0;
}
.menu {
    font-family: Verdana, Arial, Helvetica, sans-serif;
    font-size: 10pt;
    list-style-type: none;
    color: #0091c1;
    overflow:hidden;
}
.menu li {
    cursor: default; 
    position: relative; 
    text-align:center; 
    /* margin: 0 0 0 -25px; */
    padding: 8px 0 0 0;
    width: 118px;
    height: 20px;
    display: inline-block;
    float:left;
    background-image: url(http://modmyi.com/attachments/forums/iphone-4-4s-new-skins-themes-launches/465481d1282224308-classified-hd-cydia-released-goldborder.png);
    background-repeat: no-repeat;
}

.menu img {
    display: inline;
    /* vertical-align: -25%; */
    padding-right: 6px;
    vertical-align:middle;
}

Ответ 5

Чтобы устранить проблему (появление), измените вертикальное выравнивание изображений значков, содержащихся в меню:

.menu img {
    display: inline;
    vertical-align: top;
    margin-top: 2px;
    padding-right: 6px;
}

В затронутых браузерах дополнительное изображение (с display: none;) изменяло высоту содержащего элемента. Установка display: none; <img> display: none; означало, что display: inline; установка больше не применяется и была помещена под первым изображением.

Просто наличие дополнительного <img> отображения в строке исправляет вертикальное выравнивание, но, очевидно, не устраняет проблему, так как изображение нужно скрывать, не изменяя положение текста.

Это исправление изменяет вертикальное выравнивание от процента (-25%) до фиксированной позиции, избегая любых (ложных) различий в высоте содержащего элемента. Затем я установил верхний край изображения, чтобы получить желаемый интервал от верхнего края элемента.

Обновить

Это исправление нарушает отображение в IE9 - такое же появление, как IE7, без этого исправления.

Ответ 6

Вы допустили ошибку с линией высоты вместо 35px, дали 23px

<ul class="menu">
  <li><span>Li</span></li>
  <li><span>Li</span></li>
  <li><span>Li</span></li>
  <li class="change"><span>Li</span></li>
  <li><span>Li</span></li>
</ul>
ul.menu {
  overlflow: hidden;
}
ul.menu li {
  float: left;
  font-family: Verdana, Arial, Helvetica, sans-serif;
  font-size: 10pt;
  text-align: center;
  margin: 0 0 0 -25px;
  width: 152px;
  line-height: 23px;
  list-style: none;
  height: 35px;
  background: #ccc;
  color: #0091c1;
}
ul.menu li span {
  background: url(http://i.stack.imgur.com/dmHl0.png) no-repeat 5px 6px;
  display: block;
}
ul.menu li.change span {
  background-image: url(/red.png);
}

проверить выход

jsfiddle-ссылка

enter image description here