2013-03-29 10 views
14

私はCSSファイルで概説したメディアクエリに基づいてアセットを動的にロードするために、多数のライブラリ(自分自身を含む)を使用してきました。たとえば、次のようにCSSでJavaScript/DOMを使用したCSSメディアクエリルールへのアクセス

資産ローダーを使用して
@media screen and (max-width: 480px) { 
    .foo { 
     display: none; 
    } 
    } 

require.jsmodernizr.jsなどまたはwindow.matchMediaを使用し、関連するaddListener()機能:

if (function("screen and (max-width: 480px)")){ 
    // Load several files 
    load(['mobile.js','mobile.css']); 
    } 

二回、それらを宣言することは、私が見つけることができる限り/ぎこちない愚かとされ、すべてのJSヘルパーライブラリと資産ローダーは、メディアクエリを繰り返すのではなくする必要がそれらを見つけることはプログラムによって JS/DOMから。

私はdocument.stylesheets経由でプログラムで値にアクセスする機能を探っていましたが、アクセス可能かどうかはわかりません。

最も遠いのはCSSMediaRuleを探して、console.dir(document.stylesheets)を使ってスタイルシートオブジェクトを探索することです。

しかし、CSSで使用されている実際のメディアクエリルールは参照されません(document.stylesheets内) - メディアクエリの結果として適用されるクラスのみ...プログラムで見つけようとしているのは、 :

"画面と(最大幅:480PX)"

には、JavaScript/DOMを経由して、このようなCSSメディアクエリにルールにアクセスする方法はありますか? (IE < = 8で動作しないためだけ> = 9 IEで利用可能な "CSSMediaRule" クラス)

var styleSheet = document.styleSheets[0]; 
var rules = styleSheet.cssRules || styleSheet.rules; // IE <= 8 use "rules" property 

ための規則のリスト、使用中CSSMediaRule物体を検出:GETルールについて

+2

おっと、間違ってリンク、(HTTPS [ここで私はcoderwallで探していた記事です]。 com/p/_ldtkg) – steveax

+2

良い質問です。私の目的のために、JavaScriptインタラクションがそれらの要素に当てはまるので、私はいつも特定の要素が可視かどうかをチェックしてきました。しかし、より良い、より一般的な解決策があるはずです。 – Brad

+0

ねえ、それをチェックしてください。それは解決策になる可能性があります。 https://github.com/nathansmith/adapt/blob/master/assets/js/adapt.js –

答えて

11

は、クロスブラウザーの変異体を使用します。現在のDOMから取得するスタイルのための

var i = 0; 
if (rules[i].type == 4) 
{ 
    // Do something 
} 

一部の機能(IE = 8 <で動作していない):

function getCssRulesFromDocumentStyleSheets(media) 
{ 
    var resultCssRules = ''; 
    for (var i = 0; i < document.styleSheets.length; i++) 
    { 
     var styleSheet = document.styleSheets[i]; 

     if (isRuleFromMedia(styleSheet, media)) 
      resultCssRules += getCssRulesFromRuleList(styleSheet.cssRules || styleSheet.rules, media); 
    } 

    return resultCssRules; 
} 

function getCssRulesFromRuleList(rules, media) 
{ 
    var resultCssRules = ''; 
    for (var i = 0; i < rules.length; i++) 
    { 
     var rule = rules[i]; 
     if (rule.type == 1) // CSSStyleRule 
     { 
      resultCssRules += rule.cssText + "\r\n"; 
     } 
     else if (rule.type == 3) // CSSImportRule 
     { 
      if (isRuleFromMedia(rule, media)) 
       resultCssRules += getCssRulesFromRuleList(rule.styleSheet.cssRules || rule.styleSheet.rules, media); 
     } 
     else if (rule.type == 4) // CSSMediaRule 
     { 
      if (isRuleFromMedia(rule, media)) 
       resultCssRules += getCssRulesFromRuleList(rule.cssRules || rule.rules, media); 
     } 
    } 

    return resultCssRules; 
} 

