JavaScript로 CSS 클래스를 동적으로 만들고 적용하는 방법은 무엇입니까?


답변:


394

JavaScript로 CSS 클래스를 작성하려는 이유는 확실하지 않지만 다음 옵션이 있습니다.

var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '.cssClass { color: #F00; }';
document.getElementsByTagName('head')[0].appendChild(style);

document.getElementById('someElementId').className = 'cssClass';

10
내 유스 케이스는 QA 목적으로 특정 요소를 강조 표시하는 북마크입니다.
TomG

25
IE 8 이하에서는 알 수없는 런타임 오류가 발생합니다.
Andy Hume

1
내 유스 케이스는 임의의 Google 웹 글꼴을로드 한 다음 randomFont 클래스에 font-family를 제공합니다 :-)
w00t

26
또 다른 사용 사례는 CSS 파일에 의존하지 않고 단일 JS lib를 원하는 경우입니다. 필자의 경우 기본적으로 가벼운 으르렁 스타일 경고 팝업을 원합니다.
xeolabs

1
w00t와 비슷한 것을하고 있습니다. 캔버스에 글을 쓸 대화 형 html5 앱을 만들고 있는데 사용자가 사용할 다양한 글꼴을 선택할 수있게하고 싶습니다. 오히려 모든 글꼴과 loooong CSS를하는 것보다, 난 그냥 글꼴 데이터를 업로드합니다 프로그램이로드 될 때마다하는 웹 서비스에 약간의 호출이 글꼴을 제공하고 추가 백엔드를 만드는 계획입니다
CJLopez

117

모든 브라우저에서 작동 하는 더 나은 솔루션을 찾았습니다 .
document.styleSheet를 사용하여 규칙을 추가하거나 바꿉니다. 허용되는 대답은 짧고 편리하지만 IE8 이하에서도 작동합니다.

function createCSSSelector (selector, style) {
  if (!document.styleSheets) return;
  if (document.getElementsByTagName('head').length == 0) return;

  var styleSheet,mediaType;

  if (document.styleSheets.length > 0) {
    for (var i = 0, l = document.styleSheets.length; i < l; i++) {
      if (document.styleSheets[i].disabled) 
        continue;
      var media = document.styleSheets[i].media;
      mediaType = typeof media;

      if (mediaType === 'string') {
        if (media === '' || (media.indexOf('screen') !== -1)) {
          styleSheet = document.styleSheets[i];
        }
      }
      else if (mediaType=='object') {
        if (media.mediaText === '' || (media.mediaText.indexOf('screen') !== -1)) {
          styleSheet = document.styleSheets[i];
        }
      }

      if (typeof styleSheet !== 'undefined') 
        break;
    }
  }

  if (typeof styleSheet === 'undefined') {
    var styleSheetElement = document.createElement('style');
    styleSheetElement.type = 'text/css';
    document.getElementsByTagName('head')[0].appendChild(styleSheetElement);

    for (i = 0; i < document.styleSheets.length; i++) {
      if (document.styleSheets[i].disabled) {
        continue;
      }
      styleSheet = document.styleSheets[i];
    }

    mediaType = typeof styleSheet.media;
  }

  if (mediaType === 'string') {
    for (var i = 0, l = styleSheet.rules.length; i < l; i++) {
      if(styleSheet.rules[i].selectorText && styleSheet.rules[i].selectorText.toLowerCase()==selector.toLowerCase()) {
        styleSheet.rules[i].style.cssText = style;
        return;
      }
    }
    styleSheet.addRule(selector,style);
  }
  else if (mediaType === 'object') {
    var styleSheetLength = (styleSheet.cssRules) ? styleSheet.cssRules.length : 0;
    for (var i = 0; i < styleSheetLength; i++) {
      if (styleSheet.cssRules[i].selectorText && styleSheet.cssRules[i].selectorText.toLowerCase() == selector.toLowerCase()) {
        styleSheet.cssRules[i].style.cssText = style;
        return;
      }
    }
    styleSheet.insertRule(selector + '{' + style + '}', styleSheetLength);
  }
}

