Crie uma regra / classe CSS com jQuery em tempo de execução

189

Normalmente, tenho um arquivo CSS com a seguinte regra:

#my-window {
    position: fixed;
    z-index: 102;
    display:none;
    top:50%;
    left:50%;
}

Como evitar a criação de um arquivo CSS estático adicionando ao corpo as informações CSS durante as ações de tempo de execução, ou algo semelhante? (apenas usando jQuery)

Eu quero defini-lo uma vez, mas com jQuery e usá-lo muitas vezes depois; é por isso que não quero adicioná-lo sempre aos elementos DOM específicos.

Conheço os recursos simples ( css("attr1", "value");), mas como posso criar uma regra CSS reutilizável completa?

stephan
fonte

Respostas:

269

Você pode criar um elemento de estilo e inseri-lo no DOM

$("<style type='text/css'> .redbold{ color:#f00; font-weight:bold;} </style>").appendTo("head");
$("<div/>").addClass("redbold").text("SOME NEW TEXT").appendTo("body");

testado no Opera10 FF3.5 iE8 iE6

Taras Bulba
fonte
A essência é auto-suficiente. Você pode criá-lo localmente e funcionará bem. Link direto para o link de download: gist.github.com/gists/714352/download
Daniel Ribeiro
Sem problemas. Às vezes, pode ser um bug da versão secundária do jQuery ou apenas uma configuração incorreta. O acordo com js apps é o seguinte: se eles não funcionam, simplesmente não funcionam. Sem perdão.
Daniel Ribeiro
1
Lança um erro ' Chamada inesperada para acesso a método ou propriedade ' para mim no IE8. Eu tive que seguir este artigo para fazê-lo funcionar.
Brandon Boone #
6
Só pode haver 31 estilos na página no IE9- blogs.msdn.com/b/ieinternals/archive/2011/05/14/…
IvanH
1
Se não funcionar. Tente anexar estilo a body. isto é,$("<style>...</style>").appendTo("body");
inDream
118

Simplesmente

$("<style>")
    .prop("type", "text/css")
    .html("\
    #my-window {\
        position: fixed;\
        z-index: 102;\
        display:none;\
        top:50%;\
        left:50%;\
    }")
    .appendTo("head");

Percebeu as barras traseiras? Eles são usados ​​para unir strings que estão em novas linhas. Deixá-los de fora gera um erro.

bogonko
fonte
6
Este. Deve ser a resposta aceita. Na verdade, responde à pergunta.
Johannes Pille
2
Concordo com @JohannesPille, esta é a resposta real!
bayu
não está funcionando no cordova ios. você poderia sugerir isso?
RamGrg
2
Bastante eficiente e direto. Depois que a nova regra é injetada no cabeçalho, você pode recuperá-la em qualquer lugar da sua página, inclusive no PHP.
Brice Coustillas
o mesmo que stackoverflow.com/questions/1720320/…
user1742529
17

você pode aplicar css a um objeto. Assim, você pode definir seu objeto em seu javascript da seguinte maneira:

var my_css_class = { backgroundColor : 'blue', color : '#fff' };

E, em seguida, basta aplicá-lo a todos os elementos que você deseja

$("#myelement").css(my_css_class);

Portanto, é reutilizável. Para que finalidade você faria isso?

Yuval Karmi
fonte
22
Eu diria que esta é uma regra CSS e não uma classe CSS.
Hippietrail
17
Esta resposta é enganosa. O solicitante queria criar uma regra CSS em tempo de execução, não definir o estilo de um elemento específico para uma declaração CSS constante (reutilizável).
Dan Dascalescu
4
Não é bem o que pediram, mas é a solução certa :) Encher o dom com adicional <style> elementos tem algum cheiro de código desagradável
Kevin
3
Como você irá remover essas regras aplicadas quando você precisa, isso é possível com outras soluções ...
Vishwanath
@ Kevin - pode ser que sim, mas há momentos em que isso é exatamente o que você precisa. por exemplo - quando um elemento está sendo recriado por algum script ajax e você precisa manter uma nova regra de estilo.
billynoah
12

Você pode usar insertRule se não precisar dar suporte ao IE <9, de acordo com o dottoro . Também existe um pouco de código entre navegadores.

