IT戦記

プログラミング、起業などについて書いているプログラマーのブログです😚

クリックジャッキングの本質的な解決策

誰か書いてそうだけど、気にせずに投下

現実的な解決策ではなくて、本質的な解決策

クリックジャッキングはそもそも CSS の問題なので CSS の枠組みで解決すればいい。

CSS での解決策

具体的には、以下のルールをユーザースタイルシートに追加すればいい。

 * { opacity: 1 !important }

CSS2, CSS2.1, CSS3 では、ユーザースタイルシートの !important な宣言は他のどの宣言よりも優先されるはずなので、ちゃんと仕様を満たしているブラウザを使っていれば問題ないはず。
IE の場合は、 opacity じゃなくて filter を。。というか、オプションで何か filter とか無効に出来た気がするけど、忘れた><)
ユーザースタイルシートは、 IE, Firefox, Opera, Safari ほとんどのブラウザで使うことができる。
あと、 iframe の大きさを制限しておくとさらに良いかもしれない。

 iframe {
   min-height: 200px !important;
   min-width: 200px !important
 }

ただ

すべての要素が透明にできなくなってしまうのは寂しいなあ。。。

ちなみに

iframe { opacity: 1 !important }

のように iframe だけにターゲットを絞ることはできない。親要素や祖先要素が透明になる可能性があるから。

追記

でも、よく考えると iframe の上に div やら何やらを載せてボタン意外を隠してしまうという手もあるなあ。ボタンは見えてるんだけど、ボタンの名前が「送信」とかだったら分からないな。
やっぱ、 CSS オフか iframe { display: none !important } が本質的なのかなあ。やっぱり現実的ではないな。

CSS のセレクタの名前の整理

はじめに

CSSセレクタ」っていうと以下のようなものを想像すると思うんですけど

div.container ul > li

じゃあ、

などなど色々と疑問が出てくる訳で、どういう名前で呼べばいいか。自分のために書いておく。
これ系のエントリでは、以下のエントリが一番参考になります
http://d.hatena.ne.jp/kiririmode/20080516/p1

Selectors group

カンマで区切られたセレクタのリスト

div.container ul > li, div#hoge.hoge ~ span#fuga.fuga

Selector

カンマで区切られてる一個一個のやつ

div.container ul > li

とか

div#hoge.hoge ~ span#fuga.fuga

Combinator

>

とか

+

とか

~

空白とか

Sequence of simple selectors

Combinator で区切られてる一個一個のやつ

div.container
ul
li
div#hoge.hoge
span#fuga.fuga

Simple selector

div#hoge.hoge

でいうと

div
#hoge
.hoge

あと

Combinator と Sequence of simple slectors を組み合わせた

~ span#fuga.fuga

とか

> li

みたいなものにも名前が欲しいなあ。プログラムではこの単位で扱うことが多いので。
Combinator and sequence of simple seletors とでも読んでおくか。

うーん

JavaScript でこれを扱うオブジェクトを作るときは

var caoss = new CSSCombinatorAndSequenceOfSimpleSelectors();

とかになるのかな><長い><
カオス><

IE で一時的に要素のスタイルを変更する

いろいろためしたけど、以下が一番楽

// 変更
element.runtimeStyle.cssText = ' width: 100%; height: 100%';

// 戻す
element.runtimeStyle.cssText = '';

特に、戻すときに cssText 以外のプロパティを空にしても、おかしな挙動をするので cssText を使うといい。

しかも IE だけは、 CSSStyleSheet オブジェクトにも cssText が使える

// これも IE だけ
var sheet = document.createStyleSheet();

sheet.cssText = 'div { hoge: hoge; fuga: fuga } div div { piyo: piyo }';
sheet.cssText = '';

CSS Selector の最大の欠点

先頭に Combinator を置けないこと

// 以下のようなことができない
elm.querySelectorAll('> div');
elm.querySelectorAll('+ div');
elm.querySelectorAll('~ div');

Selector が仕様化されたときは、たぶん、サブツリーを起点に使われることなんて想像してなかったんだろうなあ。
その点、 jQuery はすごいなあ。

