CSS显示元素:无;打破布局 - 导致错位

时间:2013-07-11 10:21:18

标签: css macos internet-explorer google-chrome safari

我有一个基本菜单,由水平对齐列表(<li>)制成,每个列表都包含一个图标图像和一些文字:

Menu bar

<li>中的一个包含display: none;的额外图像,以便可以切换图标(在此示例中,从绿色到红色辣椒)。 问题是它在某些浏览器上没有正确对齐,如上图所示。我的理解是,与visibilty: hidden;相比,具有display: none;的元素不应该影响任何其他元素的位置,并且应该呈现为好像它不在那里?

无法正确呈现的浏览器是Google Chrome Safari - 但仅限于 MacOS (!?)和(我知道,我知道......)。我测试过的所有其他浏览器/操作系统组合都可以正常工作。

这是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>的元素样式会覆盖inline规则中的.menu img。删除它,然后在blockinline之间切换可以重现该问题。这显然是一个浏览器错误,虽然元素没有显示为内嵌或块元素应该对布局没有影响。


jsFiddles

Issue with Chrome and Safari on Macs only

Issue with extra CSS for IE7 only

请注意!对我来说,使用IE7无法正确加载小提琴页面,但结果iFrame的直接链接是http://fiddle.jshell.net/z4dU7/3/show/

赏金更新!!!

我在下面发布了一个修复程序,但实际上在IE9中引入了相同的布局问题!请随意改进或改进我的答案 - 或者以完全不同的方式来到桌面! :)

6 个答案:

答案 0 :(得分:11)

废料处理方法和使用背景图像

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. 李标签持有箭头背景; span标签持有胡椒背景
  4. id="change"更新为class="change"。除非您100%确定只有一个#change元素,否则请使用一个类。这纯粹是样式,它可以防止你在同一页面上有两个菜单列表。
  5. 调整了CSS样式,如下所示:
  6. 移除顶部衬垫并增加高度。所以你的li元素是相同的高度然后添加line-height: 35px - &gt;这是垂直居中文本的最佳方式。 Utlizing top padding有效,但它很容易出现浏览器不一致的情况。

    li元素更改为浮点数。浮动元素是IE7最友好的方法!即使IE6也不会出错,但我没有那个旧版本来测试你的网页。仅供参考 - ul.menu必须overflow: hidden来清除浮动。

    position: relative; 
    cursor: default;
    

    除非您更改了默认值,否则可以保留这两个属性。游标应该是默认的。位置:亲属是不必要的 - 你没有使用绝对定位或任何保证其需要的东西。现在,您可以在声明中保留这些内容。我只是希望代码尽可能“苗条”。

    最后的话:

    看看我的CSS。请注意我在所有声明中如何使用ul.menu。你可能想养成同样的习惯;这为开发人员提供了一些关于HTML外观的信息,更重要的是 - 如果您决定稍后添加<div class=menu>,那么您的CSS将不会被覆盖。具体而言,.menu img将适用于菜单div中的任何图像标记。

    好的 - 就是这样。如果有任何澄清,请告诉我。

    仅供参考 - 看到这个问题有一个赏金,如果你向我提供背景图片,我可以100%完善我的代码以满足你的需求 - 也许可以在你的答案编辑中上传它们。

答案 1 :(得分:3)

元素之间有空格。您的其他列表项都没有该空格。尝试删除这些元素之间的所有空格,看看是否能解决您的问题。

如果是这样,只是意味着您的HTML正在将<li>的内容解析为有换行符 - 这就是您遇到问题的原因。要解决此问题,请使用<li><span>中的文字换行。当您的浏览器解析HTML时,它会自动修剪HTML标记之间的空白并自动修复问题(不会丢失格式)

答案 2 :(得分:2)

这是一个奇怪的,但我可以在Firefox v22中重新创建这个问题。真正奇怪的部分是在jsFiddle,如果我只是点击“Tidy Up”,然后点击“Run”,问题就解决了。如Matthew R mentioned,这可能是由于删除了额外的空白区域。

断裂: enter image description here

整理,运行和修复 enter image description here

这是使用背景图像的另一种方法:

<强> Working Example

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

答案 3 :(得分:1)

我认为您的问题在于box modeldisplay:inline-block。当我在水平菜单中使用display:inline-block时,我还会对父级使用明确的修复,并为子级使用float:left;
在css的这个例子中,我在.menu中放了一些可以继承的值,我使用overflow:hidden;来解决明确的问题。然后我在float:left;中使用了li来强制它们,并避免由浏览器默认设置引起的任何奇怪的间距。然后我将图片的vertical-align值更改为middle。使用display:none;切换inline时,对我来说一切正常。我没有在列出的所有浏览器中测试。我还在css reset使用了第一块CSS,这可能是多余的,但我总觉得它在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;
}

答案 4 :(得分:0)

要解决问题的(外观),请更改菜单中包含的图标图像的垂直对齐方式:

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

在受影响的浏览器上,附加图像(display: none;)正在改变包含元素的高度。将<img>设置为display: none;意味着display: inline;设置不再应用并位于第一张图片下方。

只是让额外的<img>显示内联修复垂直对齐,但显然不能解决问题,因为图像需要隐藏而不改变文本的位置。

此修正将垂直对齐方式从百分比(-25%)更改为固定位置,从而避免包含元素高度的任何(虚假)差异。然后我设置图像的上边距以从元素的上边缘获得所需的间距。

<强>更新

此修复程序破坏了IE9中的显示 - 与没有此修复程序的IE7相同。

答案 5 :(得分:0)

你的线高错误了 而不是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-link

enter image description here