Utwórz regułę / klasę CSS za pomocą jQuery w czasie wykonywania

189

Zwykle mam plik CSS, który ma następującą zasadę:

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

Jak mogę uniknąć tworzenia takiego statycznego pliku CSS, dodając informacje CSS podczas działań środowiska wykonawczego do ciała lub coś podobnego? (tylko przy użyciu jQuery)

Chcę to zdefiniować raz, ale za pomocą jQuery i użyć go wiele razy później; dlatego nie chcę dodawać go za każdym razem do określonych elementów DOM.

Znam proste funkcje ( css("attr1", "value");), ale jak mogę stworzyć kompletną regułę CSS wielokrotnego użytku?

stephan
źródło

Odpowiedzi:

269

Możesz utworzyć element stylu i wstawić go do DOM

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

testowany na Opera10 FF3.5 iE8 iE6

Taras Bulba
źródło
Istota jest samowystarczalna. Możesz go utworzyć lokalnie i będzie działał dobrze. Bezpośredni link do łącza pobierania: gist.github.com/gists/714352/download
Daniel Ribeiro
Nie ma problemu. Czasami może to być niewielki błąd wersji jQuery lub po prostu nieprawidłowa konfiguracja. Umowa z aplikacjami js jest taka: jeśli nie działają, po prostu w ogóle nie działają. Brak litości.
Daniel Ribeiro
1
Zgłasza mi błąd „ Nieoczekiwane wywołanie metody lub dostępu do właściwości ” w IE8. Musiałem śledzić ten artykuł, aby go uruchomić.
Brandon Boone
6
Na stronie może być tylko 31 stylów w IE9- blogs.msdn.com/b/ieinternals/archive/2011/05/14/…
IvanH
1
Jeśli to nie działa. Spróbuj dodać styl do body. tj.$("<style>...</style>").appendTo("body");
inDream
118

Po prostu

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

Zauważyłeś ukośniki? Służą do łączenia ciągów znaków w nowych liniach. Pozostawienie ich powoduje błąd.

bogonko
źródło
6
To. Powinna być zaakceptowana odpowiedź. Właściwie odpowiada na pytanie.
Johannes Pille,
2
Zgadzam się z @JohannesPille, to jest prawdziwa odpowiedź!
bayu
nie działa w Cordova ios. czy możesz to zasugerować?
RamGrg,
2
Dość wydajne i proste. Po wprowadzeniu nowej reguły do ​​nagłówka możesz ją pobrać w dowolnym miejscu na stronie, w tym w PHP.
Brice Coustillas,
tak samo jak stackoverflow.com/questions/1720320/…
user1742529
17

możesz zastosować css i obiekt. Możesz więc zdefiniować swój obiekt w javascript w następujący sposób:

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

A następnie po prostu zastosuj go do wszystkich wymaganych elementów

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

To jest wielokrotnego użytku. W jakim celu byś to zrobił?

Yuval Karmi
źródło
22
Powiedziałbym, że jest to reguła CSS, a nie klasa CSS.
hippietrail
17
Ta odpowiedź jest myląca. Pytający chciał utworzyć regułę CSS w czasie wykonywania, a nie ustawić styl określonego elementu na stałą (wielokrotnego użytku) deklarację CSS.
Dan Dascalescu,
4
Nie jest to dokładnie to, o co prosili, ale jest to właściwe rozwiązanie :) Wypełnienie domu dodatkowymi elementami <style> ma nieprzyjemny zapach kodu
Kevin
3
W jaki sposób usuniesz te zasady zastosowane, gdy zajdzie taka potrzeba, jest to możliwe w przypadku innych rozwiązań ...
Vishwanath,
@Kevin - może tak być, ale są chwile, kiedy właśnie tego potrzebujesz. na przykład - gdy element jest odtwarzany przez jakiś skrypt ajax i musisz zachować nową regułę stylu.
billynoah
12

Możesz użyć insertRule, jeśli nie potrzebujesz obsługi IE <9, zgodnie z dottoro . Jest tam również trochę kodu dla różnych przeglądarek.

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

Oto wtyczka jquery, która pozwala wstrzyknąć CSS:

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

Przykład:

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

To nie jest nic nowego w porównaniu z innymi odpowiedziami, ponieważ wykorzystuje koncepcję opisaną tutaj i tutaj , ale chciałem skorzystać z deklaracji w stylu JSON:

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

Stosowanie:

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

Nie jestem pewien, czy obejmuje on wszystkie możliwości CSS, ale jak dotąd działa dla mnie. Jeśli nie, uważaj to za punkt wyjścia do własnych potrzeb. :)

sjngm
źródło
7

