¿Puede jQuery obtener todos los estilos CSS asociados con un elemento?

297

¿Hay alguna manera en jQuery para obtener todos los CSS de un elemento existente y aplicarlos a otro sin enumerarlos todos?

Sé que funcionaría si fueran un atributo de estilo attr(), pero todos mis estilos están en una hoja de estilos externa.

alex
fuente

Respuestas:

340

Un par de años tarde, pero aquí hay una solución que recupera el estilo en línea y el estilo externo:

function css(a) {
    var sheets = document.styleSheets, o = {};
    for (var i in sheets) {
        var rules = sheets[i].rules || sheets[i].cssRules;
        for (var r in rules) {
            if (a.is(rules[r].selectorText)) {
                o = $.extend(o, css2json(rules[r].style), css2json(a.attr('style')));
            }
        }
    }
    return o;
}

function css2json(css) {
    var s = {};
    if (!css) return s;
    if (css instanceof CSSStyleDeclaration) {
        for (var i in css) {
            if ((css[i]).toLowerCase) {
                s[(css[i]).toLowerCase()] = (css[css[i]]);
            }
        }
    } else if (typeof css == "string") {
        css = css.split("; ");
        for (var i in css) {
            var l = css[i].split(": ");
            s[l[0].toLowerCase()] = (l[1]);
        }
    }
    return s;
}

Pase un objeto jQuery css()y devolverá un objeto, que luego puede volver a conectar a jQuery $().css(), por ejemplo:

var style = css($("#elementToGetAllCSS"));
$("#elementToPutStyleInto").css(style);

:)

Marknadal
fuente
14
Por cierto, cuando dices un objeto JSON , solo te refieres a un objeto JavaScript ¿verdad?
alex
3
Esto se ve increíble, pero cuando lo intento se pierde ciertas propiedades como font-family.
Damon
3
@Damon: Esa es una suposición válida, considerando que la primera línea de la respuesta dice ... aquí hay una solución que recupera tanto el estilo en línea como el estilo externo .
alex
55
Este código ya no funciona (siempre devuelve un objeto vacío en Chrome)
Ivan Castellanos
12
Nota: los moderadores han modificado mi código original, no garantizo que nada funcione.
marknadal
90

Dos años de retraso, pero tengo la solución que estás buscando. Sin la intención de obtener crédito del autor original , aquí hay un complemento que encontré funciona excepcionalmente bien para lo que necesita, pero obtiene todos los estilos posibles en todos los navegadores, incluso IE.

Advertencia: este código genera muchos resultados y debe usarse con moderación. No solo copia todas las propiedades CSS estándar, sino también todas las propiedades CSS del proveedor para ese navegador.

jquery.getStyleObject.js:

/*
 * getStyleObject Plugin for jQuery JavaScript Library
 * From: http://upshots.org/?p=112
 */

(function($){
    $.fn.getStyleObject = function(){
        var dom = this.get(0);
        var style;
        var returns = {};
        if(window.getComputedStyle){
            var camelize = function(a,b){
                return b.toUpperCase();
            };
            style = window.getComputedStyle(dom, null);
            for(var i = 0, l = style.length; i < l; i++){
                var prop = style[i];
                var camel = prop.replace(/\-([a-z])/g, camelize);
                var val = style.getPropertyValue(prop);
                returns[camel] = val;
            };
            return returns;
        };
        if(style = dom.currentStyle){
            for(var prop in style){
                returns[prop] = style[prop];
            };
            return returns;
        };
        return this.css();
    }
})(jQuery);

El uso básico es bastante simple, pero también ha escrito una función para eso:

$.fn.copyCSS = function(source){
  var styles = $(source).getStyleObject();
  this.css(styles);
}

Espero que ayude.

Dakota
fuente
2
@Damon: ¡Gracias! He actualizado mi publicación y editado un poco la redacción para dejar en claro que este no es mi trabajo. Perdón por la redacción anterior, creo que escribí esta respuesta tarde por la noche, pero de cualquier manera, fue bastante tonto.
Dakota
2
¿Por qué vuelve esto this.css()? No hay documentación para este método que no tome argumentos, y si se alcanza esta declaración, arroja una excepción. Creo que sería más apropiado return returns;incluso si es un objeto vacío.
Tristan Lee
2
¿Sería posible obtener una demostración funcional de esto? No me queda claro dónde poner este código y cómo invocarlo. Tampoco me queda claro dónde se almacena la salida. Gracias.
Cymro
No entiendo cómo usarlo. Hay algo llamado jsfiddle que la mayoría de la gente usa para ayudar. Un buen programador es el peor maestro
Gino
@Gino Si desea copiar el estilo de div1 en div 2 simplemente use: $("#div2").copyCSS($("#div1"));y para obtener el estilo de cualquier elemento que pueda usar:JSON.stringify($('#element').getStyleObject());
Wessam El Mahdy
16

¿Por qué no usar .styleel elemento DOM ? Es un objeto que contiene miembros como widthy backgroundColor.

extraño
fuente
1
Estoy bastante seguro de que esta es la única forma de obtener los estilos reales asociados con la clase. (a diferencia de los estilos calculados que son diferentes)
cgp
32
Con .style solo obtienes propiedades aplicadas al atributo de estilo del elemento, pero no las aplicadas con una clase CSS.
EricSonaron
+1 porque estoy usando un script en línea y cambiándolo dinámicamente después de las palabras
clave
11

Había probado muchas soluciones diferentes. Este fue el único que funcionó para mí, ya que fue capaz de retomar los estilos aplicados a nivel de clase y en el estilo directamente atribuido en el elemento. Entonces, una fuente establecida a nivel de archivo css y una como atributo de estilo; devolvió la fuente correcta.

¡Es simple! (Lo siento, no puedo encontrar donde lo encontré originalmente)

//-- html object
var element = htmlObject; //e.g document.getElementById
//-- or jquery object
var element = htmlObject[0]; //e.g $(selector)

var stylearray = document.defaultView.getComputedStyle(element, null);
var font = stylearray["font-family"]

Alternativamente, puede enumerar todo el estilo recorriendo la matriz

for (var key in stylearray) {
console.log(key + ': ' + stylearray[key];
}
Valamas
fuente
4

La solución de @ marknadal no fue obtener propiedades con guiones para mí (por ejemplo max-width), pero cambiar el primer forbucle lo css2json()hizo funcionar, y sospecho que realiza menos iteraciones:

for (var i = 0; i < css.length; i += 1) {
    s[css[i]] = css.getPropertyValue(css[i]);
}

Recorre vía en lengthlugar de in,recupera vía en getPropertyValue()lugar detoLowerCase().

Brandon Hill
fuente