如何使用.css()来应用!important?

849

我在应用一个 !important 样式时遇到了问题。我已经尝试过:

$("#elem").css("width", "100px !important");
这段代码并未应用任何宽度样式。有没有一种像jQuery那样的方法可以应用这样的样式,而无需覆盖cssText(这意味着我需要先解析它等)?
编辑:我应该补充说明,我有一个带有!important样式的样式表,我正在尝试使用内联!important样式覆盖它,因此使用.width()之类的方法不起作用,因为它被我的外部!important样式覆盖。
另外,将覆盖先前值的值是计算出来的,因此我不能简单地创建另一个外部样式。

在使用JQuery 1.8.2时,Chromium 20.0.x对我不起作用。 - Alba Mendez
8
jQuery bug #11173 是关于修复 jQuery 核心中的 .css!important 的问题。该错误被关闭为“不予修复”。然而,那个 bug 的测试用例并不像这个问题中的测试用例那样具有限制性——测试用例没有内联的 !important 样式需要被覆盖。因此,在那个 bug 中提出的解决方法在这种情况下无法使用。 - Rory O'Kane
我已经打开了jQuery bug #2837来解决这个问题。希望那个问题不会因为没有好的理由而被关闭。 - Ian Kemp
... 然后 jQuery 决定不修复这个 bug,因为“只需使用插件”。开源万岁。 - Ian Kemp
2
可能是用CSS或jQuery覆盖!important的重复问题 - 虽然这个问题比较旧,但另一个问题的答案更清晰、更有价值。 - Jason C
显示剩余4条评论
31个回答

728
问题是由于jQuery不理解!important属性导致的,因此无法应用规则。
您可以通过引用addClass()来解决此问题并应用规则:
.importantRule { width: 100px !important; }

$('#elem').addClass('importantRule');

或者通过使用 attr()

$('#elem').attr('style', 'width: 100px !important');

然而,后一种方法会取消任何先前设置的内联样式规则。因此请谨慎使用。

当然,有一个很好的论点认为@Nick Craver的方法更容易/更明智。

上述attr()方法稍作修改,以保留原始的style字符串/属性,并根据falko在评论中提出的建议进行修改:

$('#elem').attr('style', function(i,s) { return (s || '') + 'width: 100px !important;' });

2
我倾向于你后面的方法,但令人遗憾的是,我可能最终不得不解析先前的cssText,因为我不能简单地丢弃它。 - mkoryak
1
啊,抱歉我没明白,有时候英式幽默超出了我的理解范围... :) - Sinan
1
嵌套引号('"width: 100px !important"')是什么情况?这对我没有用,但当我删除内部引号时它就起作用了。谢谢! - Peter Jaric
19
当样式为空时进行微调: $('#elem').attr('style', function(i,s) { return (s||'') + 'width: 100px !important;' }); - falko
4
你应该加入 @falko 的修正,因为在 Firefox 中,当当前样式为空时,你最后的代码片段会将样式设置为 'undefinedwidth: 100px !important;' - acdcjunior
显示剩余9条评论

344

我认为我找到了一个解决方案。我将其制作成了一个新函数:

jQuery.style(name, value, priority);

您可以使用它来通过.style('name')获取值,就像.css('name')一样,使用.style()获取CSSStyleDeclaration,并且还可以设置值,还可以指定优先级为'important'。请参见此文档

示例

var div = $('someDiv');
console.log(div.style('color'));
div.style('color', 'red');
console.log(div.style('color'));
div.style('color', 'blue', 'important');
console.log(div.style('color'));
console.log(div.style().getPropertyPriority('color'));

输出示例:

null
red
blue
important

该函数


(function($) {    
  if ($.fn.style) {
    return;
  }

  // Escape regex chars with \
  var escape = function(text) {
    return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
  };

  // For those who need them (< IE 9), add support for CSS functions
  var isStyleFuncSupported = !!CSSStyleDeclaration.prototype.getPropertyValue;
  if (!isStyleFuncSupported) {
    CSSStyleDeclaration.prototype.getPropertyValue = function(a) {
      return this.getAttribute(a);
    };
    CSSStyleDeclaration.prototype.setProperty = function(styleName, value, priority) {
      this.setAttribute(styleName, value);
      var priority = typeof priority != 'undefined' ? priority : '';
      if (priority != '') {
        // Add priority manually
        var rule = new RegExp(escape(styleName) + '\\s*:\\s*' + escape(value) +
            '(\\s*;)?', 'gmi');
        this.cssText =
            this.cssText.replace(rule, styleName + ': ' + value + ' !' + priority + ';');
      }
    };
    CSSStyleDeclaration.prototype.removeProperty = function(a) {
      return this.removeAttribute(a);
    };
    CSSStyleDeclaration.prototype.getPropertyPriority = function(styleName) {
      var rule = new RegExp(escape(styleName) + '\\s*:\\s*[^\\s]*\\s*!important(\\s*;)?',
          'gmi');
      return rule.test(this.cssText) ? 'important' : '';
    }
  }

  // The style function
  $.fn.style = function(styleName, value, priority) {
    // DOM node
    var node = this.get(0);
    // Ensure we have a DOM node
    if (typeof node == 'undefined') {
      return this;
    }
    // CSSStyleDeclaration
    var style = this.get(0).style;
    // Getter/Setter
    if (typeof styleName != 'undefined') {
      if (typeof value != 'undefined') {
        // Set style property
        priority = typeof priority != 'undefined' ? priority : '';
        style.setProperty(styleName, value, priority);
        return this;
      } else {
        // Get style property
        return style.getPropertyValue(styleName);
      }
    } else {
      // Get CSSStyleDeclaration
      return style;
    }
  };
})(jQuery);