Web 標準的な CSS の値変換方法(px → em など)(訂正あり)

はじめに

W3C の仕様に CSS の値を変換が可能なオブジェクトが定義されていることに気がついたのでメモしておきます。

まず CSSStyleDeclaration オブジェクトを取得する

例えば、

var decl = element.style;

または、

var decl = getComputedStyle(element, '');

http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration

CSSStyleDeclaration オブジェクトから getPropertyCSSValue という関数を使って CSSValue オブジェクトを取得する
var val = decl.getPropertyCSSValue('width')

http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue

以下のようにして様々な単位の値が取得できる

ただし、 CSSValue が CSSPrimitiveValue の場合だけ

if (!(val instanceof CSSPrimitiveValue)) throw Error();

// センチメートル単位で値を取得
var num = val.getFloatValue(CSSPrimitiveValue.CSS_CM);

http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue

対応ブラウザ

たぶん WebKit (Safari の開発版) だけだと思います。
WebKit++

追記

Firefox 3, Opera 9.5 でも対応しているようです。
ただ、いろいろためすと変換できない単位があったりします。
以下、参照

訂正

ちゃんと仕様のほうを確認してみました。
すると、以下のように記述されていました。

Conversions are allowed between absolute values (from millimeters to centimeters, from degrees to radians, and so on) but not between relative values. (For example, a pixel value cannot be converted to a centimeter value.)

http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue

絶対値間の変換は認められるが、相対値の変換は認められない。
ということは、どうやら WebKit の独自拡張ということなんですね。
WebKit--

めも

このメモについて

  • id:amachang の私的な学習目的
  • IE6 の標準モードに関するバグ

いろいろとポイント

  • layout
    • IE6 の視覚整形モデルの中で要素は、大きく分けて layout を持つ要素と、 layout を持たない要素に分けることができる。
    • layout を持つ要素とは、自分のサイズや位置に責任を持つ要素である。
    • layout を持つ要素は、四角形の領域を作る。
    • layout を持たない要素は、直近の layout を持つ要素のサイズおよび位置と、そこの間にあるすべての要素の margin, padding, border によってその開始点、折り返し点が決まる。
    • layout を持たない要素は、四角形の領域を作らない。上下左右の間隔を保持しているだけに過ぎない。
    • layout を持たない要素間の上下マージン(相殺されるマージン)は二つの要素間の共有のもので、ある要素特有の管理下にはない。(つまり、要素のレンダリングのバグを直したいときにマージンは影響しないことが多い)
    • 要素に layout を与える場合は style に zoom: 1 を指定すればいい

(border-left または border-right) と padding-bottom の問題

以下の HTML によって発生する

http://amachang.art-code.org/ierendering/000.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<title>IE Rendering Test</title>
</head>
<body>

    <!-- border-left と padding-bottom を持つ layout を持たないブロックレベル要素 -->
    <div style="border-left: 1em solid blue; padding-bottom: 1px;">

        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>

        <!-- この要素の最後に layout を持たないブロックレベル要素 -->
        <div>layout を持たないブロックレベル要素</div>

    </div>

    <!-- この要素が 2em (ボーダーの幅 x 2)だけずらされる -->
    <div>ずれてますか?</div>

</body>
</html>
ずれないパターン 1

http://amachang.art-code.org/ierendering/001.html

<body>

    <div style="border-left: 1em solid blue; padding-bottom: 1px;">

        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>

        <!-- この最後の要素をインライン要素にする -->
        <span>layout を持たないブロックレベル要素</span>

    </div>

    <!-- ずれない -->
    <div>ずれてますか?</div>

</body>
ずれないパターン 2

http://amachang.art-code.org/ierendering/002.html

<body>

    <div style="border-left: 1em solid blue; padding-bottom: 1px;">

        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>

        <!-- この最後のノードをテキストノードにする -->
        テキストノード

    </div>

    <!-- ずれない -->
    <div>ずれてますか?</div>

</body>
ずれる幅が違うパターン 1