기능은 다음과 같이 사용됩니다.

createCSSSelector('.mycssclass', 'display:none');

2
IE8 작업을 확인했습니다. Chrome에서 작동하지 않기 때문에 mediaType for-loop ifs에 "styleSheet.cssRules [i] .selectorText &&"및 "styleSheet.rules [i] .selectorText &&"를 추가해야했습니다. 정의되지 않았습니다.
w00t 2019

@ w00t 코드를 붙여 넣거나 편집하여 작동시킬 수 있습니까?
Hengjie

방금 Chrome (버전 34.0.1847.132)에서 함수를 붙여넣고 실행했지만 작동하지 않습니다. "TypeError : 'length'속성을 읽을 수 없습니다" 개발자 콘솔에서 생성해도 작동하지 않을 수 있습니까?
dnuske

크롬 (또는 크롬)의 일부 버전은 인덱스 0에 InsertRule을 허용하지 않습니다. 수정 사항은 다음과 같습니다. styleSheet.insertRule (selector + "{"+ style + "}", styleSheet.cssRules.length);
dnuske

1
@ dnuske 나는 같은 문제가 발생했습니다. styleSheet.cssRules는 null로 평가됩니다. 내가 사용한 수정은 새 변수를 만들고 var styleSheetLength = styleSheet.cssRules ? styleSheet.cssRules.length : 0함수 구현 대신 사용을 대체하는 것입니다.
Raj Nathani

27

짧은 대답, 이것은 "모든 브라우저에서"(특히 IE8 / 7)과 호환됩니다.

function createClass(name,rules){
    var style = document.createElement('style');
    style.type = 'text/css';
    document.getElementsByTagName('head')[0].appendChild(style);
    if(!(style.sheet||{}).insertRule) 
        (style.styleSheet || style.sheet).addRule(name, rules);
    else
        style.sheet.insertRule(name+"{"+rules+"}",0);
}
createClass('.whatever',"background-color: green;");

그리고이 마지막 비트는 클래스를 요소에 적용합니다.

function applyClass(name,element,doRemove){
    if(typeof element.valueOf() == "string"){
        element = document.getElementById(element);
    }
    if(!element) return;
    if(doRemove){
        element.className = element.className.replace(new RegExp("\\b" + name + "\\b","g"));
    }else{      
        element.className = element.className + " " + name;
    }
}

여기 약간의 테스트 페이지가 있습니다 : https://gist.github.com/shadybones/9816763

핵심 요소는 스타일 요소에 규칙을 추가 / 제거하는 데 사용할 수있는 "styleSheet"/ "sheet"속성이 있다는 사실입니다.


클래스 생성마다 새로운 "스타일"요소를 생성합니까? 따라서 데이터를 기반으로 for 루프에서 1000 개 이상의 클래스를 만들려면 document.head.appendChild를 1000 번 적용해야합니까?
bluejayke

나를 위해 크롬 style.sheet 및 style.styleSheet가 존재하지 않습니다
bluejayke


7

YUI는 지금까지 내가 본 최고의 스타일 시트 유틸리티를 가지고 있습니다. 나는 당신이 그것을 확인하는 것이 좋습니다, 그러나 여기에 맛이 있습니다 :

// style element or locally sourced link element
var sheet = YAHOO.util.StyleSheet(YAHOO.util.Selector.query('style',null,true));

sheet = YAHOO.util.StyleSheet(YAHOO.util.Dom.get('local'));


// OR the id of a style element or locally sourced link element
sheet = YAHOO.util.StyleSheet('local');


// OR string of css text
var css = ".moduleX .alert { background: #fcc; font-weight: bold; } " +
          ".moduleX .warn  { background: #eec; } " +
          ".hide_messages .moduleX .alert, " +
          ".hide_messages .moduleX .warn { display: none; }";

sheet = new YAHOO.util.StyleSheet(css);