请参考这里的示例,了解如何读取和设置CSS值。我的问题是在CSS中已经为宽度设置了!important以避免与其他主题CSS发生冲突,但是在jQuery中对宽度进行的任何更改都不会受到影响,因为它们将添加到样式属性中。

兼容性

对于使用setProperty函数设置优先级的情况,这篇文章表示IE 9+和其他所有浏览器均支持。我已经尝试过IE 8,但失败了,这就是我在我的函数中构建它的原因(请参见上文)。它将适用于在< IE 9中使用setProperty的所有其他浏览器,但需要我的自定义代码才能在< IE 9中工作。


2
还有一个 jQuery.important 插件,它在几年前发布。我正在生产中使用它,只有一个小问题(请参见他们的 Issues 标签)。 - colllin
此外,如果text不是文本,那么text.replace(...)就会出现问题。例如,我在text中得到了0(一个整数),通过编辑Regex.escape函数以返回(text + '') .replace(...)解决了这个问题。 - CWSpear
21
$( '.someclass' ).each(function () { this.style.setProperty( 'border', 'none', 'important' ); });这段代码的作用是:针对类名为"someclass"的所有元素,移除其边框样式并强制覆盖其他可能存在的样式。以下链接提供了有关如何使用CSS或jQuery重写!important的更简单、更清晰和更高效方法的讨论。https://dev59.com/nmct5IYBdhLWcg3wmOng - user352353
3
处理这个问题的唯一好方法是使用类而不是直接样式注入。 - Richard
3
@Richard,应对这种情况唯一好的方法就是在样式中不要使用!important,至少对于那些你打算用jQuery更改的东西。只要它们是你自己的样式。如果你的代码运行在一个学生编写的页面中,该学生因为不了解特殊性规则,在每个第二个样式中都添加了!important,那么迟早你会撞上其中之一!importants - Septagram
显示剩余9条评论

161

您可以使用.width()直接设置宽度,例如:

$("#elem").width(100);

更新以考虑评论: 你也有这个选项,但它将替换元素上的所有 CSS,因此不确定它是否更可行:

$('#elem').css('cssText', 'width: 100px !important');

好的,我只是以“with”作为示例,我关心的是设置!important。 - mkoryak
1
我也编辑了问题以更好地反映我的情况。基本上,我有一个外部的!important宽度设置为一些不好的东西,我必须内联覆盖它。由于这个原因,width()无法工作。 - mkoryak
@mkoryak - 更新了另一种非类选项,不确定是否适合你的情况。 - Nick Craver
1
但它将覆盖直接应用于元素的任何其他样式。https://dev59.com/73E85IYBdhLWcg3wr1qx#11723492 是最容易实现的。 - Anthony Graglia
12
防止通过$('#elem').css('cssText', $('#elem').css('cssText')+'width: 100px !important');覆盖之前的值,将其与先前的值连接起来。 - Abel Callejo

94
const elem = $("#elem");
elem[0].style.removeAttribute('width');
elem[0].style.setProperty('width', '100px', 'important');
注意: 使用Chrome可能会返回如下错误:
elem[0].style.removeAttribute不是一个函数
将该行更改为使用.removeProperty函数,例如:elem[0].style.removeProperty('width'); 可以解决此问题。

11
这是最好的答案之一。简单易行,不需要太多解释。除了 jQuery 选择器之外,它只是普通的 JavaScript。jQuery 不支持 "important",因此使用普通的 JS 是正确的方法。 - OMA
2
如果您想用Vanilla JS,只需编写 var = document.getElementById('elem'); 并在elem上执行样式方法(而不是elem [0])。干杯。 - humbolight
5
在原生JS中,removeAttribute无法正常工作。请按照以下方式操作。var style = document.getElementById('elem'); style.removeProperty('width'); style.setProperty('width', '100px', 'important'); - mcoenca
2
同样遇到了.removeAttribute的问题。它似乎是一个仅限IE的方法。@mcoenca的评论是正确的; .removeProperty可以正常工作。根据MSDN,它适用于IE9+。 - FelipeAls
2
@Dejan,非常抱歉回复晚了,但这应该可以解决问题:elem.next().get(0).style... - user5147563
显示剩余2条评论

58

David Thomas的答案描述了一种使用$('#elem').attr('style', …)的方法,但警告说使用它会删除先前在style属性中设置的样式。下面是一种使用attr()而不会出现这个问题的方法:

var $elem = $('#elem');
$elem.attr('style', $elem.attr('style') + '; ' + 'width: 100px !important');