Jeśli nie chcesz na stałe kodować CSS w bloku / pliku CSS, możesz użyć jQuery do dynamicznego dodawania CSS do elementów HTML, identyfikatorów i klas.

$(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
źródło
5
Ta odpowiedź nie jest dokładnie tym, o co pytał pytający. Pytający chciał utworzyć regułę CSS w czasie wykonywania, a nie ustawić styl określonego elementu na stałą deklarację CSS.
Dan Dascalescu,
Rozumiem, ale jest to alternatywne rozwiązanie, więc je podałem.
Mike Trpcic,
2
@MikeTrpcic Problem polega na tym, że inne osoby również szukają tego rozwiązania - aby dodać reguły css do strony - i twoja odpowiedź nie rozwiązuje tego.
data
5

Dodanie niestandardowych reguł jest przydatne, jeśli utworzysz widget jQuery, który wymaga niestandardowego CSS (np. Rozszerzenie istniejącej struktury jQueryUI CSS dla konkretnego widżetu). To rozwiązanie opiera się na odpowiedzi Tarasa (pierwsza powyżej).

Zakładając, że twój znacznik HTML ma przycisk z identyfikatorem „addrule” i div z identyfikatorem „target” zawierający trochę tekstu:

Kod 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");     
}       

Zaletą tego podejścia jest to, że można ponownie wykorzystywać zmienne cssrule w kodzie, aby dowolnie dodawać lub odejmować reguły. Jeśli cssrules jest osadzony w trwałym obiekcie, takim jak widget jQuery, masz do dyspozycji stałą lokalną zmienną.

fbloggs
źródło
Co za fajny pomysł! Użyłem go w połączeniu z fragmentem kodu na tej stronie ssdtutorials.com/tutorials/title/jquery-flashing-text.html, aby umożliwić przełączanie kolorów (oryginał przełączałby tylko klasę). Dzięki!
bgmCoder
5

Pamiętaj, że jQuery().css()nie zmienia reguł arkusza stylów, zmienia jedynie styl każdego dopasowanego elementu.

