JavaScript'ten CSS sözde sınıf kuralları belirleme


125

JavaScript'ten sahte sınıf seçiciler için CSS kurallarını (örneğin: link,: hover, vb.) Değiştirmenin bir yolunu arıyorum.

Yani CSS kodunun bir analogu: a:hover { color: red }JS'de.

Cevabı başka hiçbir yerde bulamadım; Bunun tarayıcıların desteklemediği bir şey olduğunu bilen biri varsa, bu da faydalı bir sonuç olacaktır.

Yanıtlar:


192

Bir sözde sınıfa, bir satır içi stil = "..." özniteliğinde bir sözde sınıfa sahip olamayacağınız gibi (seçici olmadığı için) tek başına belirli bir öğe üzerinde stil veremezsiniz.

Stil sayfasını değiştirerek, örneğin kuralı ekleyerek yapabilirsiniz:

#elid:hover { background: red; }

Etkilemek istediğiniz her bir öğenin seçilmesine izin verecek benzersiz bir kimliği olduğunu varsayarsak.

Teoride, istediğiniz belge http://www.w3.org/TR/DOM-Level-2-Style/Overview.html'dir, bu da (önceden var olan gömülü veya bağlantılı bir stil sayfası verildiğinde) aşağıdaki gibi sözdizimini kullanarak yapabileceğiniz anlamına gelir:

document.styleSheets[0].insertRule('#elid:hover { background-color: red; }', 0);
document.styleSheets[0].cssRules[0].style.backgroundColor= 'red';

IE, elbette kendi sözdizimini gerektirir:

document.styleSheets[0].addRule('#elid:hover', 'background-color: red', 0);
document.styleSheets[0].rules[0].style.backgroundColor= 'red';

Eski ve küçük tarayıcılar büyük olasılıkla her iki sözdizimini de desteklemeyecektir. Dinamik stil sayfası kurcalaması nadiren yapılır çünkü doğru yapmak oldukça can sıkıcıdır, nadiren ihtiyaç duyulur ve tarihsel olarak zahmetlidir.


32
Neden bu cevap olarak seçilmedi?
SZH


2
Firefox: "Hata: İşlem güvenli değil."
8128

@fluteflute, bir CSS dosyasını farklı bir etki alanından değiştirmeye çalışıyorsanız, işlemin güvenli olmadığı kabul edilir (sanırım bu bir tür aynı kökenli politika meselesi). Utanç! Kontrol etmek için basit işlev aynı menşe politikasına function sameOrigin(url) { var loc = window.location, a = document.createElement('a'); a.href = url; return a.hostname === loc.hostname && a.port === loc.port && a.protocol === loc.protocol; }
uygunluk

3
Stil sayfasının yalnızca belirli bir öğeye stil uygulamak için değiştirilmesi, tarayıcının stil sayfası her değiştirildiğinde tüm belgeyi yeniden düzenlemesine neden olduğundan önerilmez. stubbornella.org/content/2009/03/27/…
Johannes Ewald

29

Ben birlikte bir attı bunun için küçük bir kütüphane Ben JS stil manipüle için geçerli kullanım örnekleri sizce beri. Olma nedenleri:

  • Hesaplanması veya alınması gereken stilleri ayarlama - örneğin, kullanıcının bir çerezden tercih ettiği yazı tipi boyutunu ayarlama.
  • Özellikle UI pencere öğesi / eklenti geliştiricileri için davranışsal (estetik değil) stilleri ayarlama. Sekmeler, karuseller, vb. Genellikle basitçe çalışması için bazı temel CSS'ler gerektirir - temel işlev için bir stil sayfası talep etmemelidir .
  • Satır içi stillerden daha iyidir, çünkü CSS kuralları tüm mevcut ve gelecekteki öğeler için geçerlidir ve Firebug / Developer Tools'da görüntülerken HTML'yi karıştırmaz.

17

Tarayıcılar arası şeylerle başa çıkmak için bir işlev:

addCssRule = function(/* string */ selector, /* string */ rule) {
  if (document.styleSheets) {
    if (!document.styleSheets.length) {
      var head = document.getElementsByTagName('head')[0];
      head.appendChild(bc.createEl('style'));
    }

    var i = document.styleSheets.length-1;
    var ss = document.styleSheets[i];

    var l=0;
    if (ss.cssRules) {
      l = ss.cssRules.length;
    } else if (ss.rules) {
      // IE
      l = ss.rules.length;
    }

    if (ss.insertRule) {
      ss.insertRule(selector + ' {' + rule + '}', l);
    } else if (ss.addRule) {
      // IE
      ss.addRule(selector, rule, l);
    }
  }
};

8

Sadece css'yi bir şablon dizesine yerleştirin.