作为一个函数:

function addStyleAttribute($element, styleAttribute) {
    $element.attr('style', $element.attr('style') + '; ' + styleAttribute);
}
addStyleAttribute($('#elem'), 'width: 100px !important');

这里有一个JS Bin演示


2
addStyleAttribute()也可以修改为接受与jQuery的.css()相同的参数。例如,它可以支持将CSS属性映射到其值的映射。如果这样做,您基本上会重新实现.css(),但修复了!important错误,但没有任何优化。 - Rory O'Kane
1
这对我很有效,因为宽度是在CSS类中定义的,我需要动态地用基于浏览器窗口和内容宽度计算出的值来覆盖它。 - Chris Rasco

33

在阅读其他答案并进行实验后,这是对我有用的方法:

$(".selector")[0].style.setProperty( 'style', 'value', 'important' );

不过,在IE 8及以下版本中,这个方法不起作用。


1
由于我们仍然需要支持IE8(我们中的一些人,不幸的是)- 这不太好。 - mkoryak

32

现在大部分答案已经过时,IE7的支持已经不是问题。

支持IE11+和所有现代浏览器的最佳方法是:

const $elem = $("#elem");
$elem[0].style.setProperty('width', '100px', 'important');

或者如果您想的话,可以创建一个小的jQuery插件来实现这个功能。 这个插件在支持的参数上与jQuery自己的css()方法非常相似:

/**
 * Sets a CSS style on the selected element(s) with !important priority.
 * This supports camelCased CSS style property names and calling with an object 
 * like the jQuery `css()` method. 
 * Unlike jQuery's css() this does NOT work as a getter.
 * 
 * @param {string|Object<string, string>} name
 * @param {string|undefined} value
 */   
jQuery.fn.cssImportant = function(name, value) {
  const $this = this;
  const applyStyles = (n, v) => {
    // Convert style name from camelCase to dashed-case.
    const dashedName = n.replace(/(.)([A-Z])(.)/g, (str, m1, upper, m2) => {
      return m1 + "-" + upper.toLowerCase() + m2;
    }); 
    // Loop over each element in the selector and set the styles.
    $this.each(function(){
      this.style.setProperty(dashedName, v, 'important');
    });
  };
  // If called with the first parameter that is an object,
  // Loop over the entries in the object and apply those styles. 
  if(jQuery.isPlainObject(name)){
    for(const [n, v] of Object.entries(name)){
       applyStyles(n, v);
    }
  } else {
    // Otherwise called with style name and value.
    applyStyles(name, value);
  }
  // This is required for making jQuery plugin calls chainable.
  return $this;
};
// Call the new plugin:
$('#elem').cssImportant('height', '100px');

// Call with an object and camelCased style names:
$('#another').cssImportant({backgroundColor: 'salmon', display: 'block'});

// Call on multiple items:
$('.item, #foo, #bar').cssImportant('color', 'red');

这里是示例jsfiddle


30

你可以这样做:

$("#elem").css("cssText", "width: 100px !important;");

使用"cssText"作为属性名称,将您想要添加到CSS中的任何内容作为其值。


6
这样做的缺点是它会覆盖掉之前存在的任何“cssText” - 所以你不能自由地使用它。 - mkoryak
2
无论如何,您可以使用$("#elem").css("cssText", "+=;width: 100px !important;"); - lexa-b
不要忘记你可以使用波浪号字符串引用来包含变量:例如。element.css({ 'cssText': `top: ${xTop}px !important` }); - Grant

19

您可以通过两种方式来实现这一点:

$("#elem").prop("style", "width: 100px !important"); // this is not supported in chrome
$("#elem").attr("style", "width: 100px !important");

实际上, .prop() 函数 是在 jQuery v1.6 中添加的,并且可以在 Chrome 中使用... 这是从 prop 页面引用的:在 jQuery 1.6 之前,.attr() 方法有时会在检索某些属性时考虑属性值,这可能会导致不一致的行为。从 jQuery 1.6 开始,.prop() 方法提供了一种显式检索属性值的方法,而 .attr() 则检索属性。 - Mottie
1
这不是一个通用解决方案的好主意。使用它可能会覆盖您现有的样式。 - Nirav Zaveri

14

没有必要去理解@AramKocharyan的答案的复杂性,也没有必要动态插入任何样式标签。

只需要覆盖样式,但是你不必解析任何东西,为什么要这样做呢?

// Accepts the hyphenated versions (i.e. not 'cssFloat')
function addStyle(element, property, value, important) {
    // Remove previously defined property
    if (element.style.setProperty)
        element.style.setProperty(property, '');
    else
        element.style.setAttribute(property, '');

    // Insert the new style with all the old rules
    element.setAttribute('style', element.style.cssText +
        property + ':' + value + ((important) ? ' !important' : '') + ';');
}

不能使用removeProperty(),因为在Chrome中它无法删除!important规则。
不能使用element.style[property] = '',因为在Firefox中它只接受camelCase。

使用jQuery可能会更简短,但此原生函数将在现代浏览器、Internet Explorer 8等上运行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接