Zamiast tego oto funkcja javascript, którą napisałem, aby zmodyfikować same reguły arkuszy stylów.

    /**
     * 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);
        }
    }

Zalety:

  • Style mogą być obliczane w <head>skrypcie przed utworzeniem elementów DOM, a zatem przed pierwszym renderowaniem dokumentu, unikając irytującego wizualnie renderowania, a następnie obliczania, a następnie renderowania. W jQuery musisz poczekać na utworzenie elementów DOM, a następnie zmienić ich styl i zrenderować.
  • Elementy dodane dynamicznie po zmianie stylu automatycznie zastosują nowe style bez dodatkowego wywołania jQuery(newElement).css()

Ostrzeżenia:

  • Użyłem go w Chrome i IE10. Myślę, że może potrzebować niewielkiej modyfikacji, aby działała dobrze na starszych wersjach IE. W szczególności starsze wersje IE mogły nie s.cssRuleszdefiniować, więc wrócą do tego, s.rulesco ma pewne osobliwości, takie jak dziwne / błędne zachowanie związane z selektorami rozdzielanymi przecinkami, jak "body, p". Jeśli ich unikniesz, możesz być w porządku w starszych wersjach IE bez modyfikacji, ale jeszcze tego nie przetestowałem.
  • Obecnie selektory muszą dokładnie pasować: używaj małych liter i uważaj na listy rozdzielane przecinkami; kolejność musi być zgodna i powinny mieć format, "first, second"tzn. separatorem jest przecinek, po którym następuje spacja.
  • Prawdopodobnie można poświęcić na to trochę więcej czasu, próbując wykryć i inteligentnie obsługiwać nakładające się selektory, takie jak te na listach rozdzielanych przecinkami.
  • Można również dodać obsługę zapytań o media i !importantmodyfikatora bez większych problemów.

Jeśli chcesz ulepszyć tę funkcję, znajdziesz tutaj przydatne dokumenty API: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet

Craig
źródło
5

W (nietypowych) przypadkach, w których chcesz często dynamicznie zmieniać style - np. Aplikacja do budowania motywów - dodanie tagów <style> lub wywołanie CSSStyleSheet.insertRule () spowoduje powstanie arkusza stylów, który może mieć wydajność i wygląd implikacje debugowania.

Moje podejście pozwala tylko na jedną regułę na kombinację selektora / właściwości, usuwając wszelkie istniejące po ustawieniu dowolnej reguły. Interfejs API jest prosty i elastyczny:

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

Stosowanie:

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

clearStyle('body', 'background-color');
addStyle('body', 'color', '#333')
Jason Boyd
źródło
3

Co jeśli dynamicznie napisałeś sekcję <skrypt> na swojej stronie (z twoimi dynamicznymi regułami), a następnie użyłeś jQuerys .addClass (klasa), aby dodać te dynamicznie tworzone reguły?

Nie próbowałem tego, po prostu oferując teorię, która może zadziałać.

Bryan Denny
źródło
szwy najlepiej teraz. znalazłem coś jQuery.cssRule, ale jest jakaś wtyczka: - /
stephan
2
$ („head”). append ($ („<style type = 'text / css'>> ... to jeden sposób
stephan
2

Trochę leniwa odpowiedź na to pytanie, ale następujący artykuł może pomóc: http://www.javascriptkit.com/dhtmltutors/externalcss3.shtml

Spróbuj także wpisać „zmodyfikuj reguły css” w Google

Nie jestem pewien, co by się stało, gdybyś próbował zawinąć document.styleSheets [0] za pomocą jQuery (), choć możesz spróbować

James Wiseman
źródło
2

Możesz użyć wtyczki cssRule . Kod był wtedy prosty:

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

W jednym z dotychczasowych komentarzy zapytano, dlaczego ktoś chciałby zrobić coś takiego. Na przykład tworzenie stylów dla listy, w której każdy element potrzebuje odrębnego koloru tła (np. Lista kalendarzy GCal), w której liczba kolumn nie jest znana do czasu uruchomienia.

Robert Gowland
źródło
@Daniel, tak to robi; instrukcja została usunięta.
Robert Gowland
wygląda na to, że nie obsługuje następującej reguły:div:before{content:'name: ';}
liuyanghejerry,
2

Oto konfiguracja, która daje kontrolę nad kolorami za pomocą tego obiektu 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)"]
  }

ta funkcja

 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"))
    )
}

aby stworzyć ten element stylu

.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
źródło
1

jeśli nie chcesz przypisywać display: none do klasy css, odpowiednie podejście do dołączenia do stylu, jQuery.Rule wykona zadanie.

W niektórych przypadkach chcesz zastosować słupki przed zdarzeniem dołączającym zawartość ajax i zanikać zawartość po dołączeniu i to jest to!

Mattia
źródło
1

Tutaj masz funkcję, aby uzyskać pełną definicję klasy 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
źródło
1

Możesz użyć tej biblioteki o nazwie cssobj

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

W dowolnym momencie możesz zaktualizować swoje reguły w ten sposób:

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

Potem zmieniłeś regułę. jQuery nie robi tego lib.

James Yang
źródło
0

Niedawno miałem z tym problem i przy programowaniu witryny iPhone / iPod zastosowałem dwa różne podejścia.

Pierwszy sposób, w jaki natrafiłem, szukając zmian orientacji, aby zobaczyć, czy telefon jest pionowy, czy poziomy, jest to bardzo statyczny sposób, ale prosty i sprytny:

W CSS:

#content_right,
#content_normal{
 display:none;
}

W pliku 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);
}

W PHP / HTML (najpierw zaimportuj plik JS, a następnie w tagu body):

<body onorientationchange="updateOrientation();">

Zasadniczo wybiera inny wstępnie ustawiony blok CSS do uruchomienia w zależności od wyniku zwróconego z pliku JS.

Również bardziej dynamiczny sposób, który wolałem, to bardzo prosty dodatek do znacznika skryptu lub pliku JS:

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

Działa to w większości przeglądarek, ale w IE najlepiej jest zabrać amunicję za pomocą czegoś mocniejszego:

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

Lub możesz użyć getElementByClass()i zmienić zakres przedmiotów.

Mam nadzieję że to pomoże!

Popiół.

Popiół
źródło
-2

Być może możesz umieścić informacje o stylu w osobnej klasie w pliku css, np .:

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

a następnie użyć jQuery w punkcie, w którym chcesz dodać tę nazwę klasy do elementu?

JorenB
źródło
1
i nie chcesz umieszczać informacji w sekcji nagłówka strony (między tagami stylu)?
JorenB
-2

Możesz po prostu stworzyć klasę css o nazwie coś takiego jak .fixed-object, w którym jest cały twój css ...

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

Następnie w jquery, kiedy chcesz, aby coś miało ten styl, po prostu dodaj do niego tę klasę ...

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

To chyba najłatwiejszy sposób, chyba że nie rozumiem, co należy zrobić.

Sir David z Lee
źródło
-9

Używając .addClass () w jquery, możemy dynamicznie dodawać styl do elementów na stronie. na przykład. mamy styl

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

Teraz w stanie gotowości jquery możemy dodać css jak .addClass (myStyle)

Avinash
źródło