需要一种方法来强制在MSIE8中重新绘制<select>。

16

使用模拟的媒体查询来改变页面中 <select> 的字体大小。

我也遇到了其他浏览器的问题,但是我暂时通过从DOM中分离元素,等待一小段时间后重新附加它们来解决这些问题。

但在MSIE8中,<option> 的高度仍然与设置的最大字号相等,即使已经不再应用该样式。

http://fiddle.jshell.net/U3bzT/show/light/

期望结果:

切换到更小的字体大小时,font-size 被更新,但是 <option> 的行高/高度没有被更新。

对于 select-multiple 和 select-one 都会出现此问题

有什么方法可以解决这个问题吗?

注:<select> 可能已经绑定了事件,因此无法使用复制品

<script>

// just some code to simulate media query on/off state
var select;

setTimeout(function(){

    select = document.getElementsByTagName("select")[0];

    select.style.fontSize='40px';
    webkitFix();

    setTimeout(function(){
        select.style.fontSize='10px';
        webkitFix();
    },5000);

},5000);

function webkitFix(){
    document.body.removeChild(select);
    setTimeout(function(){ document.body.appendChild(select); }, 1);
}

</script>

<select multiple size="6" style="font-size:10px">
    <option>AAAAAA1</option>
    <option>BBBBBB2</option>
    <option>AAAAAA3</option>
    <option>BBBBBB4</option>
    <option>AAAAAA5</option>
    <option>BBBBBB6</option>
    <option>AAAAAA7</option>
    <option>BBBBBB8</option>
    <option>AAAAAA9</option>
</select>

2
你为什么不使用jQuery? - huysentruitw
4
@RobertMcKee: IE8 mode != IE8 @RobertMcKee说:IE8模式并不等同于IE8。 - huysentruitw
1
@WouterHuysentruit 在绝大多数情况下它们的作用相同,但确实不完全相同。 - Robert McKee
2
如果您想尝试,可以在IETester中重现它。 - user652649
2
@WouterHuysentruit: IE8 模式 !== IE8 #javascript - zigo
显示剩余15条评论
4个回答

11

这对许多开发人员多年来一直是一个大头痛。没有任何解决方法可以修复这个问题而不使用JS和CSS的替代标记。这是由于Internet Explorer中选择框设计的严格性。一旦通过<= IE8渲染了一个选择框,就无法通过class'和/或JS实际修改外观,正如你所发现的那样。即使在呈现时使用CSS修改选择框的外观也非常有限,并且留下了许多开发人员寻找替代方案。值得庆幸的是,在较新的IE版本(其中8比7好得多,虽然仍然非常缺乏)中,选择框更加可变。

我可以向您指出一些支持此说法的资源,其中一些在stackoverflow上。

许多与此相关的问题在SO上也没有得到解答,再次出于这个原因,无法以您希望解决它的方式解决这个问题。

提供了许多解决方法,其中涉及以下几种技术。

  • 使用用javascript呈现并具有select框外观的样式化<ul>
  • JS / jQuery解决方案,将选择框替换为以上和基于<div>的解决方案

对于您特定的问题,如果不采用DOM替换技术,则会发现自己一直在撞墙。

为您提供一些资源,提供解决方案,以及在此处提到使用jQuery / javascript的其他答案。

总之,如果不使用 IE 的 polyfill 或采用彻底的 select box 替代策略,很抱歉您的问题将无法解决。


1
我不确定为什么会有人踩,因为这是正确的,并且有证据支持。至少你可以留下一条评论解释为什么这显然是错误的? - David Barker
1
这些IE问题让我想起了《浮士德博士》中的一句话:“为什么,这是地狱-我还没有走出来!”。但事实上,无论使用哪种浏览器,选择框都不是很好用:它们非常不灵活,而且没有什么功能是无法通过单选框或复选框和标记语言实现的。一年前,Paul Irish呼吁W3C和浏览器开发人员制作更好的<select>,推荐使用Select 2(Chosen的改进版)。 - Barney
所以这个问题实际上是之前已经被问过很多次的重复问题。 - Huangism

