O jQuery pode obter todos os estilos CSS associados a um elemento?

297

Existe uma maneira no jQuery obter todo o CSS de um elemento existente e aplicá-lo a outro sem listar todos eles?

Eu sei que funcionaria se eles fossem um atributo de estilo attr(), mas todos os meus estilos estão em uma folha de estilos externa.

alex
fonte

Respostas:

340

Alguns anos atrasado, mas aqui está uma solução que recupera o estilo embutido e o 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;
}

Passe um objeto jQuery css()e ele retornará um objeto, que você poderá conectar novamente ao jQuery $().css(), ex:

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

:)

marknadal
fonte
14
BTW, quando você diz um objeto JSON , você quer dizer apenas um objeto JavaScript, certo?
28411 alex
3
isso parece incrível, mas quando estou tentando, perde algumas propriedades, como família de fontes.
Damon
3
@ Damon: Essa é uma suposição válida, considerando que a primeira linha da resposta diz ... aqui está uma solução que recupera o estilo em linha e o estilo externo .
alex
5
Este código não funciona mais (sempre retorna objeto vazio no Chrome)
Ivan Castellanos
12
Nota: Os moderadores modificaram meu código original, não garanto que tudo funcione.
marknadal
90

Dois anos atrasado, mas eu tenho a solução que você está procurando. Não pretendendo assumir o crédito do autor original , aqui está um plugin que eu achei que funciona excepcionalmente bem para o que você precisa, mas obtém todos os estilos possíveis em todos os navegadores, até no IE.

Aviso: Este código gera muita saída e deve ser usado com moderação. Ele não apenas copia todas as propriedades CSS padrão, mas também todas as propriedades CSS do fornecedor para esse 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);

O uso básico é bastante simples, mas ele também escreveu uma função para isso:

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

Espero que ajude.

Dakota
fonte
2
@ Damon: Obrigado! Atualizei minha postagem e editei um pouco o texto para deixar claro que esse não é meu trabalho. Desculpe pela redação anterior, acho que digitei essa resposta tarde da noite, mas de qualquer forma, foi bastante idiota.
Dakota
2
Por que isso retorna this.css()? Não há documentação para este método sem argumentos, e se essa instrução for atingida, ela lança uma exceção. Eu acho que seria mais apropriado, return returns;mesmo que seja um objeto vazio.
Tristan Lee
2
Seria possível obter uma demonstração funcional disso? Não está claro para mim onde colocar esse código e como invocá-lo. Também não está claro para mim onde a saída está sendo armazenada. Obrigado.
Cymro
Eu não entendo como usá-lo. Existe algo chamado jsfiddle que a maioria das pessoas usa para ajudar. Bom programador é o professor pior
Gino
@Gino Se você deseja copiar o estilo de div1 para div 2 uso apenas: $("#div2").copyCSS($("#div1"));e para obter o estilo de qualquer elemento que você poderia usar:JSON.stringify($('#element').getStyleObject());
Wessam El Mahdy
16

Por que não usar .styleo elemento DOM ? É um objeto que contém membros como widthe backgroundColor.

strager
fonte
1
Tenho certeza de que essa é a única maneira de obter os estilos reais associados à classe. (em oposição aos estilos calculados que são diferentes) #
1613
32
Com .style, você obtém apenas propriedades aplicadas ao atributo style do elemento, mas não aquelas aplicadas com uma classe CSS.
EricSonaron
+1 como im usando script embutido e mudá-lo de forma dinâmica afterwords
user991554
11

Eu tentei muitas soluções diferentes. Esse foi o único que funcionou para mim, pois foi capaz de captar os estilos aplicados no nível da classe e no estilo, como diretamente atribuídos ao elemento. Portanto, uma fonte definida no nível do arquivo css e outra como um atributo de estilo; retornou a fonte correta.

É simples! (Desculpe, não consigo encontrar onde o encontrei 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"]

Como alternativa, você pode listar todo o estilo percorrendo a matriz

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

A solução do @ marknadal não estava pegando propriedades hifenizadas para mim (por exemplo max-width), mas alterar o primeiro forloop css2json()fez com que funcionasse, e suspeito que realiza menos iterações:

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

Loops via em lengthvez de in,recupera via em getPropertyValue()vez detoLowerCase().

Brandon Hill
fonte