여기에 제안 된 것과 같이 스타일을 변경하는 훨씬 더 간단한 방법이 있습니다. 그들이 당신의 문제에 대해 이해가된다면 가장 좋을 수도 있지만 CSS를 수정하는 것이 더 나은 해결책 인 이유는 분명히 있습니다. 가장 확실한 경우는 많은 수의 요소를 수정해야 할 때입니다. 다른 주요 사례는 계단식을 포함하기 위해 스타일을 변경해야하는 경우입니다. dom을 사용하여 요소를 수정하면 항상 우선 순위가 높습니다. 슬레지 해머의 접근 방식이며 html 요소에서 스타일 속성을 직접 사용하는 것과 같습니다. 항상 원하는 효과는 아닙니다.


5

IE 9부터 텍스트 파일을로드하고 style.innerHTML 속성을 설정할 수 있습니다. 따라서 본질적으로 이제 ajax를 통해 CSS 파일을로드하고 콜백을 얻은 다음 스타일 태그 안에 텍스트를 설정하면됩니다.

이것은 다른 브라우저에서 작동하지만 얼마나 멀리 있는지 확실하지 않습니다. 그러나 IE8을 지원할 필요가 없으면 작동합니다.

// RESULT: doesn't work in IE8 and below. Works in IE9 and other browsers.
$(document).ready(function() {
    // we want to load the css as a text file and append it with a style.
    $.ajax({
        url:'myCss.css',
        success: function(result) {
            var s = document.createElement('style');
            s.setAttribute('type', 'text/css');
            s.innerHTML = result;
            document.getElementsByTagName("head")[0].appendChild(s);
        },
        fail: function() {
            alert('fail');
        }
    })
});

그런 다음 myCss.css와 같은 외부 파일을 가져올 수 있습니다