2
我尝试了很多方法,包括height, line-height, offsetHeight, padding, margin, word-spacing, letter-spacing, white-space, text-indent, -ms-word-break, -ms-word-wrap, line-break和其他许多方法...甚至试图了解IE hasLayout 属性以及如何解决一些问题。但是,IE8的这个错误/问题似乎无法解决...如果您不想像@DavidBarker建议的那样使用插件,也不想像@Akki619那样复制原始下拉菜单,那么我能想到的最好的方法就是:
if($isIE8) {// alternative solution for IE8


    setTimeout(function() {
        var w = parseInt(select.style.width, 10);
        var h = parseInt(select.style.height, 10);
        // change select zoom rather than changing the font-size (since font-size is buggy)
        //select.style.fontSize = '40px';
        select.style.zoom = '400%';// almost equal to '40px'
        var longestOptionText = 1;
        // for the below, I used jquery to get the longest option text, you might replace it with some javascript
        $('select option').each(function() {
            var txtlen = $(this).text().length;
            if(txtlen > longestOptionText) {
                longestOptionText = txtlen;
            }
        });
        // -------- end of jquery usage
        select.style.width = (parseInt(select.style.fontSize, 10) * longestOptionText) + 'px';
        select.style.height = (parseInt(select.style.fontSize, 10) * longestOptionText) + 'px';
        setTimeout(function() {
            //select.style.fontSize = '10px';
            select.style.zoom = '100%';
            select.style.width = w + 'px';
            select.style.height = h + 'px';
        }, 5000);
    }, 5000);


} else {// all other browsers

    // keep your original code here..

}

结果看起来与您预期的有些相似,但现在有一个小问题,如果缩放设置大于100%,则滚动条垂直栏将不可见。解决方案:增加选择高度以使所有选项可见。


2
(注意:由于您的编辑建议不使用克隆,请忽略此答案。如果有人遇到这个问题并想要进行克隆,请使用此方法,这就是我不删除答案的原因)。
如果您能够成功将克隆放入选择标签,即使事件已连接,也几乎不可能获得所需结果。以下是具体实现方法的代码。
浏览器检查:
Chrome 28.0.0
Firefox 22.0
IE 7.0/8.0
1. 使用克隆选择来管理所需结果。
代码如下:
!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title> - jsFiddle demo</title>

  <script type='text/javascript' src='/js/lib/dummy.js'></script> 

  <link rel="stylesheet" type="text/css" href="/css/result-light.css">

  <style type='text/css'>
  </style>    

<script type='text/javascript'>

window.onload=function(){
var select;

function webkitFix(){
    document.body.removeChild(select);
    setTimeout(function(){ document.body.appendChild(select); }, 1);
}

setTimeout(function(){
    select = document.getElementsByTagName("select")[0];        
    select.style.fontSize='40px';       
    webkitFix();


    setTimeout(function(){
    select.style.visibility = 'hidden';
    select1 = document.getElementsByTagName("select")[0];
    select1.style.visibility = 'visible';    
    select1.style.fontSize='10px';
    webkitFix();
    },5000);

},5000);
}     
</script>  

</head>
<body>
  <select id="one" multiple size="6" style="font-size:10px;">
    <option value="AAAAAA1">AAAAAA1</option>
    <option value="BBBBBB2">BBBBBB2</option>
    <option>AAAAAA3</option>
    <option>BBBBBB4</option>
    <option>AAAAAA5</option>
    <option>BBBBBB6</option>
    <option>AAAAAA7</option>
    <option>BBBBBB8</option>
    <option>AAAAAA9</option>
</select>

<select id="two" multiple size="6" style="font-size:10px; position:absolute; visibility:hidden;">
    <option value="AAAAAA1">AAAAAA1</option>
    <option value="BBBBBB2">BBBBBB2</option>
    <option>AAAAAA3</option>
    <option>BBBBBB4</option>
    <option>AAAAAA5</option>
    <option>BBBBBB6</option>
    <option>AAAAAA7</option>
    <option>BBBBBB8</option>
    <option>AAAAAA9</option>
</select>      
</body>  

截图 1:

输入图片描述

截图 2:

输入图片描述

截图 3:

输入图片描述


0
尝试访问选择器上的 offsetHeight。它会强制重新绘制。

1
你所说的访问是指读取吗?因为你不能写入 offsetHeight - huysentruitw
1
阅读,可以。访问并不一定意味着写入。 - probablyup
+1 不需要投反对票,因为这很困难。无论如何,它没有起作用 :( - user652649
你可以在设置字体大小后调整缩放比例为1。如果可以,请告诉我它是否有效。 - Najam Awan
如果你简单地谷歌一下,你会看到有数百个结果推荐读取 offsetHeight,因为浏览器需要重新绘制以计算该值。停止如此精英主义,这样很不吸引人。 - probablyup
2
@ultraviol3tlux 我并没有成为精英主义者的意图。但是,如果你在回答之前测试过这个问题,你就会发现它不起作用,唉... - huysentruitw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接