http://amachang.art-code.org/ierendering/003.html

<body>

    <div style="border-left: 1em solid blue; padding-bottom: 1px;">

        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>

        <!-- border-bottom を付ける -->
        <div style="border-bottom: 1px solid blue;">layout を持たないブロックレベル要素</div>
    </div>

    <!-- 2em ではなくて 1em しかずれない -->
    <div>ずれてますか?</div>

</body>
ずれる幅が違うパターン 2

http://amachang.art-code.org/ierendering/004.html

<body>

    <div style="border-left: 1em solid blue; padding-bottom: 1px;">

        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>

        <!-- padding-bottom を付ける -->
        <div style="padding-bottom: 1px;">layout を持たないブロックレベル要素</div>
    </div>

    <!-- 2em ではなくて 1em しかずれない -->
    <div>ずれてますか?</div>

</body>
ずれないパターン 3

http://amachang.art-code.org/ierendering/005.html

<body>

    <!-- border-bottom を追加 -->
    <div style="border-left: 1em solid blue; border-bottom: 1px solid blue; padding-bottom: 1px;">

        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>

        <div>layout を持たないブロックレベル要素</div>
    </div>

    <!-- ずれない -->
    <div>ずれてますか?</div>

</body>
ずれないパターン 4

http://amachang.art-code.org/ierendering/006.html

<body>

    <!-- layout を与える -->
    <div style="zoom: 1; border-left: 1em solid blue; padding-bottom: 1px;">

        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>

        <div>layout を持たないブロックレベル要素</div>
    </div>

    <!-- ずれない -->
    <div>ずれてますか?</div>

</body>
ずれないパターン 5

http://amachang.art-code.org/ierendering/007.html

<body>

    <div style="border-left: 1em solid blue; padding-bottom: 1px;">

        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>

        <!-- layout を与える -->
        <div style="zoom: 1">layout を持つブロックレベル要素</div>
    </div>

    <!-- ずれない --> 
    <div>ずれてますか?</div>

</body>
ずれる幅が違うパターン 3

http://amachang.art-code.org/ierendering/008.html

<body>

    <div style="border-left: 1em solid blue; padding-bottom: 1px;">
        <!-- からっぽ -->
    </div>

    <!-- 1em ずれる -->
    <div>ずれてますか?</div>

</body>
現象
  • 要素の下辺( margin を考えない)が padding で、最後の子要素が non-layout ブロックレベル要素のときに発生する
  • 最後の子要素がインライン要素の場合に発生しない
  • 最後の子要素に対して borderpadding を指定した場合にずれる幅が変わる(半分になる)

はみ出した箇所が表示されない問題

http://cssbug.at.infoseek.co.jp/detail/winie/b025.html
http://cssbug.at.infoseek.co.jp/detail/winie/b041.html
http://cssbug.at.infoseek.co.jp/detail/winie/b046.html

実際の例と回避

http://amachang.art-code.org/ierendering/009.html

<body>

    <div style="zoom:1; border: 1px solid blue; margin: 2em;">
        あああ
        <div style="border: 1px solid red">端っこ見えてます?</div>
        あああ
        <div style="margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div>
        あああ
        <div style="zoom: 1; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div>
        あああ
        <div style="position: relative; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div>
        あああ
        <div style="zoom: 1; position: relative; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div>
        あああ
    </div>

    <div style="zoom:1; border: 1px solid blue; margin: 2em;">
        あああ
        <div style="margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div>
    </div>

    <div style="zoom:1; border: 1px solid blue; margin: 2em;">
        あああ
        <div style="zoom: 1; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div>
    </div>

    <div style="zoom:1; border: 1px solid blue; margin: 2em;">
        あああ
        <div style="position: relative; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div>
    </div>

    <div style="zoom:1; border: 1px solid blue; margin: 2em;">
        あああ
        <div style="zoom: 1; position: relative; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div>
    </div>

    <div style="border: 1px solid blue; margin: 2em;">
        あああ
        <div style="border: 1px solid red">端っこ見えてます?</div>
        あああ
        <div style="margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div>
        あああ
        <div style="zoom: 1; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div>
        あああ
        <div style="position: relative; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div>
        あああ
        <div style="zoom: 1; position: relative; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div>
        あああ
    </div>

    <div style="border: 1px solid blue; margin: 2em;">
        あああ
        <div style="margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div>
    </div>

    <div style="border: 1px solid blue; margin: 2em;">
        あああ
        <div style="zoom: 1; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div>
    </div>

    <div style="border: 1px solid blue; margin: 2em;">
        あああ
        <div style="position: relative; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div>
    </div>

    <div style="border: 1px solid blue; margin: 2em;">
        あああ
        <div style="zoom: 1; position: relative; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div>
    </div>

</body>

floatclearbackground の問題

layout を持たない親要素の中で floatclear すると背景が margin 領域まで広がる。そして、自分の兄要素の layout を持たないものが消える(消えると言っても実際に消えるわけではなく、「再描画」が伝搬しなくなる。スクロールによって出現する)
この消え方を Peek-a-boo というらしい
http://amachang.art-code.org/ierendering/010.html

<body>

    <div style="margin: 1em; background: gray;">
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
        <div style="float: right">おおお</div>
        <div style="clear: right">かかか</div>
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
        <div style="float: right">おおお</div>
        <div style="clear: right">かかか</div>
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
    </div>

    <div style="margin: 1em; zoom: 1; background: gray;">
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
        <div style="float: right">おおお</div>
        <div style="clear: right">かかか</div>
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
        <div style="float: right">おおお</div>
        <div style="clear: right">かかか</div>
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
    </div>

    <div style="margin: 2em; background: gray;">
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
        <div style="float: right">おおお</div>
        <div style="clear: right"></div>
    </div>

    <div style="zoom:1; margin: 2em; background: gray;">
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
        <div style="float: right">おおお</div>
        <div style="clear: right"></div>
    </div>

    <div style="margin: 2em; background: gray;">
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
        <div style="float: right">おおお</div>
        <div style="clear: right"></div>
    </div>

</body>
基本的には以下の有名なバグも仕組みは同じ

http://www.positioniseverything.net/explorer/peekaboo.html
http://amachang.art-code.org/ierendering/011.html

<body>
    <div style="background: gray">
        <div style="height: 20em; float: left">
            <br />
            <span>&nbsp;Float&nbsp;
                <br /><br />
                <a href="#">&nbsp;test link&nbsp;</a>
            </span>
        </div>
        This is bare text. <a href="#">Test link</a> 
        <div style="border: 3px solid #f00; background: #dde;">This is text inside a div. <a href="#">Test link</a></div>
        This is bare text. <a href="#">Test link</a>
        <div style="border: 3px solid #0c0; background: #dde;">This is text inside a div. <a href="#">Test link</a></div>
        This is bare text. <a href="#">Test link</a>
        <div style="border: 3px solid #00f; background: #dde;">This is text inside a div.  <a href="#">Test link</a></div>
        This is bare text. <a href="#">Test link</a>
        <div style="clear: left">Clearing div</div>
        <div style="border: 3px solid #00f; background: #dde;">This div is after the cleared div. (purple box) If cleared div 
        does not touch float, bug is not triggered. <a href="#">Test link</a></div>
    </div>
</body>
float よりも clear が原因

float というよりもボックス内で clearance マージンが設定されたかどうかで発生するかが決まる。
たとえば、コンテンツを文字で満たして float 要素を囲み、 clearance マージンの設定が必要のない状態にするとこの問題は発生しない。( clear を指定した要素の margin-top を clearance よりも大きくしてもこの問題は発生しない)
あと、 clearance マージンより下方向にコンテンツがない場合は、 Peek-a-boo は起きない。
重要なことは、 clearance マージンと non-layout なブロックの背景。

float の 3px

このバグは。。。 3px くらい空いてほうがいいでしょ的な気分で付けたとしか思えない。。。
(margin-left or margin-right): -3px くらいしか解決策はないのかな?

(続くかも)