おはようございます。時間があるときに、以下のようなサイトを作成しているのですが、この2枚のスクリーンショットは、違うところがあります。どこが違うのかというと、2枚目のやつは、ボックスのコーナーが丸っこくなっていて、いわゆる角丸コーナーと言われるものになっています。
ちょっとお洒落っぽいサイトデザインにしようと思っているのですが、そのためには、角張ったデザインよりも、角が取れたデザインの方が良いかなと考えました。で、角丸コーナーは、FirefoxやWebKit系のSafariやChromeは、以下のような感じでCSSでの指定が可能です。
-moz-border-radius: 10px; // Firefox -webkit-border-radius: 10px; // Webkit系
問題は、これらのCSSに対応していないOperaやIEです。Operaは、近い将来にサポートするでしょうけど、IEは、今後数年は期待できないかもです。なので、これら2つのブラウザに対しては、JavaScriptを通じてのアプローチを取ることになります。
IEでは、VMLを利用するのがよさげです。しかも角丸コーナーのためにあるようなroundrectというのが予め実装されているので、これを使うのが簡単そうですが、例えば最初に挙げたサイトショットにあるように、ナビ―ゲーションタブの上側だけ丸っこくしたいとかいう場合の制御が難しいです。なので、VMLを使うにしても、もうちょっと、凝ってみることにします。そもそも角丸コーナーを実現するには、以下のようなアプローチを取るのが自然でしょう。
要は、4つの各コーナーに小さい円を描いて、それをクリッピングすれば良いわけです。これなら、ボーダー半径は、FirefoxやWebkit系で指定する値と同様に振る舞うことが期待出来ます。で、それを実際に書き下したのが以下。
<div style="background:#fffacd; position:absolute; right:-20px; bottom:-20px; width:50px; height:50px; clip:rect(25px 50px 50px 25px);"> <v:group style="width:50px; height:50px; position:absolute;" coordsize="50,50"> <v:oval fillcolor="#fff" strokeweight="20px" strokecolor="#ffd700" style="left:9px; top:9px; width:30px; height:30px;" /> </v:group> </div>
これをIEで見ると、以下のように見えます。なかなか良い感じですね。
残りの角についても同様にすればOKです。ただし、IEのVMLバグなのかどうか分かりませんが、作成したVML画像の位置が1ピクセルぐらい微妙にずれる場合があるようです。理論的には、OKのはずなんですが。。
さて、Operaの場合はどうでしょうか。OperaはVMLはサポートしませんが、代わりにSVGをサポートします。なので、これを用いて、上で述べたようなアプローチを取ればOKですね。大体以下のようなスクリプトでOKでしょう。
function svg_corner(id, location, r, obg){ var d = document, e = d.getElementById(id); if(e.currentStyle.position == 'static'){ e.style.setProperty('position', 'relative', null); } r = r || 10; var svg = d.createElementNS('http://www.w3.org/2000/svg', 'svg'); svg.style.setProperty('position', 'absolute', null); var ibg = e.currentStyle.backgroundColor; ibg = ibg == 'transparent' ? '#fff' : ibg; if(!obg){ var p = e.parentNode; while(p && p.currentStyle.backgroundColor){ obg = p.currentStyle.backgroundColor; if(p.nodeName == "HTML") break; if(obg && obg != "transparent") break; p = p.parentNode; } } obg = (!obg || obg == "transparent") ? "#fff" : obg; var bc = e.currentStyle.borderColor; bc = (!bc || bc == "transparent") ? "#fff" : bc; var bw = parseInt(e.currentStyle.borderWidth); var rect = d.createElementNS('http://www.w3.org/2000/svg', 'rect'); var oval = d.createElementNS('http://www.w3.org/2000/svg', 'circle'); var attr = []; switch (location){ case 'tl' : attr = [r + bw/2, r + bw/2, 'top', -bw, 'left', -bw]; break; case 'tr' : attr = [0, r + bw/2, 'top', -bw, 'right', -bw]; break; case 'bl' : attr = [r + bw/2, 0, 'bottom', -bw, 'left', -bw]; break; case 'br' : attr = [0, 0, 'bottom', -bw, 'right', -bw]; break; } oval.setAttribute('fill', ibg); oval.setAttribute('cx', attr[0]); oval.setAttribute('cy', attr[1]); oval.setAttribute('r', r); oval.setAttribute('stroke', bc); oval.setAttribute('stroke-width', bw + 'px'); rect.setAttribute('fill', obg); rect.setAttribute('width', r * 2 + bw + 'px'); rect.setAttribute('height', r * 2 + bw + 'px'); svg.appendChild(rect); svg.appendChild(oval); svg.style.setProperty(attr[2], attr[3] + 'px', null); svg.style.setProperty(attr[4], attr[5] + 'px', null); svg.style.setProperty('width', r + bw/2 + 'px', null); svg.style.setProperty('height', r + bw/2 + 'px', null); e.insertBefore(svg, e.firstChild); }
これらをまとめると、以下のようなデモンストレーションが出来ます。このデモでは、ID指定した要素に対して角丸を発動していますが、特定のクラス名を持ったものに対して、ということも簡単に出来るでしょう。
上のサンプルでは、ついでにFirefoxやWebkit系でも、スクリプトでボーダー属性を指定するようにしています。このふたつ、指定の仕方が微妙に違うんですよねぇ。ちょっとはまりました。以下の感じ。document.getElementById(id).style.WebkitBorderTopLeftRadius = radius + "px"; // Webkit系 document.getElementById(id).style.MozBorderRadiusTopleft = radius + "px"; // Firefox。leftのLも小文字。
なお、OperaでのSVGの使い方は、「Operaで丸角を実現するCSSを試してみた (解決) 」や「角丸にするためにライブラリを作ってみる 」が参考になりました。
Comments