.myClass { background:#F00; }

5

Vishwanath의 솔루션은 주석으로 약간 다시 작성되었습니다.

function setStyle(cssRules, aSelector, aStyle){
    for(var i = 0; i < cssRules.length; i++) {
        if(cssRules[i].selectorText && cssRules[i].selectorText.toLowerCase() == aSelector.toLowerCase()) {
            cssRules[i].style.cssText = aStyle;
            return true;
        }
    }
    return false;
}

function createCSSSelector(selector, style) {
    var doc = document;
    var allSS = doc.styleSheets;
    if(!allSS) return;

    var headElts = doc.getElementsByTagName("head");
    if(!headElts.length) return;

    var styleSheet, media, iSS = allSS.length; // scope is global in a function
    /* 1. search for media == "screen" */
    while(iSS){ --iSS;
        if(allSS[iSS].disabled) continue; /* dont take into account the disabled stylesheets */
        media = allSS[iSS].media;
        if(typeof media == "object")
            media = media.mediaText;
        if(media == "" || media=='all' || media.indexOf("screen") != -1){
            styleSheet = allSS[iSS];
            iSS = -1;   // indication that media=="screen" was found (if not, then iSS==0)
            break;
        }
    }

    /* 2. if not found, create one */
    if(iSS != -1) {
        var styleSheetElement = doc.createElement("style");
        styleSheetElement.type = "text/css";
        headElts[0].appendChild(styleSheetElement);
        styleSheet = doc.styleSheets[allSS.length]; /* take the new stylesheet to add the selector and the style */
    }

    /* 3. add the selector and style */
    switch (typeof styleSheet.media) {
    case "string":
        if(!setStyle(styleSheet.rules, selector, style));
            styleSheet.addRule(selector, style);
        break;
    case "object":
        if(!setStyle(styleSheet.cssRules, selector, style));
            styleSheet.insertRule(selector + "{" + style + "}", styleSheet.cssRules.length);
        break;
    }

4

당신의 작업에서 당신을 도울 수있는 흥미로운 프로젝트는 JSS 입니다.

JSS는 CSS보다 더 나은 추상화입니다. 선언적이고 유지 관리 가능한 방식으로 스타일을 설명하는 언어로 JavaScript를 사용합니다. 브라우저 및 서버 측에서 런타임에 작동하는 고성능 JS to CSS 컴파일러입니다.

JSS 라이브러리를 사용하면 .attach()함수를 사용하여 DOM / 헤드 섹션에 삽입 할 수 있습니다 .

평가를위한 Repl 온라인 버전 .

더욱이 JSS에 대한 정보 .

예를 들면 :

// Use plugins.
jss.use(camelCase())

// Create your style.
const style = {
  myButton: {
    color: 'green'
  }
}

// Compile styles, apply plugins.
const sheet = jss.createStyleSheet(style)

// If you want to render on the client, insert it into DOM.
sheet.attach()

3

구글 클로저 사용하기 :

ccsom 모듈을 사용할 수 있습니다.

goog.require('goog.cssom');
var css_node = goog.cssom.addCssText('.cssClass { color: #F00; }');

자바 스크립트 코드는 CSS 노드를 문서 헤드에 넣을 때 크로스 브라우저가 되려고합니다.


3

https://jsfiddle.net/xk6Ut/256/

JavaScript에서 CSS 클래스를 동적으로 만들고 업데이트하는 한 가지 옵션 :

  • 스타일 요소를 사용하여 CSS 섹션 만들기
  • CSS
    클래스를 업데이트 할 수 있도록 스타일 요소에 ID 사용

.....

function writeStyles(styleName, cssText) {
    var styleElement = document.getElementById(styleName);
    if (styleElement) 
             document.getElementsByTagName('head')[0].removeChild(
        styleElement);
    styleElement = document.createElement('style');
    styleElement.type = 'text/css';
    styleElement.id = styleName;
    styleElement.innerHTML = cssText;
    document.getElementsByTagName('head')[0].appendChild(styleElement);
}

...

    var cssText = '.testDIV{ height:' + height + 'px !important; }';
    writeStyles('styles_js', cssText)

1

답을 살펴 보았고 가장 명백하고 직접적인 내용이 누락되었습니다. document.write()필요한 CSS 덩어리를 작성하는 데 사용하십시오.

다음은 예제입니다 (codepen에서 확인하십시오 : http://codepen.io/ssh33/pen/zGjWga ).

<style>
   @import url(http://fonts.googleapis.com/css?family=Open+Sans:800);
   .d, body{ font: 3vw 'Open Sans'; padding-top: 1em; }
   .d {
       text-align: center; background: #aaf;
       margin: auto; color: #fff; overflow: hidden; 
       width: 12em; height: 5em;
   }
</style>

<script>
   function w(s){document.write(s)}
   w("<style>.long-shadow { text-shadow: ");
   for(var i=0; i<449; i++) {
      if(i!= 0) w(","); w(i+"px "+i+"px #444");
   }
   w(";}</style>");
</script> 

<div class="d">
    <div class="long-shadow">Long Shadow<br> Short Code</div>
</div>

페이지로드 후 CSS 규칙을 작성해야하거나 XHTML을 사용하지 않는 한 좋습니다.
Tim Down

1
function createCSSClass(selector, style, hoverstyle) 
{
    if (!document.styleSheets) 
    {
        return;
    }

    if (document.getElementsByTagName("head").length == 0) 
    {

        return;
    }
    var stylesheet;
    var mediaType;
    if (document.styleSheets.length > 0) 
    {
        for (i = 0; i < document.styleSheets.length; i++) 
        {
            if (document.styleSheets[i].disabled) 
            {
                continue;
            }
            var media = document.styleSheets[i].media;
            mediaType = typeof media;

            if (mediaType == "string") 
            {
                if (media == "" || (media.indexOf("screen") != -1)) 
                {
                    styleSheet = document.styleSheets[i];
                }
            } 
            else if (mediaType == "object") 
            {
                if (media.mediaText == "" || (media.mediaText.indexOf("screen") != -1)) 
                {
                    styleSheet = document.styleSheets[i];
                }
            }

            if (typeof styleSheet != "undefined") 
            {
                break;
            }
        }
    }

    if (typeof styleSheet == "undefined") {
        var styleSheetElement = document.createElement("style");
        styleSheetElement.type = "text/css";
        document.getElementsByTagName("head")[0].appendChild(styleSheetElement);
        for (i = 0; i < document.styleSheets.length; i++) {
            if (document.styleSheets[i].disabled) {
                continue;
            }
            styleSheet = document.styleSheets[i];
        }

        var media = styleSheet.media;
        mediaType = typeof media;
    }

    if (mediaType == "string") {
        for (i = 0; i < styleSheet.rules.length; i++) 
        {
            if (styleSheet.rules[i].selectorText.toLowerCase() == selector.toLowerCase()) 
            {
                styleSheet.rules[i].style.cssText = style;
                return;
            }
        }

        styleSheet.addRule(selector, style);
    }
    else if (mediaType == "object") 
    {
        for (i = 0; i < styleSheet.cssRules.length; i++) 
        {
            if (styleSheet.cssRules[i].selectorText.toLowerCase() == selector.toLowerCase()) 
            {
                styleSheet.cssRules[i].style.cssText = style;
                return;
            }
        }

        if (hoverstyle != null) 
        {
            styleSheet.insertRule(selector + "{" + style + "}", 0);
            styleSheet.insertRule(selector + ":hover{" + hoverstyle + "}", 1);
        }
        else 
        {
            styleSheet.insertRule(selector + "{" + style + "}", 0);
        }
    }
}





createCSSClass(".modalPopup  .header",
                                 " background-color: " + lightest + ";" +
                                  "height: 10%;" +
                                  "color: White;" +
                                  "line-height: 30px;" +
                                  "text-align: center;" +
                                  " width: 100%;" +
                                  "font-weight: bold; ", null);

문서에 프로그래머없는 현재의 스타일 시트는 경우 어떻게
bluejayke

1

모듈 식 솔루션은 다음과 같습니다.

var final_style = document.createElement('style');
final_style.type = 'text/css';

function addNewStyle(selector, style){
  final_style.innerHTML += selector + '{ ' + style + ' } \n';
};

function submitNewStyle(){
  document.getElementsByTagName('head')[0].appendChild(final_style);

  final_style = document.createElement('style');
  final_style.type = 'text/css';
};

function submitNewStyleWithMedia(mediaSelector){
  final_style.innerHTML = '@media(' + mediaSelector + '){\n' + final_style.innerHTML + '\n};';
    submitNewStyle();
};

당신은 기본적으로 어디서나 코드에서 수행
addNewStyle('body', 'color: ' + color1);, 어디 color1변수를 정의한다.

당신은 "포스트"당신은 단순히 수행 현재 CSS 파일을하려는 경우 submitNewStyle(),
다음은 여전히 나중에 CSS를 추가 할 수 있습니다.

"미디어 쿼리"를 사용하여 추가하려는 경우 옵션이 있습니다.
"NewStyles 추가"후에는 간단하게 사용하십시오 submitNewStyleWithMedia('min-width: 1280px');.


현재 시간에 따라 공개 웹 사이트의 CSS를 변경했기 때문에 유스 케이스에 매우 유용했습니다. 나는 "active"스크립트를 사용하기 전에 하나의 CSS 파일을 제출하고, 나머지는 이후에 (사이트를 통해 요소에 액세스하기 전에 사이트를 좀처럼 보이게 만듭니다 querySelector).


나는 오늘 이것을 시도 할 것입니다. 내 유스 케이스에서 이것이 어떻게 작동하는지 알려 드리겠습니다. 손가락이 건! 다 !!!
lopezdp

0

검색 자의 이익을 위해; jQuery를 사용하는 경우 다음을 수행 할 수 있습니다.

var currentOverride = $('#customoverridestyles');

if (currentOverride) {
 currentOverride.remove();
}

$('body').append("<style id=\"customoverridestyles\">body{background-color:pink;}</style>");

분명히 내부 CSS를 원하는대로 변경할 수 있습니다.

일부 사람들은 순수한 JavaScript를 선호하지만, 작동하고 스타일을 동적으로 쓰거나 덮어 쓰는 데 매우 강력합니다.


0

나는 여기에 대한 답변 중 일부를 살펴 보았고 새로운 스타일 시트가 없으면 자동으로 새 스타일 시트를 추가하는 것을 찾을 수 없었으며 이미 필요한 스타일을 포함하는 기존 스타일을 수정하지 않으면 새로운 기능을 만들었습니다 ( 테스트하지는 않았지만 addRule을 사용하는 모든 브라우저에서 작동해야하며 기본 네이티브 JavaScript 외에도 작동하는지 알려주세요).

function myCSS(data) {
    var head = document.head || document.getElementsByTagName("head")[0];
    if(head) {
        if(data && data.constructor == Object) {
            for(var k in data) {
                var selector = k;
                var rules = data[k];

                var allSheets = document.styleSheets;
                var cur = null;

                var indexOfPossibleRule = null,
                    indexOfSheet = null;
                for(var i = 0; i < allSheets.length; i++) {
                    indexOfPossibleRule = findIndexOfObjPropInArray("selectorText",selector,allSheets[i].cssRules);
                    if(indexOfPossibleRule != null) {
                        indexOfSheet = i;
                        break;
                    }
                }

                var ruleToEdit = null;
                if(indexOfSheet != null) {

                    ruleToEdit = allSheets[indexOfSheet].cssRules[indexOfPossibleRule];

                } else {
                    cur = document.createElement("style");
                    cur.type =  "text/css";
                    head.appendChild(cur);
                    cur.sheet.addRule(selector,"");
                    ruleToEdit = cur.sheet.cssRules[0];
                    console.log("NOPE, but here's a new one:", cur);
                }
                applyCustomCSSruleListToExistingCSSruleList(rules, ruleToEdit, (err) => {
                    if(err) {
                        console.log(err);
                    } else {
                        console.log("successfully added ", rules, " to ", ruleToEdit);
                    }
                });
            }
        } else {
            console.log("provide one paramter as an object containing the cssStyles, like: {\"#myID\":{position:\"absolute\"}, \".myClass\":{background:\"red\"}}, etc...");
        }
    } else {
        console.log("run this after the page loads");
    }

};  

그런 다음 위의 함수 내부 또는 다른 곳에이 두 도우미 함수를 추가하십시오.

function applyCustomCSSruleListToExistingCSSruleList(customRuleList, existingRuleList, cb) {
    var err = null;
    console.log("trying to apply ", customRuleList, " to ", existingRuleList);
    if(customRuleList && customRuleList.constructor == Object && existingRuleList && existingRuleList.constructor == CSSStyleRule) {
        for(var k in customRuleList) {
            existingRuleList["style"][k] = customRuleList[k];
        }

    } else {
        err = ("provide first argument as an object containing the selectors for the keys, and the second argument is the CSSRuleList to modify");
    }
    if(cb) {
        cb(err);
    }
}

function findIndexOfObjPropInArray(objPropKey, objPropValue, arr) {
    var index = null;
    for(var i = 0; i < arr.length; i++) {
        if(arr[i][objPropKey] == objPropValue) {
            index = i;
            break;
        }
    }
    return index;
}

CSS 스타일 / 규칙 목록 클래스에는 길이 속성 만 있고 .filter 메서드는 없기 때문에 둘 다 .filter 대신 for 루프를 사용합니다.

그런 다음 호출하십시오.

myCSS({
    "#coby": {
        position:"absolute",
        color:"blue"
    },
    ".myError": {
        padding:"4px",
        background:"salmon"
    }
})

브라우저에서 작동하거나 오류가 발생하면 알려주십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.