javascript - 通过 JavaScript/DOM 访问 CSS 媒体查询规则

标签 javascript css dom media-queries

我一直在使用许多库(包括我自己的库)来根据我在 CSS 文件中概述的媒体查询动态加载资源。例如:

在 CSS 中:

  @media screen and (max-width: 480px) {
    .foo {
      display: none;
    }
  }

使用 Assets 加载器; require.js , modernizr.js等或使用 window.matchMedia 和相关的 addListener() 函数:

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

两次声明它们很笨拙/愚蠢,据我所知,所有 JS 帮助程序库和 Assets 加载器都要求您重复媒体查询,而不是从 JS/DOM 中以编程方式定位它们。

所以,我一直在探索通过 document.stylesheets 以编程方式访问值的能力,但我不确定它们是否可以访问,而且似乎很少有文档表明它们是.

我最远的是寻找 CSSMediaRule 并使用 console.dir(document.stylesheets) 等来探索样式表对象。

但没有引用(在 document.stylesheets 中)CSS 中使用的实际媒体查询规则 - 只有作为媒体查询结果应用的类......我是什么m 试图以编程方式定位是:

"screen and (max-width: 480px)"

有没有办法通过 JavaScript/DOM 访问此类 CSS 媒体查询规则

最佳答案

对于获取规则,请使用跨浏览器变体:

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

用于在规则列表中检测 CSSMediaRule 对象(不适用于 IE <= 8,因为“CSSMediaRule”类仅在 IE >= 9 中可用):

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

一些从当前 DOM 获取样式的函数(不适用于 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 Fiddle:https://jsfiddle.net/luisperezphd/hyentcqc/

关于javascript - 通过 JavaScript/DOM 访问 CSS 媒体查询规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15696124/

相关文章:

html - 单选按钮侧面有奇怪的“多余”点

javascript - 如何使用 JavaScript 更改文本

javascript - 禁用Java中的dom更改事件?

javascript - 如何使用Iron Router和Meteor将模板渲染为模板

javascript - Handlebars.js - 循环一个不包括第一个元素的数组?

javascript - 如何在Angular的Chrome浏览器中捕获控制台日志

java - 如何以编程方式更新和添加具有序列的复杂类型到 XSD

javascript - 欧芹自定义验证器不起作用

css - 在悬停时切换一种 Font Awesome ,没有javascript

android - 灰度过滤器在安卓手机默认浏览器中不起作用