如何通过javascript / jQuery从CSS类中获取样式属性?

时间:2013-06-06 15:00:01

标签: javascript jquery css

如何通过jQuery从CSS类访问属性? 我有一个CSS类,如:

.highlight { 
    color: red; 
}

我需要在对象上做一个颜色动画:

$(this).animate({
    color: [color of highlight class]
}, 750);

这样我就可以从red更改为blue(在CSS中),我的动画将按照我的CSS工作。

一种方法是使用highlight类放置一个不可见的元素,然后获取要在动画中使用的元素的颜色,但我想这是一种非常非常糟糕的做法。

有什么建议吗?

8 个答案:

答案 0 :(得分:66)

我编写了一个小函数,遍历文档中的样式表,寻找匹配的选择器,然后是样式。

有一点需要注意,这只适用于使用样式标记定义的样式表或来自同一域的外部工作表。

如果表单已知,您可以将其传入,并且不必查看多张表格(更快,如果您有冲突规则则更准确)。

我只在jsFiddle上测试了一些弱测试用例,让我知道这是否适合你。

function getStyleRuleValue(style, selector, sheet) {
    var sheets = typeof sheet !== 'undefined' ? [sheet] : document.styleSheets;
    for (var i = 0, l = sheets.length; i < l; i++) {
        var sheet = sheets[i];
        if( !sheet.cssRules ) { continue; }
        for (var j = 0, k = sheet.cssRules.length; j < k; j++) {
            var rule = sheet.cssRules[j];
            if (rule.selectorText && rule.selectorText.split(',').indexOf(selector) !== -1) {
                return rule.style[style];
            }
        }
    }
    return null;
}

示例用法:

var color = getStyleRuleValue('color', '.foo'); // searches all sheets for the first .foo rule and returns the set color style.

var color = getStyleRuleValue('color', '.foo', document.styleSheets[2]); 

编辑:

我忽略了考虑分组规则。我将选择器检查更改为:

if (rule.selectorText.split(',').indexOf(selector) !== -1) {

现在它将检查分组规则中的任何选择器是否匹配。

答案 1 :(得分:3)

由于您已经在使用jQuery,请尝试使用jQuery-ui的函数switchClass,这将允许您为这种新颜色设置动画。

例如:

 $('div').switchClass( "", "highlight", 1000 );

Demo


如果您不想包含整个 UI库,请使用以下代码:

switchClass: function( remove, add, speed, easing, callback) {
    return $.effects.animateClass.call( this, {
        add: add,
        remove: remove
    }, speed, easing, callback );
}

和animateClass fn:

var classAnimationActions = [ "add", "remove", "toggle" ],
    shorthandStyles = {
        border: 1,
        borderBottom: 1,
        borderColor: 1,
        borderLeft: 1,
        borderRight: 1,
        borderTop: 1,
        borderWidth: 1,
        margin: 1,
        padding: 1
    };
function styleDifference( oldStyle, newStyle ) {
    var diff = {},
        name, value;




    for ( name in newStyle ) {
        value = newStyle[ name ];
        if ( oldStyle[ name ] !== value ) {
            if ( !shorthandStyles[ name ] ) {
                if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
                    diff[ name ] = value;
                }
            }
        }
    }




    return diff;
}
function getElementStyles( elem ) {
    var key, len,
        style = elem.ownerDocument.defaultView ?
            elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
            elem.currentStyle,
        styles = {};




    if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
        len = style.length;
        while ( len-- ) {
            key = style[ len ];
            if ( typeof style[ key ] === "string" ) {
                styles[ $.camelCase( key ) ] = style[ key ];
            }
        }
    // support: Opera, IE <9
    } else {
        for ( key in style ) {
            if ( typeof style[ key ] === "string" ) {
                styles[ key ] = style[ key ];
            }
        }
    }




    return styles;
}
$.effects.animateClass = function( value, duration, easing, callback ) {
    var o = $.speed( duration, easing, callback );

    return this.queue( function() {
        var animated = $( this ),
            baseClass = animated.attr( "class" ) || "",
            applyClassChange,
            allAnimations = o.children ? animated.find( "*" ).addBack() : animated;

        // map the animated objects to store the original styles.
        allAnimations = allAnimations.map(function() {
            var el = $( this );
            return {
                el: el,
                start: getElementStyles( this )
            };
        });

        // apply class change
        applyClassChange = function() {
            $.each( classAnimationActions, function(i, action) {
                if ( value[ action ] ) {
                    animated[ action + "Class" ]( value[ action ] );
                }
            });
        };
        applyClassChange();

        // map all animated objects again - calculate new styles and diff
        allAnimations = allAnimations.map(function() {
            this.end = getElementStyles( this.el[ 0 ] );
            this.diff = styleDifference( this.start, this.end );
            return this;
        });

        // apply original class
        animated.attr( "class", baseClass );

        // map all animated objects again - this time collecting a promise
        allAnimations = allAnimations.map(function() {
            var styleInfo = this,
                dfd = $.Deferred(),
                opts = $.extend({}, o, {
                    queue: false,
                    complete: function() {
                        dfd.resolve( styleInfo );
                    }
                });

            this.el.animate( this.diff, opts );
            return dfd.promise();
        });

        // once all animations have completed:
        $.when.apply( $, allAnimations.get() ).done(function() {

            // set the final class
            applyClassChange();

            // for each animated element,
            // clear all css properties that were animated
            $.each( arguments, function() {
                var el = this.el;
                $.each( this.diff, function(key) {
                    el.css( key, "" );
                });
            });

            // this is guarnteed to be there if you use jQuery.speed()
            // it also handles dequeuing the next anim...
            o.complete.call( animated[ 0 ] );
        });
    });
};