function isRuleFromMedia(ruleOrStyleSheet, media) 
{ 
    while (ruleOrStyleSheet) 
    { 
     var mediaList = ruleOrStyleSheet.media; 
     if (mediaList) 
     { 
      if (!isMediaListContainsValue(mediaList, media) && !isMediaListContainsValue(mediaList, 'all') && mediaList.length > 0) 
       return false; 
     } 

     ruleOrStyleSheet = ruleOrStyleSheet.ownerRule || ruleOrStyleSheet.parentRule || ruleOrStyleSheet.parentStyleSheet; 
    } 

    return true; 
} 

function isMediaListContainsValue(mediaList, media) 
{ 
    media = String(media).toLowerCase(); 

    for (var i = 0; i < mediaList.length; i++) 
    { 
     // Access to mediaList by "[index]" notation now work in IE (tested in versions 7, 8, 9) 
     if (String(mediaList.item(i)).toLowerCase() == media) 
      return true; 
    } 

    return false; 
} 

機能使用例:ここでは

<style type="text/css"> 
    @media screen and (max-width: 480px) { 
     p { margin: 10px; } 
    } 

    @media screen and (max-width: 500px) { 
     p { margin: 15px; } 
    } 

    @media print { 
     p { margin: 20px; } 
    } 
</style> 

<!-- ... --> 

<script type="text/javascript"> 
    alert(getCssRulesFromDocumentStyleSheets('print')); 
    alert(getCssRulesFromDocumentStyleSheets('screen and (max-width: 480px)')); 
    // For IE (no space after colon), you can add fix to "isMediaListContainsValue" function 
    alert(getCssRulesFromDocumentStyleSheets('screen and (max-width:480px)')); 
</script> 

はそれのためにJSフィドルです:https://jsfiddle.net/luisperezphd/hyentcqc/

+0

この関数は完全一致を検索します。 "screen and(max ...")と部分一致(例えば "screen")のようなものではないでしょうか? 私は画面のクラスをどんな次元にでも複製し、削除し、再作成しようとしています。 これはこれに使用できると思いますか? ありがとうございました。 – sergio

5

これは私がそれを行う方法です。

CSSでさまざまなブレークポイントでコンテンツを公開または非表示にするクラスを作成します。とにかくこれは便利なユーティリティです。これらはすでに、例えば、Twitter Bootstrapで利用可能です。

<style type="text/css"> 
    .visible-sm, .visible-md, .visible-lg{ 
    display:none; 
    } 
    @media (max-width: 480px) { 
    .visible-sm{ 
     display: block; 
    } 
    } 
    @media (min-width: 481px) and (max-width: 960px) { 
    .visible-md{ 
     display: block; 
    } 
    } 
    @media (min-width: 961px) { 
    .visible-lg{ 
     display: block; 
    } 
    } 
</style> 

これらのクラスですべてのドキュメントに空のスパンを追加します。 スパンをインラインにしておくと、ページに表示されません。

<span id="media_test"> 
    <span class="visible-sm"></span> 
    <span class="visible-md"></span> 
    <span class="visible-lg"></span> 
</span> 

この短いjquery拡張子をスクリプトファイルに追加します。 これは、現在のメディアクエリと一致するbodyタグの新しいクラスを設定します。

(function ($) { 
    $.fn.media_size = function() { 
    //the default port size 
    var size = 'lg'; 
    //the sizes used in the css 
    var sizes = ['sm','md','lg']; 
    //loop over to find which is not hidden 
    for (var i = sizes.length - 1; i >= 0; i--) { 
    if($('#media_test .visible-'+sizes[i]).css("display").indexOf('none') == -1){ 
     size = sizes[i]; 
     break; 
    }; 
    }; 
    //add a new class to the body tag 
    $('body').removeClass(sizes.join(' ')).addClass(size); 
    } 
}(jQuery)); 
$(document).media_size(); 

これで、cssメディアのModernizrスタイルに自動的に統合されました。

あなたのメディアクエリに基づいて、上の条件付きでのjavascript(jqueryの)を書くことができます:// coderwall:

<a href="#">how big is this viewport?</a> 

<script type="text/javascript"> 
    $('.sm a').click(function(e){ alert('Media queries say I\'m a small viewport');}); 
    $('.lg a').click(function(e){ alert('Media queries say I\'m a large viewport');}); 
</script> 
関連する問題