document.styleSheets[0].insertRule('#my-window {\
    position: fixed;\
    z-index: 102;\
    display:none;\
    top:50%;\
    left:50%;\
}', 0)
Sean
fonte
9

Aqui está um plugin jquery que permite injetar CSS:

https://github.com/kajic/jquery-injectCSS

Exemplo:

$.injectCSS({
    "#my-window": {
        "position": "fixed",
        "z-index": 102,
        "display": "none",
        "top": "50%",
        "left": "50%"
    }
});
Robert Kajic
fonte
9

Isso não é novidade em comparação com algumas das outras respostas, pois usa o conceito descrito aqui e aqui , mas eu queria usar a declaração no estilo JSON:

function addCssRule(rule, css) {
  css = JSON.stringify(css).replace(/"/g, "").replace(/,/g, ";");
  $("<style>").prop("type", "text/css").html(rule + css).appendTo("head");
}

Uso:

addCssRule(".friend a, .parent a", {
  color: "green",
  "font-size": "20px"
});

Não tenho certeza se ele cobre todos os recursos do CSS, mas até agora funciona para mim. Caso contrário, considere-o um ponto de partida para suas próprias necessidades. :)

sjngm
fonte
7

Se você não deseja codificar o CSS em um bloco / arquivo CSS, é possível usar o jQuery para adicionar dinamicamente o CSS aos elementos, IDs e classes HTML.

$(document).ready(function() {
  //Build your CSS.
  var body_tag_css = {
    "background-color": "#ddd",
    "font-weight": "",
    "color": "#000"
  }
  //Apply your CSS to the body tag.  You can enter any tag here, as
  //well as ID's and Classes.
  $("body").css(body_tag_css);
});
Mike Trpcic
fonte
5
Essa resposta não é exatamente o que o solicitante pediu. O solicitante queria criar uma regra CSS em tempo de execução, não definir o estilo de um elemento específico para uma declaração CSS constante.
Dan Dascalescu
Eu entendo, mas esta é uma solução alternativa, então eu a forneci.
Mike Trpcic
2
@MikeTrpcic O problema é que também há outras pessoas pesquisando essa solução - para adicionar regras de CSS a uma página - e sua resposta não resolve isso.
nate
5

Adicionar regras personalizadas é útil se você criar um widget jQuery que exija CSS personalizado (como estender a estrutura CSS jQueryUI existente para o seu widget em particular). Esta solução baseia-se na resposta de Taras (a primeira acima).

Supondo que sua marcação HTML tenha um botão com um ID de "addrule" e uma div com um ID de "target" contendo algum texto:

Código jQuery:

$( "#addrule" ).click(function () { addcssrule($("#target")); });

function addcssrule(target) 
{ 
var cssrules =  $("<style type='text/css'> </style>").appendTo("head");

cssrules.append(".redbold{ color:#f00; font-weight:bold;}"); 
cssrules.append(".newfont {font-family: arial;}"); 
target.addClass("redbold newfont");     
}       

A vantagem dessa abordagem é que você pode reutilizar cssrules variáveis ​​no seu código para adicionar ou subtrair regras à vontade. Se cssrules estiver incorporado em um objeto persistente, como um widget jQuery, você terá uma variável local persistente para trabalhar.

fbloggs
fonte
Que ótima ideia! Usei-o em conjunto com o snippet nesta página ssdtutorials.com/tutorials/title/jquery-flashing-text.html para permitir alternar uma cor (o original alternaria apenas uma classe). Obrigado!
bgmCoder
5

Observe que jQuery().css()não altera as regras da folha de estilo, apenas altera o estilo de cada elemento correspondente.

Em vez disso, aqui está uma função javascript que escrevi para modificar as regras da folha de estilo.

    /**
     * Modify an existing stylesheet.
     * - sheetId - the id of the <link> or <style> element that defines the stylesheet to be changed
     * - selector - the id/class/element part of the rule.  e.g. "div", ".sectionTitle", "#chapter2"
     * - property - the CSS attribute to be changed.  e.g. "border", "font-size"
     * - value - the new value for the CSS attribute.  e.g. "2px solid blue", "14px"
     */
    function changeCSS(sheetId, selector, property, value){
        var s = document.getElementById(sheetId).sheet;
        var rules = s.cssRules || s.rules;
        for(var i = rules.length - 1, found = false; i >= 0 && !found; i--){
            var r = rules[i];
            if(r.selectorText == selector){
                r.style.setProperty(property, value);
                found = true;
            }
        }
        if(!found){
            s.insertRule(selector + '{' + property + ':' + value + ';}', rules.length);
        }
    }