const cssTemplateString = `.foo:[psuedoSelector]{prop: value}`;

Ardından bir stil öğesi oluşturun ve dizeyi stil etiketine yerleştirin ve belgeye ekleyin.

const styleTag = document.createElement("style");
styleTag.innerHTML = cssTemplateString;
document.head.insertAdjacentElement('beforeend', styleTag);

Gerisini özgüllük halleder. Ardından, stil etiketlerini dinamik olarak kaldırabilir ve ekleyebilirsiniz. Bu, DOM'daki kitaplıklara ve stil sayfası dizisiyle uğraşmaya basit bir alternatiftir. Mutlu Kodlama!


insertAdjacentElementbaşlıca tarayıcılarda (Chrome, Firefox, Edge) 2 argüman gerektirir, bunlardan ilki referans öğeye göre konumu belirler ( buraya bakın ). Bu yeni bir değişiklik mi? (Cevaba 'ön uç' eklendi).
collapsar

6

Benim hünerim bir öznitelik seçici kullanmaktır. Özniteliklerin javascript ile ayarlanması daha kolaydır.

css

.class{ /*normal css... */}
.class[special]:after{ content: 'what you want'}

javaScript

  function setSpecial(id){ document.getElementById(id).setAttribute('special', '1'); }

html

<element id='x' onclick="setSpecial(this.id)"> ...  

4
Bu çözüm jQuery kullanır - soru soran kişi saf Javascript istediğinde, bu kadar basit bir şey için jQuery boyutuna bir bağımlılık getirir.
Tom Ashworth

Pratik olarak günümüzde tüm web siteleri jquery kullanmasına rağmen, onu saf javascript kullanmak için değiştireceğim.
Sergio Abreu

1
Ve bu yöntem .class [özel] 'in CSS özniteliklerini tam olarak nasıl değiştiriyor: sözde öğeden sonra, arka plan rengi veya başka bir şey?
andreszs

5

Başka bir alternatif var. Sözde sınıfları doğrudan manipüle etmek yerine, bir "vurgulu" sınıf veya "ziyaret edilen" bir sınıf gibi aynı şeyleri modelleyen gerçek sınıflar oluşturun. Her zamanki "" ile sınıfları biçimlendirin. sözdizimi ve ardından uygun olay tetiklendiğinde bir öğeden sınıfları eklemek veya kaldırmak için JavaScript'i kullanabilirsiniz.


2
Bu işe yaramaz: sözde sınıflardan önce ve sonra.
jbyrd

Ve bu, AJAX aracılığıyla alınan bir değerle arka plan resmini değiştirmek için geçerli değildir.
andreszs

1
@jbyrd :before& :aftersözde öğelerdir, sınıflar değil.
Roy Ling

@royling - evet, düzeltme için teşekkürler! Yorumumu düzenleyemiyorum.
jbyrd

4

Doğrudan javascript ile sözde sınıf kuralları belirlemek yerine, kuralları farklı CSS dosyalarında farklı şekilde ayarlayabilir ve ardından bir stil sayfasını kapatmak ve diğerini açmak için Javascript kullanabilirsiniz. A List Apart'ta bir yöntem açıklanmıştır (daha fazla ayrıntı için qv.).

CSS dosyalarını şu şekilde ayarlayın:

<link rel="stylesheet" href="always_on.css">
<link rel="stylesheet" title="usual" href="preferred.css"> <!-- on by default -->
<link rel="alternate stylesheet" title="strange" href="alternate.css"> <!-- off by default -->

Ve sonra javascript kullanarak aralarında geçiş yapın:

function setActiveStyleSheet(title) {
   var i, a, main;
   for(i=0; (a = document.getElementsByTagName("link")<i>); i++) {
     if(a.getAttribute("rel").indexOf("style") != -1
        && a.getAttribute("title")) {
       a.disabled = true;
       if(a.getAttribute("title") == title) a.disabled = false;
     }
   }
}

Sınıfı dinamik olarak bir AJAX isteği tarafından alınan bir değere değiştirmeniz gerekirse ne olur? Şu anda bir CSS dosyası oluşturamazsınız ...
andreszs

2

Daha önce de belirtildiği gibi bu, tarayıcıların desteklediği bir şey değildir.

Stiller dinamik olarak gelmiyorsa (yani, onları bir veritabanından veya başka bir şeyden çekerek), sayfanın gövdesine bir sınıf ekleyerek bu sorunu çözebilmelisiniz.

Css şunun gibi görünür:

a:hover { background: red; }
.theme1 a:hover { background: blue; }

Ve bunu değiştirecek javascript şöyle bir şey olacaktır:

// Look up some good add/remove className code if you want to do this
// This is really simplified

document.body.className += " theme1";  