使用所有需要的功能:http://jsfiddle.net/maniator/3C5ZQ/

答案 2 :(得分:2)

这个怎么样?

$('<span class="highlight"></span>').appendTo('body');
$(this).animate({
    color: $('.highlight').css('color')
}, 750);
$('.highlight').remove();

它有点脏,但会给你一个(空)元素来引用你得到的CSS值。

更新以下是来自CSS parser/abstracter? How to convert stylesheet into object

的合适解决方案
function findColorProperty(selector) {
    rules = document.styleSheets[0].cssRules
    for(i in rules) {
        //if(rules[i].selectorText==selector) 
            //return rules[i].cssText; // Original
        if(rules[i].selectorText == selector) 
            return rules[i].style.color; // Get color property specifically
    }
    return false;
}

用法

$(this).animate({
    color: findColorProperty('.highlight')
}, 750);

这是一个小提琴http://jsfiddle.net/wzXDx/1/。由于环境的嵌入性,我不得不使用styleSheets[1]来使这个在小提琴中起作用。

答案 3 :(得分:2)

我想到的唯一解决方案如下:

//create an element with this class and append it to the DOM
var eleToGetColor = $('<div class="highlight" style="display: none;">').appendTo('body');
//get the color of the element
var color = eleToGetColor.css('color');
//completly remove the element from the DOM
eleToGetColor.remove();