Vantagens:

  • Os estilos podem ser calculados em um <head> script antes da criação dos elementos DOM e, portanto, antes da primeira renderização do documento, evitando uma renderização visualmente irritante, depois computando e renderizando novamente. Com o jQuery, é necessário aguardar a criação dos elementos DOM, modificá-los e renderizá-los novamente.
  • Os elementos adicionados dinamicamente após o restyle terão automaticamente os novos estilos aplicados sem uma chamada extra para jQuery(newElement).css()

Ressalvas:

  • Eu usei no Chrome e IE10. Eu acho que pode precisar de uma pequena modificação para fazê-lo funcionar bem em versões mais antigas do IE. Em particular, as versões mais antigas do IE podem não ter sido s.cssRulesdefinidas; portanto, elas voltarão a s.rulester algumas peculiaridades, como comportamento de bugs / erros relacionados a seletores delimitados por vírgulas, como "body, p". Se você evitá-las, pode estar bem nas versões mais antigas do IE sem modificação, mas ainda não a testei.
  • Atualmente, os seletores precisam corresponder exatamente: use letras minúsculas e tenha cuidado com listas delimitadas por vírgulas; a ordem precisa corresponder e eles devem estar no formato, "first, second"ou seja, o delimitador é uma vírgula seguida por um caractere de espaço.
  • Provavelmente, poderia-se gastar algum tempo adicional tentando detectar e manipular inteligentemente seletores sobrepostos, como aqueles em listas delimitadas por vírgulas.
  • Pode-se também adicionar suporte para consultas de mídia e !importantmodificador sem muitos problemas.

Se você quiser fazer algumas melhorias nessa função, encontrará alguns documentos úteis da API aqui: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet

Craig
fonte
5

Nos casos (incomuns) em que você deseja alterar dinamicamente os estilos com frequência - por exemplo, um aplicativo construtor de temas - adicionar tags <style> ou chamar CSSStyleSheet.insertRule () resultará em uma folha de estilo crescente, que pode ter desempenho e design implicações de depuração.

Minha abordagem permite apenas uma única regra por combinação de seletor / propriedade, limpando qualquer existente ao definir qualquer regra. A API é simples e flexível:

function addStyle(selector, rulename, value) {
    var stylesheet = getAppStylesheet();
    var cssRules = stylesheet.cssRules || stylesheet.rules;
    var rule = stylesheet.insertRule(selector + ' { ' + rulename + ':' + value + ';}', cssRules.length);
}

function clearStyle(selector, rulename) {
    var stylesheet = getAppStylesheet();
    var cssRules = stylesheet.cssRules || stylesheet.rules;
    for (var i=0; i<cssRules.length; i++) {
        var rule = cssRules[i];
        if (rule.selectorText == selector && rule.style[0] == rulename) {
            stylesheet.deleteRule(i);
            break;
        }
    }       
}

function addStyles(selector, rules) {
    var stylesheet = getAppStylesheet();
    var cssRules = stylesheet.cssRules || stylesheet.rules;
    for (var prop in rules) {
        addStyle(selector, prop, rules[prop]);
    }
}

function getAppStylesheet() {
    var stylesheet = document.getElementById('my-styles');
    if (!stylesheet) {
        stylesheet = $('<style id="my-styles">').appendTo('head')[0];
    }
    stylesheet = stylesheet.sheet;
    return stylesheet;
}

Uso:

addStyles('body', {
    'background-color': 'black',
    color: 'green',
    margin: 'auto'
});

clearStyle('body', 'background-color');
addStyle('body', 'color', '#333')
Jason Boyd
fonte
3

E se você escrevesse dinamicamente uma seção <script> em sua página (com suas regras dinâmicas) e usasse jQuerys .addClass (class) para adicionar essas regras criadas dinamicamente?

Eu não tentei isso, apenas oferecendo uma teoria que pode funcionar.

