Como obter um atributo de estilo de uma class CSS por javascript / jQuery?

Como posso acessar uma propriedade de uma class CSS por jQuery? Eu tenho uma class CSS como:

.highlight { color: red; } 

E preciso fazer uma animação colorida em um object:

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

Para que eu possa mudar de red para blue (no CSS) e minha animação funcionará de acordo com o meu CSS.

Uma abordagem seria colocar um elemento invisível com a class de highlight e, em seguida, obter a cor do elemento a ser usado na animação, mas acho que essa é uma prática muito, muito ruim.

Alguma sugestão?

Eu escrevi uma pequena function que percorre as folhas de estilo no documento procurando o seletor correspondente e depois o estilo.

Há uma ressalva, isso só funcionará para folhas de estilo definidas com uma tag de estilo ou folhas externas do mesmo domínio.

Se a planilha é conhecida, você pode passá-la e salvar-se de ter que procurar em várias planilhas (mais rápido e se você tiver regras colidindo, é mais exato).

Eu só testei no jsFiddle com alguns casos de teste fracos, deixe-me saber se isso funciona para você.

 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; } 

exemplo de uso:

 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]); 

editar:

Eu negligenciei levar em consideração as regras agrupadas. Eu mudei o seletor de seleção para isso:

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

Agora, ele verificará se algum dos seletores em uma regra agrupada corresponde.

Como você já está usando o jQuery, tente usar a function switchClass do jQuery-ui, que permitiria que você se switchClass com essa nova cor.

Por exemplo:

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

Demonstração


Caso você não queira include toda a biblioteca da interface do usuário, aqui está o código que eles usam:

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

E o 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 ] ); }); }); }; 

Trabalhando violino com todas as funções que são necessárias: http://jsfiddle.net/maniator/3C5ZQ/

A única solução que me vem à mente é a seguinte:

 //create an element with this class and append it to the DOM var eleToGetColor = $(' 
 .highlight { color: red; } div { width: 200px; height: 100px; color: blue; font-size: 6em; font-weight: bold; } 
    
TEST

Que tal agora?

 $('').appendTo('body'); $(this).animate({ color: $('.highlight').css('color') }, 750); $('.highlight').remove(); 

É meio sujo, mas vai lhe dar um elemento (vazio) para fazer referência ao valor CSS para o qual você está procurando.

Update Here é uma solução decente do CSS parser / abstracter? Como converter folhas de estilo em 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; } 

Uso

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

Aqui está um violino http://jsfiddle.net/wzXDx/1/ . Eu tive que usar styleSheets[1] para fazer isso funcionar no violino devido à natureza incorporada do ambiente.

Acabei de escrever esta function obter todos os estilos por um seletor. Aviso: O seletor deve ser o mesmo que no 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; } } } } 

Infelizmente eu não posso comentar sobre esta resposta incrível, mas encontrei um caso que não é fornecido (quando a class CSS é declarada várias vezes e a primeira declaração não tem o estilo que você está procurando), fez um jsFiddle para servir para isso:

 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; } 

Também tirou a divisão no condicional, não necessária e agora confirma que o estilo está presente na regra que está sendo verificada.

Apenas para shigiggles, criei um jsFiddle para armazenar em cache os estilos por seletor:

 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; } 

Embora se você usar isso, eu sugiro colocá-lo em um encerramento / aula. Mais uma vez obrigado a rlemon pelo original incrível.

Aqui está outro método: adicione um div oculto com a class aplicada. Use jQuery.css para procurar o valor do estilo. Em seguida, remova o elemento.

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') ); 

Por que não adicionar class .highlighted , armazenar em cache o estilo de color , removê-lo e animar a cor em cache? Ou seja, não acrescente elementos e não analise os estilos.

exemplo de jsfiddle

 var $element = $('.my-class').addClass('highlighted'); var colorToAnimate = $element.css('color'); $element.removeClass('highlighted'); alert(colorToAnimate); 
 .my-class { color: blue; } .highlighted { color: red; } 
  Animated color text