带有 CSS 显示的元素:无;破坏布局 - 导致错位
Posted
技术标签:
【中文标题】带有 CSS 显示的元素:无;破坏布局 - 导致错位【英文标题】:Element with CSS display: none; breaking layout - causing misalignment 【发布时间】:2013-07-09 13:52:06 【问题描述】:我有一个基本菜单,由水平对齐的列表 (<li>
) 组成,每个列表都包含一个图标图像和一些文本:
其中一个<li>
包含一个带有display: none;
的额外图像,以便可以切换图标(在本例中从绿色变为红色辣椒。
问题是它在某些浏览器上无法正确对齐,如上图所示。我的理解是,与visibilty: hidden;
相比,带有display: none;
的元素不应该影响任何其他元素的位置,并且应该像不存在一样呈现?
无法正确呈现的浏览器是 Google Chrome 和 Safari - 但仅限于 MacOS(!?) 和 IE7(我知道,我知道...)在 Windows 上。我测试过的所有其他浏览器/操作系统组合都可以正常工作。
这是 html:
<ul class="menu">
<li><img src="/green.png">li</li>
<li><img src="/green.png">li</li>
<li><img src="/green.png">li</li>
<li id="change">
<img src="/red.png" style="display: none;">
<img src="/green.png">
li
</li>
<li><img 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 的浏览器 hack,因为它无法识别来自基于条件导入 (<!--[if lte IE 7]>
) 的单独样式表的内联块:
.menu li
zoom: 1;
display: inline;
虽然,很明显,无论操作系统如何,Chrome 和 Safari 都不会加载该样式,因此不会在 Mac 上引起我的问题。
我知道最快的解决方案是重构 HTML 和 javascript 对图标的显示/隐藏的操作,但我真的很想知道是什么导致了这个问题以及如何解决它。
更新
我已经找到原因了。基本上,<img>
元素上的display: none;
元素样式会覆盖.menu img
规则中的inline
。删除它,然后在block
和inline
之间切换可以让您重现该问题。这显然是一个浏览器错误,虽然元素没有显示为内联或块元素,但对布局没有影响。
jsFiddles
Issue with Chrome and Safari on Macs only
Issue with extra CSS for IE7 only
注意!对我来说,使用 IE7 无法正确加载 Fiddle 页面,但结果 iFrame 的直接链接是 http://fiddle.jshell.net/z4dU7/3/show/
赏金更新!!!
我在下面发布了一个修复程序,但它实际上在 IE9 中引入了相同的布局问题!请随时改进或改进我的答案 - 或以完全不同的方式来到桌面! :)
【问题讨论】:
我认为我们需要看到这一点才能为您提供帮助。我做了一个快速的小提琴,无法重现这种行为 - display:none 从布局中删除了图像(应该如此)。也许#change
应用了其他样式?
这个小提琴演示在 IE7 中:jsfiddle.net/z4dU7/3 要在 Mac 上查看问题,只需删除最后一个样式规则(从我系统上的 IE 特定样式表中提取)。跨度>
@David 我已经用两个场景的链接更新了我的问题。
你可能还是要考虑使用背景图片,这样它们就不会影响视觉流动。
对不起,它可能已经被建议了,但我很懒,我不想阅读所有的答案。如果你的意思是切换图像,我假设有某种用户触发它的动作。一旦使用一些 javascript 执行此操作,为什么不直接更改图像的 src 属性?由于不会有更多隐藏图像,所以问题应该消失了对吗?
【参考方案1】:
要解决(外观)问题,请更改菜单中包含的图标图像的垂直对齐方式:
.menu img
display: inline;
vertical-align: top;
margin-top: 2px;
padding-right: 6px;
在受影响的浏览器上,附加图像(带有display: none;
)正在改变包含元素的高度。将<img>
设置为display: none;
意味着display: inline;
设置不再应用并且位于第一个图像下方。
仅仅通过内联显示额外的<img>
可以解决垂直对齐问题,但显然不能解决问题,因为需要在不改变文本位置的情况下隐藏图像。
此修复将垂直对齐方式从百分比 (-25%) 更改为固定位置,从而避免包含元素高度的任何(虚假)差异。然后,我设置了图像的上边距,以从元素的上边缘获得所需的间距。
更新
此修复会破坏 IE9 中的显示 - 外观与没有此修复的 IE7 相同。
【讨论】:
您可以尝试将隐藏图像的宽度和高度设置为 1 或 0。这样即使它们以某种方式影响布局,它也不可见。【参考方案2】:这是一个奇怪的问题,但我可以在 Firefox v22 中重现该问题。真正奇怪的是,在jsFiddle 中,如果我只是点击“整理”然后点击“运行”,问题就解决了。正如Matthew R mentioned,这可能是由于额外的空白被删除了。
破碎:
整理、运行和修复
这是使用背景图像的另一种方法:
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】:元素之间有空格。您的其他列表项都没有那个空格。尝试删除这些元素之间的所有空格,看看是否能解决您的问题。
如果是这样,则仅表示您的 HTML 将 <li>
的内容解析为有换行符 - 这就是您看到问题的原因。要解决此问题,请使用 <span>
将 <li>
中的文本包装起来。当您的浏览器解析 HTML 时,它会自动修剪 HTML 标记之间的空白并自动修复问题(不会丢失您的格式)
【讨论】:
【参考方案4】:报废方法和使用背景图片
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及以上运行。
-
删除了
img
标记,并将美学(图像)作为背景实现
必须添加额外的 span
,因为 CSS2 只允许每个元素 1 个背景图片
李标签持有箭头背景; span 标签保存辣椒背景
将id="change"
更新为class="change"
。除非您 100% 确定您将只有一个 #change 元素,否则请使用类。这纯粹是样式设置,它可以防止您在同一页面上拥有两个菜单列表。
对 CSS 样式进行了如下微调:
移除顶部填充并增加高度。因此,您的 li 元素的高度相同,但随后添加了 line-height: 35px
-> 这是垂直居中文本的最佳方式。使用顶部填充可以工作,但容易导致浏览器不一致。
将li
元素更改为浮点数。浮动元素是最适合 IE7 的方法!即使 IE6 也不会出错,但我没有那个旧版本来测试你的网页。仅供参考 - ul.menu 必须有 overflow: hidden
才能清除浮动。
position: relative;
cursor: default;
除非您更改了默认值,否则您可以保留这两个属性。光标应该是默认的。 Position: relative 是不必要的——你没有使用绝对定位或任何需要它的东西。现在,您可以将这些保留在您的声明中。我只是希望代码尽可能“苗条”。
最后的话:
看看我的 CSS。请注意我在所有声明中如何使用ul.menu
。您可能希望养成这样做的习惯;这为开发人员提供了一些关于 HTML 外观的见解,更重要的是 - 如果您决定稍后添加 <div class=menu>
,您的 css 将不会被覆盖。具体而言,.menu img
将应用于菜单 div 中的任何图像标签。
好的 - 就是这样。如果有任何澄清,请告诉我。
仅供参考 - 鉴于这个问题很有价值,如果你向我提供背景图片,我可以完善我的代码以 100% 满足你的需求 - 或许可以在编辑你的答案时上传它们。
【讨论】:
+1 我喜欢这个解决方案,并且已经得到了很好的解释。使用内部跨度很好地避免了需要多个背景图像的问题,并且对 HTML 没有太大的修改。 +1。 The right approach。对我来说,使用<img>
s 进行布局就像使用<table>
s 进行布局一样。【参考方案5】:
我认为您的问题在于box model
和display:inline-block
。当我在水平菜单中使用 display:inline-block
时,我也会对父级使用明确的修复,对子级使用 float:left;
。
在这个 css 示例中,我在 .menu
中放置了一些可以继承的值,我使用 overflow:hidden;
来解决明确的问题。然后我在li
中使用float:left;
来强制它们收紧并避免浏览器默认设置导致的任何奇怪间距。然后我将图像的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;
【讨论】:
【参考方案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-link
【讨论】:
以上是关于带有 CSS 显示的元素:无;破坏布局 - 导致错位的主要内容,如果未能解决你的问题,请参考以下文章