2012/12/30

CSSのクラスの値をJavaScriptで変更する方法

jQuery に有りそうで無いのでクラスに設定したスタイルを後からJavascript変更する方法をメモ。
function Common(){this.initialize.apply(this, arguments)};
(function(Class){

    /**
     * ルールのキャッシュ
     * @type CSSStyleRule
     */
    var classCssRuleCache = {};

    /**
     * セレクタに一致するルールを取得。
     * <li>検索は重いのキャッシュする。
     * @param {string} selectror セレクタ文字列
     * @returns {CSSStyleRule} ルール
     */
    Class.getCssRule = function(selector) {
        if (classCssRuleCache[selector]) return classCssRuleCache[selector];
        var sheets = document.styleSheets;
        for (var i=0; i<sheets.length; i++) {
            var rules = sheets[i].cssRules;
            if (rules == null) rules = sheets[i].rules; // ForIE
            for (var j=0; j<rules.length; j++) {
                if (selector == rules[j].selectorText) {
                    classCssRuleCache[selector] = rules[j];
                    return rules[j];
                }
            }
        }
        return null;
    }

    /**
     * セレクタに一致するルールを取得。
     * <li>当該セレクタのルールが存在しなければ作成する。
     * @param {string} selectror セレクタ文字列
     * @returns {CSSStyleRule} ルール
     */
    Class.getCssRuleWithDefine = function(selector) {
        var rule = Class.getCssRule(selector);
        if (rule) return rule;

        var sheet = document.styleSheets[0];
        if (sheet.insertRule) {
            sheet.insertRule(selector+"{}", sheet.cssRules.length);
        } else {
            sheet.addRule(selector,"dummy:dummy");//forIE
        }
        return Class.getCssRule(selector);
    }
   
   
    /**
     * セレクタにルールを設定。
     * <li>当該セレクタのルールが存在しなければ作成する。
     * @param {string} selectror セレクタ文字列
     * @param {object} スタイルのマッピング 例:{textAling: "center",…}
     */
    Class.setCssRule = function(selector, style) {
        var rule = Class.getCssRuleWithDefine(selector);
        if (rule == null) return;
        for (var k in style) rule.style[k] = style[k];
    }
   
   
    /**
     * セレクタにルールを important 付きで設定。
     * <li>当該セレクタのルールが存在しなければ作成する。
     * @param {string} selectror セレクタ文字列
     * @param {object} スタイルのマッピング 例:{textAling: "center",…}
     */
    Class.setCssRuleImportant = function(selector, style) {
        var rule = Class.getCssRuleWithDefine(selector);
        if (rule == null) return;
        for (var k in style) rule.style.setProperty(k, style[k], 'important');
    }

})(Common);
使用例:
Common.getCssRule(".MyClass", {textAlign:"center", color:"red"});
だけ。setCssRuleImportant()を使えば !impotant 付きになる。
厳密に言うとクラスのスタイルの言うものは存在しないのでセレクタのスタイルを変更している。つまり第一引数にクラス名を指定する時はドット(.)が必須なので注意。


間単に解説すると読み込まれたCSSはブラウザ依存で以下のプロパティに保存されている。

ブラウザプロパティ名
IE8以前document.styleSheets[ ].rules[ ]
その他document.styleSheets[ ].cssRules[ ]

cssRules[ ] の型は CSSStyleRule で以下のプロパティを持つ。

プロパティ名説明
stringselectorTextセレクタ文字列
CSSStyleDeclarationstyleスタイルセット


セレクタ文字列の正規化の方法は不明だったので複雑なセレクタを変更する場合は自力で正規化をする必要があるかもしれない。(タグ名の大文字/小文字や空白の扱いの事)

IE8以前はルールの追加方法も異る。

ブラウザプロパティ名
IE8以前addRule(selector, style[, index])
その他insertRule(rule,index)

