使用JavaScript / jQuery动态修改CSS类属性值

时间:2011-08-19 17:51:12

标签: javascript jquery css dynamic properties

我遇到了一个独特的情况,到目前为止我无法找到解决方案:动态地为CSS样式赋值。我知道如何使用jQuery为元素分配宽度,高度等,但我想要做的是实际更改样式表中定义的值,以便可以将动态创建的值分配给多个元素。

我正在构建的是一个占据整个视口的图像幻灯片,重新调整图像的宽度,高度和左侧属性,以便图像始终居中,有利于宽度超过高度,除非视口更高而不是宽(调整大小不会重新加载页面,只需激活一个函数来调整图像大小)。

我已经成功地让它在一个图像上工作,现在我正在尝试确定将这些属性值分配给幻灯片中所有图像的最佳方法,而不必为每个图像单独指定这三个项目。

我的问题:

可以动态修改类中属性的值吗?我确定答案就在那里,我可能只是在我的搜索中没有使用正确的术语。希望我能很好地描述这个问题。 TIA。

15 个答案:

答案 0 :(得分:28)

与此处的一些答案相反,使用Javascript编辑样式表本身不仅可行,而且性能更高。简单地执行$('.myclass').css('color: red')将最终循环遍历与选择器匹配的每个项目并单独设置样式属性。这是非常低效的,如果你有数百个元素,它将导致问题。

更改项目上的类是一个更好的主意,但您仍然遇到同样的问题,因为您正在更改N个项目的属性,这可能是一个很大的数字。更好的解决方案可能是在一个单个父项或少数父项上更改类,然后使用css中的“Cascade”命中目标项。这适用于大多数情况,但不是全部。

有时您需要将很多项目的CSS更改为动态的内容,或者通过点击少数父母来实现这一点是没有好办法的。更改样式表本身,或添加一个小的新样式来覆盖现有的css是一种非常有效的方式来更改项目的显示。您只是在一个位置与DOM进行交互,浏览器可以非常有效地处理这些更改。

jss是一个库,可以帮助您更轻松地从javascript直接编辑样式表。

答案 1 :(得分:21)

DemoIE demo

您可以使用以下功能:

function setStyle(cssText) {
    var sheet = document.createElement('style');
    sheet.type = 'text/css';
    /* Optional */ window.customSheet = sheet;
    (document.head || document.getElementsByTagName('head')[0]).appendChild(sheet);
    return (setStyle = function(cssText, node) {
        if(!node || node.parentNode !== sheet)
            return sheet.appendChild(document.createTextNode(cssText));
        node.nodeValue = cssText;
        return node;
    })(cssText);
};

功能

  • 该函数是用vanilla-js编写的,因此它具有比jQuery替代品更好的性能
  • 首次调用setStyle后会创建一个样式表,因此如果您不调用它,则不会创建任何样式表。
  • 同样的样式表会在setStyle
  • 的以下调用中重复使用
  • 该函数返回对与您添加的一堆CSS相关联的节点的引用。如果再次使用该节点作为第二个参数调用该函数,它将用新的CSS替换旧的CSS。

示例

var myCSS = setStyle('*{ color:red; }');
setStyle('*{ color:blue; }', myCSS); // Replaces the previous CSS with this one

浏览器支持

至少,它适用于IE9,FF3,Chrome 1,Safari 4,Opera 10.5。

还有一个IE version适用于现代浏览器和旧版本的IE! (适用于IE8和IE7,但可能会崩溃IE6)。

答案 2 :(得分:18)

好问题。这里的很多答案都有一个解决方案,直接与你的要求相矛盾

“我知道如何使用jQuery为元素分配宽度,高度等,但我想要做的是实际更改样式表中定义的值,以便可以将动态创建的值分配给多元素。

jQuery .css样式元素内联:它不会更改物理CSS规则!如果你想这样做,我建议使用一个vanilla JavaScript解决方案:

document.styleSheets[0].cssRules[0].cssText = "\
     #myID {
         myRule: myValue;
         myOtherRule: myOtherValue;
     }";

这样,您将设置样式表css规则,而不是附加内联样式。

希望这有帮助!

答案 3 :(得分:8)

就像@benvie所说的那样,更有效地更改样式表而不是使用jQuery.css(它将循环遍历集合中的所有元素)。每次调用函数时都不要在头部添加新样式也很重要,因为它会产生内存泄漏和数千个必须由浏览器单独应用的CSS规则。我会做这样的事情:

//Add the stylesheet once and store a cached jQuery object
var $style = $("<style type='text/css'>").appendTo('head'); 

function onResize() {
    var css = "\
        .someClass {\
            left:   "+leftVal+";\
            width:  "+widthVal+";\
            height: "+heightVal+";\
        }";

    $style.html(css);
}

此解决方案将通过每次调整大小仅修改DOM一次来更改样式。请注意,对于有效的js缩小和压缩,您可能不希望漂亮地打印css,但为了清晰起见,我这样做了。

