Hatena::ブログ(Diary)

latest log このページをアンテナに追加 RSSフィード

2009-07-19

IE6 で borderColor="transparent" が機能しない

uuAltCSS+.js のコードリード用のエントリです。コードを知らない方には無意味なエントリです。

border-radius: 用の処理に、「ボーダー部分をcanvasで描画し、元々borderが設定されていたノードの borderColor を透明にする」という処理がありますが、IE6 は borderColor="transparent" が機能しません(colorが赤なら、赤いボーダーが描画されてしまう)

単純に、border = "0px none" としてしまうと、再描画時に ノード の幅/高さを求める処理で問題が発生します(ボーダー幅がなくなったため、元々のサイズより小さく再描画されてしまう)。

これを回避するため以下のコードを追加しました。

処理の概要は

  • borderColor = "transparent" と同じように振舞うには、マージンにボーダー幅を含めた状態で描画する
  • ただし幅/高さの再計算の直前に、元の状態(ボーダーが設定されている状態)に戻し要素のサイズを再計算する。再計算が終わったら、border = "0px none" を設定する。

です。

function boxshadow() {
  (略)
+   if (_ie6) {
+     // オリジナルの値を保存する
+     prop.ie6borderorg = {
+       marginTop: cs.marginTop,
+       marginLeft: cs.marginLeft,
+       marginRight: cs.marginRight,
+       marginBottom: cs.marginBottom,
+       borderTopWidth: cs.borderTopWidth,
+       borderLeftWidth: cs.borderLeftWidth,
+       borderRightWidth: cs.borderRightWidth,
+       borderBottomWidth: cs.borderBottomWidth
+     };
+     // 上書用の値を事前に作成しておく
+     prop.ie6borderfix = {
+       marginTop: (prop.NMT + prop.NBT) + "px",
+       marginLeft: (prop.NML + prop.NBL) + "px",
+       marginRight: (prop.NMR + prop.NBR) + "px",
+       marginBottom: (prop.NMB + prop.NBB) + "px",
+       border: "0px none"
+     };
+   }
  (略)
}

function boxshadowRecalc() {
  var nodeProp = _plan.boxshadow, v, i = 0, iz = nodeProp.length,
      prop;

  for (; i < iz; i += 2) {
    v = nodeProp[i]; // node
    prop = v.uuAltCSSBoxShadow;
    // update rect
+   if (_ie6) { // restore border and margin state
+     _mm.mix(v.style, prop.ie6borderorg);
+   }
    prop.nodeRect = _style.getRect(v);
    prop.viewRect = _style.getRect(prop.view);
    prop.nodeOffset = getOffsetFromAncestor(v, prop.view);
    boxshadowDraw(v, prop, 1);
  }
}

function boxshadowDraw(node, pr, redraw) {
  (略)
  // --- gradient ---
  if (pr.gradtype) {
    (略)
  }
  if (pr.radius) {
    (略)
    if (!redraw) {
      // bg setting
      node.style.backgroundColor = TRANSPARENT;
      node.style.backgroundImage = "none";
-     if (_ie6) {
-       // IE6 bug 'borderColor = "transparent";' unsupported
-       node.style.paddingTop = pr.NBT + pr.NPT;
-       node.style.paddingLeft = pr.NBL + pr.NPL;
-       node.style.paddingRight = pr.NBR + pr.NPR;
-       node.style.paddingBottom = pr.NBB + pr.NPB;
-       node.style.border = "0px none";
-     } else {
-       node.style.borderColor = TRANSPARENT;
-     }
+     node.style.borderColor = TRANSPARENT;
+   }
+   if (_ie6) {
+     // IE6 'borderColor = "transparent";' unsupported
+     _mm.mix(node.style, pr.ie6borderfix);
    }
  }
  (略)
}

コード追加前(before)

上記のコードを追加する前はこのように画像の下が身切れる現象が発生していました。

f:id:uupaa:20090719010106j:image

この現象は以下の条件が重なった場合に発生します。

  • IE6
  • ページ表示直後の一度だけ発生する
  • nodeの親にボーダーが設定されていない
  • nodeにwidthが明示されていない
  • nodeがスクロールして表示される位置(ページの下方)に設置されている

また、描画中にリドロー(再描画)も発生しています。

この状態は、window サイズを拡大/縮小することでリセットできます。

f:id:uupaa:20090719010108j:image

コード追加後(after)

対策コード追加後は以下のようになります。

f:id:uupaa:20090719010109j:image

他のブラウザと同様のレンダリングになり、身切れる現象は回避できましたが、今度はリドローすると、要素の高さが若干変化(増えたり減ったり)する新たな現象が発生するようになりました。

f:id:uupaa:20090719010107j:image

こちらについては有効な対策方法が現在見つかっていないため、宿題です。

ロジックの見直しを行い、上記制限はなくなりました。