2010年4月4日 星期日

動態 CSS 選單在瀏覽器中顯示異常

週五有同事遇到了網頁程式中的動態選單無法正常顯示的問題,被 art 提供的 flash 元件遮住大半,仍舊是典型的 CSS menu 顯示異常的問題

處理過太多次了,每次都得花我很多口水精神解釋,這次乾脆著文一篇,下次好直接參考使用

一般 CSS menu 在顯示上會遇到以下的問題,稍作整理
  • 被 flash 物件所覆蓋,這種情況在 Firefox 中沒有發現,其他常見瀏覽器幾乎都會
  • 被 <select /> 網頁元素所覆蓋,目前這種情況只剩下顧人怨的 IE6 會發生

以下程式碼用來試驗各種瀏覽器不同遮蔽的情況
<html>
<head>
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
  <style>
  .menu {
      position: absolute;
      border: solid 1px gray;
      background: #f0f0f0;
      padding: 3px 10px;
      display: none;
  }
  .menu ul {
      list-style: none;
      margin: 0px;
      padding: 0px;
      max-width: 200px;
  }
  .menu a {
      line-height: 150%;
      text-decoration: none;
  }
  .menu a:hover {
      background: #e0e0e0;
  }
  </style>
  <script type="text/javascript">
  var vars = {}, params = {};
  swfobject.embedSWF('http://images.tv.adobe.com/swf/player.swf', 'MSH_MashupViewer_87602', '400', '121', '8',
                     'http://dilbert.com/swf/v1/express_install.swf', vars, params);

  $(document).ready(function () {
      var $menu = $(".menu_pad");
      var $div = $menu.find("div.menu");
      $menu.hover(
          function () {
              var pos = $menu.position();
              var dim = { top: pos.top + $menu.outerHeight(), left: pos.left };
              $div.css(dim).show();
          },
          function () {
              $div.hide();
          });
  });
  </script>
</head>
<body>
  <div>
      <span class="menu_pad">
          Menu
          <div class="menu">
              <ul>
                  <li><a href="javascript:">New</a></li>
                  <li><a href="javascript:">Open</a></li>
                  <li><a href="javascript:">Exit</a></li>
              </ul>
          </div>
      </span>
      <br/>
      <select>
        <option value="1">option 1</option>
        <option value="2">option 2</option>
        <option value="3">option 3</option>
      </select>
      <br/>
      <div id="MSH_MashupViewer_87602"></div>
  </div>
</body>
</html>
在常見瀏覽器的測試顯示結果如下表列出


IE 6 這種結果,難怪連狗都嫌 XD


IE 7


IE 8


IE 9 preview


Firefox 3.6.2


Safari 4.0.5


Opera 10.51


Chrome 5.0.360.4 Dev

在 flash 的部分,可以在 Adobe 官網上找到解決方式,請參考 Flash content displays on top of all DHTML layers 的指引加入 wmode 參數並指定為 transparent

在 <select /> 的部分,則可以用一份透明的 iframe 來幫忙遮住強勢的 select 元素,而且它得剛好墊在需要被保護的顯示元件之下

修改後的內容如下,反白的部分是小小的調整
<html>
<head>
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
  <style>
  .menu {
      position: absolute;
      border: solid 1px gray;
      background: #f0f0f0;
      padding: 3px 10px;
      display: none;
  }
  .menu ul {
      list-style: none;
      margin: 0px;
      padding: 0px;
      max-width: 200px;
  }
  .menu a {
      line-height: 150%;
      text-decoration: none;
  }
  .menu a:hover {
      background: #e0e0e0;
  }
  .glass {
      position: absolute;
      filter: alpha(opacity=0);
      -moz-opacity: 0;
      opacity: 0;
      width: 100%;
      height: 100%;
      display: none;
  }
  </style>
  <script type="text/javascript">
  var vars = {}, params = { wmode: 'transparent' };
  swfobject.embedSWF('http://images.tv.adobe.com/swf/player.swf', 'MSH_MashupViewer_87602', '400', '121', '8',
                     'http://dilbert.com/swf/v1/express_install.swf', vars, params);

  $(document).ready(function () {
      var $menu = $(".menu_pad");
      var $glass = $("<iframe frameBorder='0' class='glass'></iframe>");
      var $div = $menu.find("div.menu").before($glass);
      $menu.hover(
          function () {
              var pos = $menu.position();
              var dim = { top: pos.top + $menu.outerHeight(), left: pos.left };
              $div.css(dim).show();
              dim.width = $div.outerWidth();
              dim.height = $div.outerHeight();
              $glass.css(dim).show();
          },
          function () {
              $div.hide();
              $glass.hide();
          });
  });
  </script>
</head>
<body>
  <div>
      <span class="menu_pad">
          Menu
          <div class="menu">
              <ul>
                  <li><a href="javascript:">New</a></li>
                  <li><a href="javascript:">Open</a></li>
                  <li><a href="javascript:">Exit</a></li>
              </ul>
          </div>
      </span>
      <br/>
      <select>
        <option value="1">option 1</option>
        <option value="2">option 2</option>
        <option value="3">option 3</option>
      </select>
      <br/>
      <div id="MSH_MashupViewer_87602"></div>
  </div>
</body>
</html>
這樣一來,幾乎常見瀏覽器的顯示情況就都在控制內了

完整的範例程式碼下載

沒有留言: