ラベル HTML&CSS の投稿を表示しています。 すべての投稿を表示
ラベル HTML&CSS の投稿を表示しています。 すべての投稿を表示

2015年12月5日

Firefox のボタン(<button>, <input type=button>)の大きさ(幅・高さ)が違う場合の対処法

width や height を指定せず、padding や内部の文字列で大きさを確保するボタン(<button> や <input type="button">)では、IE/Chrome と比べて Firefox のボタンサイズが大きくなる。
文字の幅は、同じフォントを指定してもブラウザによって異なるのが普通だが(レンダリングエンジンが異なるため)、Firefox のみ明らかに大きくなる。

[問題になる CSS の例]

button {
    padding: 5px;
    border: 1px solid lime;
    letter-spacing: 0px;

    /* ブラウザ間の差が少ないメイリオを使用 */
    font: 15px/22px Meiryo;
    cursor: pointer;
}
[プレビュー]
[開発者ツールの画面キャプチャ]
IE Chrome Firefox (Firebug)
IE button inspection Chrome button inspection Firefox button inspection
※ Firefox のボタンサイズが、縦方向 2px、横方向 6px 大きい。

原因と対処法

困った時の stackoverflow。
Firefox はボタンフォーカス時の点線の幅と padding が確保されているため、他のブラウザより大きくなるのだとか。
これ → Firefox focused button

[ボタンフォーカスの点線を消す CSS]

button::-moz-focus-inner {
    padding: 0;
    border: 0;
}
/* input[type=button] なども同様に指定可能 */
[プレビュー]
[Firebug の画面キャプチャ]
Firefox button inspection

ボタンフォーカスの点線を消したくない場合、margin を工夫することで大きさを合わせることが可能。

button::-moz-focus-inner {
    padding: 0;
    margin: -1px; /* 点線の幅分のマイナスマージン */
}

ただし、最初にも書いたが、ブラウザによる文字の幅の差はどうすることもできないので、ボタンの大きさ完全に一致させたい場合は、button の width を指定するしかない。

検証環境

  • Windows 7 64bit
  • Internet Explorer 11
  • Firefox 42.0
  • Chrome 48.0.2564.8

2015年11月19日

<iframe> を動的生成する際の注意点

javascript で src 無しの <iframe> とその中身を構築した際、はまったことがあったのでメモ。

  • 動的に追加した <iframe> の中身をいじる際は、
    iframe.contentWindow.documentdocument.write() を使う
    または
    <iframe> のロード完了を待つ。(<iframe> 自身に onload イベントがある)
  • <iframe> に onload イベントを設置する際は、DOM への追加前に行う。
    DOM に <iframe> を追加した瞬間、onload イベントが処理されるブラウザがあるため (Chrome)

[サンプルコード]

// 単純化のため、jquery 使用

// 良い例
// IE:OK / Firefox:OK / Chrome:OK
$(function(){
    $('<iframe>').load(function(){
        // ロード完了後、DOM を変更できる。
        var ibody = this.contentWindow.document.body;
        $(ibody).append('<div>ブロック要素</div>');
    }).appendTo('body');
    // イベント設置後に DOM へ追加
});


// 悪い例(1)
// IE:OK / Firefox:NG / Chrome:OK
// Chrome は iframe の DOM 追加後、即時ロード完了する模様
// IE は iframe のロード完了を待たなくても大丈夫っぽい??
$(function(){
    var iframe = $('<iframe>').appendTo('body');
    var ibody = iframe[0].contentWindow.document.body;
    $(ibody).append('<div>ブロック要素</div>');
});


// 悪い例(2)
// IE:OK / Firefox:OK / Chrome:NG
// Chrome は iframe が即時ロード完了するので、DOM 追加後に load イベントを付けても無意味
$(function(){
    var iframe = $('<iframe>').appendTo('body');
    iframe.load(function(){
        var ibody = this.contentWindow.document.body;
        $(ibody).append('<div>ブロック要素</div>');
    });
});
[環境]
  • Windows 7 64bit
  • Internet Explorer 11
  • Firefox 42.0
  • Chrome 48.0.2564.8

2015年3月19日

IE10 table に colspan を指定するとカラムの下線が消えるバグ

検索でもたくさん引っかかる割と有名なバグ。
今更という気もするが、自分も遭遇したため、現象と解決手段をまとめておく。

発生条件(AND)
  • IE10 実機
  • ドキュメントモード: 標準 / Quirks / Internet Explorer 9 標準 / Internet Explorer 8 標準
  • table に { border-collapse: collapse; } を指定
  • td と th に 0 でない border-bottom を指定
  • td または th に 2 以上の colspan を指定

現象が発生するコードと画面キャプチャ。
[CSS]

table { border-collapse: collapse; width: 400px; }
td, th { border: 1px solid black; }
[HTML]

<table>
    <tr>
        <th>col</th>
        <th>col</th>
        <th>col</th>
    </tr>
    <tr>
        <td colspan=3>col3</td>
    </tr>
</table>
[画面キャプチャ]
IE10 table border bug image

常に発生するわけでもなく、画面の再描画で正常に表示されたりする。
開発者ツールを使うと再描画が走るので調査できなかったり・・・

解決手段

発生条件からどれか 1 つを取り除けば、現象は発生しない。
「IE10 を使わない」が理想だけど、実際はドキュメントモードを変更または CSS で何とかすることになると思う。

上のコードに対する CSS による解決例。
※ CSS ハックなどで、IE10 にだけ下記を適用
 (全ブラウザに対して適用してもコードが特殊になるだけで害はないはず・・)

/* カラムの下線を 0 に指定 */
td, th { border-bottom: 0 none; }

/* 代わりに table の下線を指定 */
table { border-bottom: 1px solid black; }

/* または、tr でも可能 (tr の border は IE8以降で有効) */
tr { border-bottom: 1px solid black; }

IE お得意の条件付きコメントは IE10 から廃止されているため、IE10 のみ適用する場合は CSS ハックまたは javascript に頼るしかない。
まだバグが残ってるのに・・・

2015年2月22日

table カラムの colspan と nth-child の相性問題

この記事のテーブルレイアウトで苦労したのでメモ。

例えば、列数 > 2 のテーブルの先頭 2 列を色指定したい場合、nth-child を使うと簡単にできる。
[CSS]

/* td と th の先頭 2 列を指定 */
td:nth-child(-n+2), th:nth-child(-n+2) {
    background-color: purple;
}

しかし、先頭 2 列に colspan=2 が含まれる場合・・・
[HTML]

<table>
    <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
    </tr>
    <tr>
        <td colspan=2>1-2</td>
        <td>3</td>
    </tr>
</table>

nth-child は colspan を考慮してくれないため、破綻する。
[プレビュー]
123
1-23

解決手段

まず、<colgroup> と <col> を使ってスタイルを指定する方法がある。
◇cssでセル幅を指定するとcolspanで破綻する: 万象酔歩 にくわしく説明されているので、ここでは割愛。

基本的には上記でいいのだが、<td> や <th> に既にスタイルを割り当てている場合、<colgroup> が使えない。
<colgroup> と <col> では、 !important を指定しても <td> と <th> のスタイルを上書きできない。

もう 1 つの方法として、非表示の <td> <th> を利用して、nth-child を適用する方法がある。
[HTML]

<table>
    <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
    </tr>
    <tr>
        <td colspan=2>1-2</td>
        <td style="display:none"><!-- 非表示カラム --></td>
        <td>3</td>
    </tr>
</table>
[プレビュー]
123
1-23

非表示要素を使うのは微妙だが、対象のカラムすべてに class を書いたりするよりはましである。

その他

Selectors Level 4 の Column combinator が実装されれば、こんな工夫はいらなくなるはず。

2014年6月7日

IE9.js(ie7-js) でスタイルシートの解析を部分的に無視

記事タイトルのような機能が無かったため、機能追加したものを作成。
https://bitbucket.org/temp_impl/ie9-js/src

オリジナルとの差分
https://bitbucket.org/temp_impl/ie9-js/commits/124d43c6f6d12327aa0c8e20775ba6a106ea2de0

使用方法

<style> や <link> に class="ie9js-ignore" を付けると、スタイルシート解析の対象外になる。
「class に 対象クラス名が含まれているか」で判定しているので、クラス名が複数あってもOK。

<html>
<head>
<!-- スタイルシート解析から無視される -->
<link type="text/css" rel="stylesheet" href="style.ignore.css" class="ie9js-ignore" />
<style type="text/css" class="ie9js-ignore">
div > div:first-child {
    background-color: cyan;
}
</style>

<!-- スタイルシート解析される -->
<link type="text/css" rel="stylesheet" href="style.css" />
<style type="text/css">
div > div:last-child {
    background-color: yellow;
}
</style>

<!--[if lt IE 9]>
<script src="IE9.min.js"></script>
<![endif]-->
</head>

<body>
  <div>
    <div>first</div>
    <div>last</div>
  </div>
</body>
</html>

使いどころ

対象ブラウザ(IE7/IE8)で元から使えるスタイルシートは解析させる必要がないので無視できる。
解析されて javascript 適用のスタイルシートになると、そのままでは DHTML で使えないなどの問題が起こったりする。

また、ファイルサイズが大きい css を無視できると、当然レスポンスが良くなる。
IE7/IE8 に対応している jquery-ui の css など。

2014年5月31日

IE9.js(ie7-js) を DHTML でも使用する方法

IE9.js(ie7-js) は便利だが、画面表示後に変更された HTML(いわゆる DHTML・動的 HTML)に対してスタイルが適用されないことがある。

理由は単純で、主に擬似要素などブラウザが対応していないスタイルシートを javascript により適用しているためである。
javascript によるスタイル適用は画面ロード時の 1 回だけになり、後から変更された HTML に対しては何もできない。

そこで、スタイルを再適用させるための関数 IE7.recalc() が存在する。
IE9.js + DHTML でスタイルシートが適用されない場合は試してみる価値あり。
主に擬似要素を使ってるスタイルで有効。

使用例


<html>
<head>
<style type="text/css">
div > div:first-child > span {
    background-color: cyan;
}
</style>
<!--[if lt IE 9]>
<script src="http://ie7-js.googlecode.com/svn/version/2.1(beta4)/IE9.js"></script>
<![endif]-->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
    var index = 0;
    $('#add_dynamic').click(function(){
        $('#dynamic').append('<div><span>' + (index++) + '</span></div>');
        IE7.recalc();
    });
});
</script>
</head>

<body>
<input type="button" id="add_dynamic" value="add" />
<div id="dynamic"></div>
</body>
</html>
※first-child は IE7・IE8 でも使用可能だが、IE9.js を使用すると javascript 適用のスタイルシートになる。

参考URL

2014年5月30日

IE7 テキストボックスの上下余白(margin)

IE でテキストボックス <input type="text" /> を縦方向に並べる際、テキストボックスに margin:0 を指定しても、IE のバージョンによっては上下に余白ができることがある。
特に IE7 において顕著である。
※横方向に並べる際は問題ない。

具体例

[CSS]

div {
    margin: 0;
    padding: 0;
    width: 120px;
    /* 見易さのためのオプション */
    background-color: #00ffff;
    text-align: center;
}
div input {
    margin: 0;
    width: 50px;
    border: 1px solid #000000;
}
[HTML]
※DOCTYPE を指定しないとバージョン間の差異はさらに増える

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- 中略 -->
<div>
<input type="text" /><input type="text" /><br/>
<input type="text" /><input type="text" />
</div>
[プレビュー]
IE11
IE8~10もほぼ同じ
IE11 textbox
IE7 IE7 textbox

解決手段

見た目どおり上下の余白を取り除くという発想で、<input> に "margin: -1px 0" を指定しただけでは、縦中央に余白が残る。
IE7 textbox minus margin

そこで、<div> に font-size:12px を指定してみると、縦中央の余白も無くなる。
(理由は不明、高さ関係の計算で font-size が必要とか?)
<input> に対してではなく、それを包括する要素に指定するのがポイント
IE7 textbox minus margin and font-size

[IE7 に対応した CSS]

div {
    margin: 0;
    padding: 0;
    width: 120px;
    font-size: 12px;
    /* 見易さのためのオプション */
    background-color: #00ffff;
    text-align: center;
}
div input {
    margin: 0;
    width: 50px;
    border: 1px solid #000000;
}
/* IE7 のみ適用 */
*+html div input {
    margin: -1px 0;
}

/* [おまけ] reset.css で記載する場合
 * ※属性セレクタを使用するため、IE9.js などが必要
 */
*+html input[type=text] {
    margin: -1px 0;
}

備考

<input> に padding:0 を指定すると、IE8 と IE9 でも上に余白ができるが、上記と同様に <div> に font-size を指定すれば無くなる。
クロスブラウザ対応で font-size の指定は意外と重要。

2014年4月22日

ul > li > div でテーブルレイアウト

html + css で <table> を使わずにテーブルレイアウトを作る方法をググったところ、<div> のみで構築する方法と、<ul> <li> <div> で構築する方法が多かった。
<div> のみだと class が増えそうなので、<ul> <li> <div> で構築する方法を選択。

しかし、検索結果の情報には、なぜか <li> の下の <div> に「float:left;」を使ったものが多い。
「float:left;」の何が問題かというと、「vertical-align」と共存できない・・・

そこで、下記を使ってみた。
ul → table , li → tr , div → td のように使用可能。

ul.table-layout {
    list-style: none;
    display: table;
    margin: 0;
    padding: 0;
}
ul.table-layout > li {
    display: table-row;
}
ul.table-layout > li > div {
    display: table-cell;
    vertical-align: middle;
}

使用例

[HTML ソース]

<ul class="table-layout">
    <li>
        <div style="padding:5px">
            <div style="border:1px solid #ff00ff">て<br>す<br>と</div>
        </div>
        <div style="padding:5px">
            <div style="border:1px solid #ffff00">レイアウト</div>
        </div>
        <div style="padding:5px">
            <div style="border:1px solid #00ffff">で<br>す</div>
        </div>
    </li>
</ul>

[プレビュー]


  • レイアウト

備考

この方法は "dispaly: table" に対応してないブラウザでは不可。
つまり、IE7 等では諦めて <table> を使うのが無難。