あと @import とか対応が必要だけどあんまり使わないから必要になるまで放置かな(^^;


2012/11/18

CSSだけでボーダーレイアウトのテンプレ

CSSだけでヘッダー、フッター、サイドを固定するのは以外と難しい。
ググっても怪しいやり方しか出てこない。(まあ IE6 のせいなんだが)

つう訳でCSSだけでクロスブラウザの真っ当な(IEハック無し) ボーダーレイアウトのテンプレを書いてみた。 (但し、IE7は後方互換モード)

ボーダーレイアウト:

ブラウザを小さくした所:

ブラウザを小さくしてもヘッダー、フッター、サイドはそのままの大きさで中央部のみ可変サイズとなる。
スクロールバーは中央部にしか出ない。

他のブラウザで動作確認。

Firefox-ESR:

Safari:

IE6:

IE7(後方互換モード):

IE8:

IE6,IE8は本物でも確認した。IE7はIE-Testerのみ。

実行サンプル



まあ、JavaScriptを使えば簡単だけどレイアウトの為だけに jQuery+Plugin を使わなくて済むのは良いじゃないかと。

ソース

HTML: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>Border layout frame</title> <link rel="stylesheet" href="BorderLayout.css" /> <style> *{font: bold large sans-serif;} </style> </head> <body> <div id="borderLayoutMain" class="BorderLayoutFrame"> <div id="borderLayoutMainInner"> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> テスト テスト テスト テスト テスト テスト テスト <br/> </div> </div> <div id="borderLayoutLeft" class="BorderLayoutFrame"> Left </div> <div id="borderLayoutRight" class="BorderLayoutFrame"> Right </div> <div id="borderLayoutHeader" class="BorderLayoutFrame"> Header </div> <div id="borderLayoutFooter" class="BorderLayoutFrame"> Footer </div> </body> </html>

CSS: IEハック無しです (^^)v

html,body { height:100%; padding:0; margin:0; overflow: hidden; } .BorderLayoutFrame { box-sizing: border-box; -moz-box-sizing: border-box; display: inline-block; position: absolute; overflow: hidden; zoom:1; background: white; } #borderLayoutHeader { width: 100%; height: 80px; /* Header height */ top: 0; border-bottom: 1px solid gray; } #borderLayoutFooter { width: 100%; height: 30px; /* Footer height */ bottom: 0; border-top: 1px solid gray; } #borderLayoutLeft { width: 200px; /* Left width */ height: 100%; top: 0; left: 0; padding-top: 80px; /* Header height */ padding-bottom: 30px; /* Footer height */ border-right: 1px solid gray; } #borderLayoutRight { width: 200px; /* Right width */ height: 100%; top: 0; right: 0; padding-top: 80px; /* Header height */ padding-bottom: 30px; /* Footer height */ border-left: 1px solid gray; } #borderLayoutMain { width: 100%; height: 100%; top: 0; left: 0; padding-top: 80px; /* Header height */ padding-left: 200px; /* Left width */ padding-right: 200px; /* Right width */ padding-bottom: 30px; /* Footer height */ } #borderLayoutMainInner { height: 100%; width: 100%; overflow: auto; position: relative; } /* EOF */

2012/10/29

タグの間の空白対策

HTMLでタグを改行区切りで記述した時に入る空白の対策メモ。

こうした時の

<img src="img/user_black_female.png" /> <img src="img/user_business.png" /> <img src="img/user_business_boss.png" /> <img src="img/user_female.png" />

この隙間の事。


普通形

コードの汚さを我慢すればこれが一番楽。 <img src="img/user_black_female.png" /><img src="img/user_business.png" /><img src="img/user_business_boss.png" /><img src="img/user_female.png" />


letter-spacing:-n;

CSSの letter-spacing をマイナスにして調整する。
元ネタ:http://inspire-tech.jp/2011/06/inline_block_spaces/ <span style="letter-spacing: -0.40em;"> <img src="img/user_black_female.png" /> <img src="img/user_business.png" /> <img src="img/user_business_boss.png" /> <img src="img/user_female.png" /> </span>

幅指定がフォント依存なので厳密なケースでは使えない。


JavaScript

JavaScriptでテキストノードを削除する。 $("#xxxx").contents().each(function(){ if (this.nodeType==3) this.parentNode.removeChild(this); });

JavaScriptが使える場合のみ。


display:table-cell;

teble-cell で出来るとの情報が有ったので試してみる。
元ネタ:http://h2ham.seesaa.net/article/117579108.html img { display: table-cell; }

ブラウザ依存。Chromeはアウト。IEもIE7以前は teble-cell 未対応のはず。

IE8:

Firefox:

Chrome:

結論

現状、CSSだけでうまいことやる方法は無さげ。
いままで通りか、JavaScript でやるしか無さそう。

2011/10/31

CCS だけで吹き出し。

Google Map 用の吹き出しを作ったときに画像を使ったんだけど CSS だけでも吹き出しが作れるみたい。

三角形の所はどうすんだろうと思ったら世の中には頭の良い人が いるもんで太い border の片側を透明にする事で実現していた。

こーいうのをコロンブスの卵って言うんだろうな。

参考サイトはこの辺、他多数。

  • http://terkel.jp/archives/2009/12/css-only-speech-bubbles/

さっそく試してみる。
左右の吹き出しの例が多いんだけど汎用性を考えて真中も有りにした。

吹き出し
データだよーん

大きさは内部データのサイズに追従する。 髭の部分も任意に伸ばせる。

吹き出し
データ
だよーん だよーん だよーん だよーん

ちょっといじると三角形を片側にして左右吹き出しにもできる。

左から吹き出し

右から吹き出し

CSS3 を使って影やらグラデーションやらで装飾したので下手に画像を 用意するより見栄えが良くなってしまった。

ま、やっぱり IE7 じゃ動かないんだけどね :-P

ソース:

<style> .Balloon { display: inline-block; color: black; font-style: bold; } .Balloon > span { display: inline-block; position: relative; top: -0px; left: -8px; border-bottom: 8px solid transparent; width: 50%; border-left: none; border-right: 8px solid #d0d0d0; } .Balloon > span + span { width: 0%; border-left: 8px solid #c8c8c8; border-right: none; } .Balloon > div { display: inline-block; border: 1px outset #fff; padding: 4px; background-image: -webkit-gradient(linear, left top, left bottom, from(#f0f0f0), to(#d0d0d0)); /* Saf4+, Chrome */ background-image: -webkit-linear-gradient(top, #f0f0f0, #d0d0d0 ); /* Chrome 10+, Saf5.1+ */ background-image: -moz-linear-gradient(top, #f0f0f0, #d0d0d0 ); /* FF3.6 */ background-image: -ms-linear-gradient(top, #f0f0f0, #d0d0d0 ); /* IE10 */ background-image: -o-linear-gradient(top, #f0f0f0, #d0d0d0 ); /* Opera 11.10+ */ background-image: linear-gradient(top, , #d0d0d0 ); -webkit-border-radius: 8px; -khtml-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px; -moz-box-shadow: 1px 1px 3px rgba(0,0,0,.3) ; -webkit-box-shadow: 1px 1px 3px rgba(0,0,0,.3) ; box-shadow: 1px 1px 3px rgba(0,0,0,.3) ; } .Long> .Balloon > span { border-bottom: 32px solid transparent; } .Right> .Balloon > span { width: 75%; border-bottom: 12px solid transparent; border-right: 12px solid #d0d0d0; } .Right> .Balloon > span+span { display: none; } .Left> .Balloon > span { width: 25%; border-bottom: 12px solid transparent; border-right: 0px solid #d0d0d0; } .Left> .Balloon > span+span { border-left: 12px solid #d0d0d0; } </style> <div class="Balloon"><div> 吹き出し<br/>データだよーん </div><br/><span></span><span></span></div> <div class="Long"> <div class="Balloon"><div> 吹き出し<br/>データ<br/>だよーん だよーん だよーん だよーん </div><br/><span></span><span></span></div> </div> <span class="Left"> <div class="Balloon"><div> 左から吹き出し </div><br/><span></span><span></span></div> </span> <span class="Right"> <div class="Balloon"><div> 右から吹き出し </div><br/><span></span><span></span></div> </span>


プロフィール
20年勤めた会社がリーマンショックで消滅、紆余曲折を経て現在はフリーランスのSE。 失業をきっかけにこのブログを始める。

サイト内検索

登録
RSS/2.0

カテゴリ

最近の投稿【css】

リンク

アーカイブ