答案 4 :(得分:5)

使用jquery在<head>

中添加样式覆盖
$('<style>.someClass {color: red;} input::-webkit-outer-spin-button: {display: none;}</style>')
.appendTo('head'); 

答案 5 :(得分:4)

我有一个改变特定CSS类值的解决方案。但只有将CSS保留在标签中才有效。如果您只是从外部文件保留到CSS的链接。

<style src='script.js'></style>

此解决方案无效。

如果你的css看起来像这样:

<style id='style'>
.foo {
height:50px;
}
</style>

您可以使用JS / jQuery更改标记的值。

我写了一个函数,也许它不是最好的函数,但它有效。如果你愿意,你可以改进它。

function replaceClassProp(cl,prop,val){

if(!cl || !prop || !val){console.error('Wrong function arguments');return false;}


// Select style tag value

var tag = '#style';

    var style = $(tag).text();
    var str = style;

// Find the class you want to change
    var n = str.indexOf('.'+cl);
    str = str.substr(n,str.length);
    n = str.indexOf('}');
    str = str.substr(0,n+1);

    var before = str;

// Find specific property

    n = str.indexOf(prop);
    str = str.substr(n,str.length);
    n = str.indexOf(';');
    str = str.substr(0,n+1);

// Replace the property with values you selected

    var after = before.replace(str,prop+':'+val+';');
    style=style.replace(before,after);

// Submit changes

    $(tag).text(style);

}

然后只需将标记变量更改为样式标记ID并执行:

replaceClassProp('foo','height','50px');

这与$('。foo')。css('height','50px')之间的区别;当你使用jQuery的css方法执行它时,所有具有.foo类的元素都将在DOM中具有可见的style ='height:50px'。如果你这样做,元素是不受影响的,你唯一能看到的就是class ='foo'

<强>优点

  • 清除DOM
  • 您可以修改所需的属性而无需替换整个样式

<强>缺点

  • 仅内部CSS
  • 您必须找到要修改的特定样式标记

希望无论如何都有帮助。

答案 6 :(得分:3)

您无法动态修改CSS类的成员。但是,您可以在页面上使用新的css类实现引入新的<style>标记,然后切换出类。例如:

Sample.css

.someClass { border: 1px solid black; font-size: 20px; }

您想要完全更改该类,因此您需要创建一个新的样式元素:

<style>
   .someClassReplacement { border: 1px solid white; font-size: 14px; }       
</style>

然后通过jQuery进行简单的替换:

$('.someClass').removeClass('someClass').addClass('someClassReplacement');

答案 7 :(得分:2)

为什么不使用.class选择器来修改该类中每个对象的属性?

即:

$('.myclass').css('color: red;');

答案 8 :(得分:2)

function changeStyle(findSelector, newRules) {
    // Change original css style declaration.   
    for ( s in document.styleSheets ) {
        var CssRulesStyle = document.styleSheets[s].cssRules;
        for ( x in CssRulesStyle ) {
            if ( CssRulesStyle[x].selectorText == findSelector) {
                for ( cssprop in newRules ) {
                    CssRulesStyle[x].style[cssprop] = newRules[cssprop];
                }

                return true;
            }
        }
    }

    return false;
}

changeStyle('#exact .myStyle .declaration', {'width':'200px', 'height':'400px', 'color':'#F00'});

答案 9 :(得分:1)

您应该重新考虑解决此问题的方法。使用精心设计的选择器并附加类可能是这种方法的更优雅的解决方案。据我所知,你无法修改外部CSS。

答案 10 :(得分:1)

YUI 2和3有一个模块样式表,可以让你这样做(使用javascript动态编辑样式表)。 http://yuilibrary.com/yui/docs/stylesheet/。所以我认为这是可能的。这与$(“。some”)。css({...})不同,但实际上是从样式表中更改/添加/删除样式定义,就像用户要求的那样。

答案 11 :(得分:1)

好的..有同样的问题并修复了,但解决方案可能不适合所有人。

如果您知道要删除的样式表和规则的索引,请尝试document.styleSheets[1].deleteRule(0);之类的内容。

从一开始,我就有了 main.css (索引0)文件。然后,我创建了一个新文件 js_edit.css (索引1),它只包含一个规则,其中包含我想在页面加载完成后删除的属性(在一堆其他JS函数之后) )。

现在,由于 js_edit.css main.css 之后加载,您可以随意插入/删除 js_edit.css 中的规则它们将覆盖 main.css 中的那些。

var x = document.styleSheets[1];
x.insertRule("p { font-size: 2rem; }", x.cssRules.length);

x.cssRules.length返回第二个(索引1)样式表中的规则数,从而在最后插入新规则。

我确定你可以使用一堆for循环来搜索你想要修改的规则/属性,然后在同一张表中重写整个规则,但我发现这种方式对我的需求更简单。

http://www.quirksmode.org/dom/w3c_css.html给了我很多帮助。