$("div").animate({
  //set the new color
  color: color,
}, 1000);
.highlight {
  color: red;
}
div {
  width: 200px;
  height: 100px;
  color: blue;
  font-size: 6em;
  font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/themes/smoothness/jquery-ui.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script>
<div>TEST</div>

答案 4 :(得分:1)

我刚刚编写了这个函数,通过选择器获取所有样式。注意:选择器必须与CSS中的相同。

    /**
     * Gets styles by a classname
     * 
     * @notice The className must be 1:1 the same as in the CSS
     * @param string className_
     */
    function getStyle(className_) {

        var styleSheets = global_.document.styleSheets;
        var styleSheetsLength = styleSheets.length;
        for(var i = 0; i < styleSheetsLength; i++){
            var classes = styleSheets[i].rules || styleSheets[i].cssRules;
            var classesLength = classes.length;
            for (var x = 0; x < classesLength; x++) {
                if (classes[x].selectorText == className_) {
                    var ret;
                    if(classes[x].cssText){
                        ret = classes[x].cssText;
                    } else {
                        ret = classes[x].style.cssText;
                    }
                    if(ret.indexOf(classes[x].selectorText) == -1){
                        ret = classes[x].selectorText + "{" + ret + "}";
                    }
                    return ret;
                }
            }
        }

    }

答案 5 :(得分:1)

不幸的是我不能评论这个真棒answer,但发现了一个没有照顾的情况(当CSS类被多次声明并且第一个声明没有你正在寻找的样式时for),提出jsFiddle来迎合它:

function getStyleRuleValue(style, selector, sheet) {
  var sheets = typeof sheet !== 'undefined' ? [sheet] : document.styleSheets;
  for (var i = 0, l = sheets.length; i < l; i++) {
    var sheet = sheets[i];
    if( !sheet.cssRules ) { continue; }
    for (var j = 0, k = sheet.cssRules.length; j < k; j++) {
      var rule = sheet.cssRules[j];
      if (rule.selectorText && rule.selectorText.indexOf(selector) !== -1 && rule.style[style] !== '') {
        return rule.style[style];
      }
    }
  }
  return null;
}

还在条件中删除了分割,没有必要,现在它确认样式存在于被检查的规则中。

只是为了shigiggles创建了一个jsFiddle来按选择器缓存样式:

var styleCache = {};

function getStyleRuleValue(style, selector, sheet) {
  if (typeof styleCache[selector] !== 'undefined') {
    if (typeof styleCache[selector][style] !== 'undefined') {
        return styleCache[selector][style];
    }
  }
  else {
    styleCache[selector] = {};
  }

  var sheets = typeof sheet !== 'undefined' ? [sheet] : document.styleSheets;
  for (var i = 0, l = sheets.length; i < l; i++) {
    var sheet = sheets[i];
    if( !sheet.cssRules ) { continue; }
    for (var j = 0, k = sheet.cssRules.length; j < k; j++) {
      var rule = sheet.cssRules[j];
      if (rule.selectorText && rule.selectorText.indexOf(selector) !== -1 && rule.style[style] !== '') {
        return styleCache[selector][style] = rule.style[style];
      }
    }
  }
  return null;
}

虽然如果你使用它,我建议把它放在一个闭包/类中。再次感谢rlemon获得了令人敬畏的原创作品。

答案 6 :(得分:0)

这是另一种方法:在应用类的情况下添加隐藏的div。使用jQuery.css查找样式值。然后删除元素。

http://plnkr.co/edit/Cu4lPbaJWHW42vgsk9ey

function getStyleValue(className, style) {
  var elementId = 'test-' + className,
    testElement = document.getElementById(elementId),
    val;

  if (testElement === null) {
    testElement = document.createElement('div');
    testElement.className = className;
    testElement.style.display = 'none';
    document.body.appendChild(testElement);
  }

  val = $(testElement).css(style);
  document.body.removeChild(testElement);
  return val;
}

console.log( 'The style value is ' + getStyleValue('dark-red', 'color') );

答案 7 :(得分:0)

为什么不添加.highlighted类,缓存color样式,而不是将其删除并设置为缓存颜色的动画?即不要添加元素,不要解析和解析。循环样式。

jsfiddle example

&#13;
&#13;
var $element = $('.my-class').addClass('highlighted');
var colorToAnimate = $element.css('color');

$element.removeClass('highlighted');

alert(colorToAnimate);
&#13;
.my-class {
  color: blue;
}
.highlighted {
  color: red;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span class="my-class">Animated color text</span>
&#13;
&#13;
&#13;