Meraktan element.classList.adddolayı, iyi desteklenmiyor mu? İnsanların yaptığını görüyorum element.className +=.
Joel Cornett

2
classList daha yeni bir özellik ve oldukça yakın zamana kadar iyi bir destek almış gibi görünmüyor (bkz. caniuse.com/classlist )
Nathaniel Reinhart


-1

Jquery'de hover sözde sınıflarını kolayca ayarlayabilirsiniz.

$("p").hover(function(){
$(this).css("background-color", "yellow");
}, function(){
$(this).css("background-color", "pink");
});

-1

işte iki işlevi içeren bir çözüm: addCSSclass belgeye yeni bir css sınıfı ekler ve toggleClass onu açar

Örnek, bir div öğesine özel bir kaydırma çubuğu eklemeyi gösterir.

// If newState is provided add/remove theClass accordingly, otherwise toggle theClass
function toggleClass(elem, theClass, newState) {
  var matchRegExp = new RegExp('(?:^|\\s)' + theClass + '(?!\\S)', 'g');
  var add = (arguments.length > 2 ? newState : (elem.className.match(matchRegExp) === null));

  elem.className = elem.className.replace(matchRegExp, ''); // clear all
  if (add) elem.className += ' ' + theClass;
}

function addCSSclass(rules) {
  var style = document.createElement("style");
  style.appendChild(document.createTextNode("")); // WebKit hack :(
  document.head.appendChild(style);
  var sheet = style.sheet;

  rules.forEach((rule, index) => {
    try {
      if ("insertRule" in sheet) {
        sheet.insertRule(rule.selector + "{" + rule.rule + "}", index);
      } else if ("addRule" in sheet) {
        sheet.addRule(rule.selector, rule.rule, index);
      }
    } catch (e) {
      // firefox can break here          
    }
    
  })
}

let div = document.getElementById('mydiv');
addCSSclass([{
    selector: '.narrowScrollbar::-webkit-scrollbar',
    rule: 'width: 5px'
  },
  {
    selector: '.narrowScrollbar::-webkit-scrollbar-thumb',
    rule: 'background-color:#808080;border-radius:100px'
  }
]);
toggleClass(div, 'narrowScrollbar', true);
<div id="mydiv" style="height:300px;width:300px;border:solid;overflow-y:scroll">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed a eros metus. Nunc dui felis, accumsan nec aliquam quis, fringilla quis tellus. Nulla cursus mauris nibh, at faucibus justo tincidunt eget. Sed sodales eget erat consectetur consectetur. Vivamus
  a diam volutpat, ullamcorper justo eu, dignissim ante. Aenean turpis tortor, fringilla quis efficitur eleifend, iaculis id quam. Quisque non turpis in lacus finibus auctor. Morbi ullamcorper felis ut nulla venenatis fringilla. Praesent imperdiet velit
  nec sodales sodales. Etiam eget dui sollicitudin, tempus tortor non, porta nibh. Quisque eu efficitur velit. Nulla facilisi. Sed varius a erat ac volutpat. Sed accumsan maximus feugiat. Mauris id malesuada dui. Lorem ipsum dolor sit amet, consectetur
  adipiscing elit. Sed a eros metus. Nunc dui felis, accumsan nec aliquam quis, fringilla quis tellus. Nulla cursus mauris nibh, at faucibus justo tincidunt eget. Sed sodales eget erat consectetur consectetur. Vivamus a diam volutpat, ullamcorper justo
  eu, dignissim ante. Aenean turpis tortor, fringilla quis efficitur eleifend, iaculis id quam. Quisque non turpis in lacus finibus auctor. Morbi ullamcorper felis ut nulla venenatis fringilla. Praesent imperdiet velit nec sodales sodales. Etiam eget
  dui sollicitudin, tempus tortor non, porta nibh. Quisque eu efficitur velit. Nulla facilisi. Sed varius a erat ac volutpat. Sed accumsan maximus feugiat. Mauris id malesuada dui.
</div>


-2

REACT kullanırsanız, radyum denen bir şey vardır . Burada çok kullanışlıdır:

  • Etkileşimli stiller belirtilmişse, sahne öğelerine işleyiciler ekleyin, örneğin, onMouseEnter for: hover, gerekirse mevcut işleyicileri sarma

  • İşleyicilerden herhangi biri, örneğin üzerine gelindiğinde tetiklenirse, Radium, bileşenler durum nesnesinde Radium'a özgü bir alanı güncellemesi için setState'i çağırır.

  • Yeniden oluştururken, geçerli olan tüm etkileşimli stilleri çözün, örneğin: üzerine gelindiğinde, öğenin anahtarına veya radyuma özgü durumda ref'e bakarak

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.