答案 12 :(得分:0)

这可能是讨论的后期,但我需要的东西就像这里所讨论的内容,但没有找到任何真正做到我想要的东西,并且很容易做到。我需要的是隐藏和显示众多元素,而无需单独访问每个元素,以某种方式更新它们,从而改变隐藏的显示样式。所以我想出了以下内容:

<style>
  /* The bulk of the css rules should go here or in an external css file */
  /* None of these rules will be changed, but may be overridden */
  .aclass { display: inline-block; width: 50px; height: 30px; }
</style>
<style id="style">
  /* Only the rules to be changed should go in this style */
  .bclass { display: inline-block; }
</style>
<script>
  //
  // This is a helper function that returns the named style as an object.
  // This could also be done in other ways.
  // 
  function setStyle() { return document.getElementById( 'style' ); }
</script>
<div id="d1" class="aclass" style="background-color: green;">
  Hi
</div>
<!-- The element to be shown and hidden --> 
<div id="d2" class="aclass bclass" style="background-color: yellow;">
  there
</div>
<div id="d3" class="aclass" style="background-color: lightblue;">
  sailor
</div>
<hr />
<!-- These buttons demonstrate hiding and showing the d3 dive element -->
<button onclick="setStyle().innerHTML = '.bclass { display: none; }';">
  Hide
</button>&nbsp;&nbsp;
<button onclick="setStyle().innerHTML = '.bclass { display: inline-block; }';">
  Show
</button>

通过在嵌入式和命名样式表中切换bclass规则,该样式表位于任何其他相关样式表之后,在这种情况下是一个带有aclass规则的样式表,我可以在一个地方更新显示css规则并让它覆盖aclass规则,它也有自己的显示规则。

这种技术的优点在于它非常简单,有效地完成了实际工作,它不需要任何库,例如JQuery或插件,以及更新所有库的真正工作更改适用的位置由浏览器的css核心功能执行,而不是在JavaScript中执行。此外,它适用于IE 9及更高版本,Chrome,Safari,Opera以及MicroSoft Edge可以模拟的所有其他浏览器,适用于台式机和平板电脑/手机设备。

答案 13 :(得分:0)

此解决方案修改Cycne以使用ES6语法并提前退出循环以获取外部样式表。此解决方案不会修改外部样式表

&#13;
&#13;
function changeStyle(findSelector, newDeclarations) {
    // Change original css style declaration.
    document.styleSheets.forEach((sheet) => {
      if (sheet.href) return;
      const cssRulesList = sheet.cssRules;
      cssRulesList.forEach((styleRule) => {
        if (styleRule.selectorText === findSelector) {
          Object.keys(newDeclarations).forEach((cssProp) => {
            styleRule.style[cssProp] = newDeclarations[cssProp];
          });
        }
      });
    });
  }

  const styleDeclarations = {
    'width': '200px',
    'height': '400px',
    'color': '#F00'
  };
  changeStyle('.paintBox', styleDeclarations);
&#13;
&#13;
&#13;

HTML头部分中还必须至少有一个样式标记,例如

<style> .paintBox {background-color: white;}</style>

答案 14 :(得分:0)

动态修改 CSS 类中的 CSS 属性值的方法是在 CSS 类属性值中使用 CSS 变量,然后使用 JavaScript 和 DOM 来更改 CSS 变量。最终结果是,当设置新 CSS 变量值的代码运行时,设备屏幕上的样式将立即更改。因此,代码更改了 CSS 变量,并且在 CSS 类设置中使用了 CSS 变量。请注意,CSS 类名和 JavaScript 类是两个不同的东西。

  • 使用 CSS 变量
  • 将 CSS 变量放在静态 CSS 类属性值通常所在的位置
  • 使用代码设置新的 CSS 变量值
  • 对 CSS 变量的更改会更改 CSS 类属性值,从而导致设备屏幕上的样式发生更改

CSS - 样式

<style>
  :root { /* Set CSS variable values - These values can be changed with JavaScript 
    and DOM */
  --myCSS_ValueOne: initialValue;

  }

  .classNameHere {
    property_Name_Here: var(--myCSS_ValueOne);/* This CSS property gets its value from
    the CSS variable */

  }

</style>

JavaScript 和 DOM

<script>
  var r = document.querySelector(':root');//Get global root element

  function setA_NewCSS_VariableValue() {
    r.style.setProperty('--myCSS_ValueOne', 'the_New_Value');// Set a new CSS variable
      //value which immediately changes the CSS class setting because the CSS
      //property setting uses a CSS Variable -
  }
</script>

还可以使用 matchMedia() 方法运行一个函数来响应媒体查询(设备视口中的更改 - 例如设备屏幕的宽度)。

var x = window.matchMedia("(max-width: 300px)")
x.addListener(setA_NewCSS_VariableValue) // create a listener function that runs
//when the viewport is less than, or equal to, 300 pixels wide.