Bryan Denny
fonte
costuras a melhor maneira agora. Eu encontrei algo jQuery.cssRule, mas é algum tipo de plugin: - /
stephan
2
$ ("head"). append ($ ("<style type = 'text / css'>> é um caminho)
stephan
2

Um pouco preguiçoso, responda a isso, mas o seguinte artigo pode ajudar: http://www.javascriptkit.com/dhtmltutors/externalcss3.shtml

Além disso, tente digitar "modificar regras de css" no google

Não tenho certeza do que aconteceria se você tentasse quebrar um documento.styleSheets [0] com jQuery (), mas você poderia tentar

James Wiseman
fonte
2

Você pode usar o plug-in cssRule . O código era simples então:

$.cssRule("#my-window {
    position: fixed;
    z-index: 102;
    display:none;
    top:50%;
    left:50%;
}");

Até agora, um dos comentários perguntou por que alguém iria querer fazer uma coisa dessas. Por exemplo, a criação de estilos para uma lista em que cada item precisa de uma cor de plano de fundo distinta (por exemplo, lista de calendários do GCal) em que o número de colunas não é conhecido até o tempo de execução.

Robert Gowland
fonte
@ Daniel, sim; declaração removida.
Robert Gowland
parece que não suporta regras como esta:div:before{content:'name: ';}
liuyanghejerry 9/11/11
2

Aqui está uma configuração que fornece comando sobre cores com este objeto json

 "colors": {
    "Backlink": ["rgb(245,245,182)","rgb(160,82,45)"],
    "Blazer": ["rgb(240,240,240)"],
    "Body": ["rgb(192,192,192)"],
    "Tags": ["rgb(182,245,245)","rgb(0,0,0)"],
    "Crosslink": ["rgb(245,245,182)","rgb(160,82,45)"],
    "Key": ["rgb(182,245,182)","rgb(0,118,119)"],
    "Link": ["rgb(245,245,182)","rgb(160,82,45)"],
    "Link1": ["rgb(245,245,182)","rgb(160,82,45)"],
    "Link2": ["rgb(245,245,182)","rgb(160,82,45)"],
    "Manager": ["rgb(182,220,182)","rgb(0,118,119)"],
    "Monitor": ["rgb(255,230,225)","rgb(255,80,230)"],
    "Monitor1": ["rgb(255,230,225)","rgb(255,80,230)"],
    "Name": ["rgb(255,255,255)"],
    "Trail": ["rgb(240,240,240)"],
    "Option": ["rgb(240,240,240)","rgb(150,150,150)"]
  }

esta função

 function colors(fig){
    var html,k,v,entry,
    html = []
    $.each(fig.colors,function(k,v){
        entry  = "." + k ;
        entry += "{ background-color :"+ v[0]+";";
        if(v[1]) entry += " color :"+ v[1]+";";
        entry += "}"
        html.push(entry)
    });
    $("head").append($(document.createElement("style"))
        .html(html.join("\n"))
    )
}

para produzir esse elemento de estilo

.Backlink{ background-color :rgb(245,245,182); color :rgb(160,82,45);}
.Blazer{ background-color :rgb(240,240,240);}
.Body{ background-color :rgb(192,192,192);}
.Tags{ background-color :rgb(182,245,245); color :rgb(0,0,0);}
.Crosslink{ background-color :rgb(245,245,182); color :rgb(160,82,45);}
.Key{ background-color :rgb(182,245,182); color :rgb(0,118,119);}
.Link{ background-color :rgb(245,245,182); color :rgb(160,82,45);}
.Link1{ background-color :rgb(245,245,182); color :rgb(160,82,45);}
.Link2{ background-color :rgb(245,245,182); color :rgb(160,82,45);}
.Manager{ background-color :rgb(182,220,182); color :rgb(0,118,119);}
.Monitor{ background-color :rgb(255,230,225); color :rgb(255,80,230);}
.Monitor1{ background-color :rgb(255,230,225); color :rgb(255,80,230);}
.Name{ background-color :rgb(255,255,255);}
.Trail{ background-color :rgb(240,240,240);}
.Option{ background-color :rgb(240,240,240); color :rgb(150,150,150);}
Chris Glasier
fonte
1

se você não deseja atribuir uma exibição: none a uma classe css, a abordagem correta para acrescentar ao estilo, o jQuery.Rule faz o trabalho.

Em alguns casos, você deseja aplicar stiles antes do evento de acréscimo do conteúdo ajax e desaparecer após o acréscimo, e é isso!

Mattia
fonte
1

Aqui você tem uma função para obter a definição completa de uma classe CSS:

getCSSStyle = function (className) {
   for (var i = 0; i < document.styleSheets.length; i++) {
       var classes = document.styleSheets[i].rules || document.styleSheets[i].cssRules;
       for (var x = 0; x < classes.length; x++) {
           if (classes[x].selectorText  && - 1 != classes[x].selectorText.indexOf(className)) {
               return classes[x].cssText || classes[x].style.cssText;
           }
       }
   }
   return '';
};
berniecc
fonte
1

Você pode usar esta lib chamada cssobj

var result = cssobj({'#my-window': {
  position: 'fixed',
  zIndex: '102',
  display:'none',
  top:'50%',
  left:'50%'
}})

A qualquer momento, você pode atualizar suas regras assim:

result.obj['#my-window'].display = 'block'
result.update()

Então você mudou a regra. O jQuery não é a biblioteca que está fazendo isso.

James Yang
fonte
0

Eu tenho mexido com isso recentemente e usei duas abordagens diferentes ao programar um site para iPhone / iPod.

A primeira maneira que me deparei ao procurar mudanças de orientação, para que você possa ver se o telefone é retrato ou paisagem, é uma maneira muito estática, mas simples e inteligente:

Em CSS:

#content_right,
#content_normal{
 display:none;
}

No arquivo JS:

function updateOrientation(){
  var contentType = "show_";
  switch(window.orientation){
   case 0:
   contentType += "normal";
   break;

   case -90:
   contentType += "right";
   break; document.getElementById("page_wrapper").setAttribute("class",contentType);
}

Em PHP / HTML (importe seu arquivo JS primeiro e depois na tag body):

<body onorientationchange="updateOrientation();">

Basicamente, isso escolhe um bloco CSS predefinido diferente para executar, dependendo do resultado retornado do arquivo JS.

Além disso, a maneira mais dinâmica que eu preferia era uma adição muito simples a uma tag de script ou seu arquivo JS:

document.getelementbyid(id).style.backgroundColor = '#ffffff';

Isso funciona para a maioria dos navegadores, mas para o IE é melhor remover a munição com algo mais apertado:

var yourID = document.getelementbyid(id); 
 if(yourID.currentstyle) { 
  yourID.style.backgroundColor = "#ffffff";      // for ie :@ 
 } else { 
  yourID.style.setProperty("background-color", "#ffffff");        // everything else :)
 }

Ou você pode usar getElementByClass()e alterar uma variedade de itens.

Espero que isto ajude!

Cinza.

Cinza
fonte
-2

Talvez você possa colocar as informações de estilo em uma classe separada no seu arquivo css, por exemplo:

.specificstyle {
    position: fixed;
    z-index: 102;
    display:none;
    top:50%;
    left:50%;
}

e, em seguida, use jQuery no momento da sua escolha para adicionar esse nome de classe ao elemento?

JorenB
fonte
1
e você não deseja colocar as informações na seção principal da sua página (entre as tags de estilo)?
JorenB
-2

Você pode apenas criar uma classe css chamada algo como .fixed-object que contém todo o seu css ...

.fixed-object{
    position: fixed;
    z-index: 102;
    display:none;
    top:50%;
    left:50%;
}

Então, no jquery, sempre que você quiser que algo tenha esse estilo, basta adicionar essa classe a ele ...

$(#my-window).addClass('fixed-object');

Essa parece ser a maneira mais fácil de fazer isso, a menos que eu esteja entendendo mal o que você precisa fazer.

Sir David de Lee
fonte
-9

Usando .addClass () no jquery, podemos adicionar dinamicamente estilo aos elementos da página. por exemplo. nós temos estilo

.myStyle
{
  width:500px;
  height:300px;
  background-color:red;
 }

Agora, no estado pronto de jquery, podemos adicionar css como .addClass (myStyle)

Avinash
fonte