使用JavaScript删除所有CSS样式而不删除类。

3
有没有一种方法可以使用JavaScript从特定选择器中删除所有CSS样式,而不将选择器本身从元素中删除?
问题在于,我想向元素添加自己的类来处理样式,但该元素是由WordPress插件创建的,并且已经有覆盖我的类的类。 我无法删除原始类,因为它们还用于Javascript。
通常情况下,我会放弃并在我的类中添加! important来处理问题,如果没有其他方法,我仍然可以这样做。 但是,原始类实际上定义了几乎所有内容,包括多个伪状态,因此我必须列出从color:border-bottom-right-radius:的所有内容,并在其后添加!important (包括:focus:hover 等所有内容)以覆盖所有原始样式。
基本上,我有以下内容:
<button class="original-class-1 original-class-2">Button</button>

<style>
    .my-styles {
        color: #fafafa;
        background-color: #090909;
        border: 1px solid;
     }

    .original-class-1 {
        color: #000000;
        background-color: #ffffff;
        border-width: 1px;
        border-style: solid;
        ...
        ...
        etc-with-everything-but-the-kitchen-sink: killme;
     }

     .original-class-2 {
        padding-top: 5px;
        padding-right: 5px;
        padding-bottom: 5px;
        padding-left: 5px;
        ...
        ...
        etc-with-even-more-stuff: why;
     }
</style>

and I want

<button class="original-class-1 original-class-2 my-styles">Button</button>

<style>
     .my-styles {
        color: #fafafa;
        background-color: #090909;
        border: 1px solid;
     }

     .original-class-1 {
     }

     .original-class-2 {
     }
</style>

目前我已经开始做了类似于这样的东西:

const buttons = document.querySelectorAll('.original-class-1');

for (const button of buttons ) {
    
    button.style.removeAllProperties(); // Does something like this exist?
    button.classList.add('my-styles');
    
}

明确一下,原始类别是从一个外部样式表中增加样式的,我只是将它们放在上面的<style> 标签中以便说明。


2
这样的东西存在吗? - Jaromanda X
https://developer.wordpress.org/themes/advanced-topics/child-themes/#how-to-create-a-child-theme - dale landry
在评论中,您指出插件样式稍后加载。因此,问题中的示例CSS有点误导,因为它显示自定义样式在加载之后。然而,这是一个很好的问题+1。 - Yogi
真的 - 我已经更新了原始内容以澄清我正在经历的级联顺序。 - Shoelaced
https://developer.mozilla.org/zh-CN/docs/Web/API/CSSStyleDeclaration/removeProperty 不是很高效,但我认为这与所要求的内容有关。 - TiagoT
4个回答

1
你可以尝试在CSS中使用all: revertall: initial来重置自定义类的样式,然后再提供实际规则。本段代码使用了revert进行实验(选择适合你的方法),并使用夸张的样式使更改更加明显。请注意保留HTML标记。

.original-class-1 {
    color: #000000;
    background-color: limegreen;
    border-width:7px;
    border-style: solid;
    /* plus more */
}
.original-class-1:hover {
   border-style: dashed;
}


.original-class-2 {
    padding-top: 15px;
    padding-right: 15px;
    padding-bottom: 15px;
    padding-left: 15px;
    /* plus more */
 
}

.my-styles, .my-styles:hover {
    all: revert;
    color: #fafafa;
    background-color: #090909;
    border: 3px solid red;
}
<button class="original-class-1 original-class-2">Button</button>
<button class="original-class-1 original-class-2 my-styles">Button2</button>

伪元素选择器似乎不会对冒号后的通配符做出响应,例如为一个虚构的".my-style:*"选择器指定规则,因此需要在.my-style:hover选择器中明确复制.my-style规则。

谢谢回复,是的,我尝试过像这样的东西,但插件的样式表在我的样式之后加载,所以它仍会覆盖“all:revert”。如果我能弄清楚如何让我的样式成为内联的... - Shoelaced
无论如何,我会点赞,因为我觉得它很有趣,而且我认为它可能对其他试图解决类似问题的人有帮助。+1 - Yogi
谢谢。我接下来的想法是在JavaScript中在类似于DOMContentLoaded的事件触发后,将自定义样式表加载/追加到DOM中。不幸的是,我无法尝试Wordpress,也不知道它是否提供复杂的替代方案。 - traktor
感谢@traktor-- 它给了我一些想法。 - Shoelaced

0
提供的示例中,按钮元素是使用类进行样式设置的,而不是使用元素的“style”属性。由于按钮元素是使用类进行样式设置的,因此您可以尝试修改按钮上的“class”属性。

window.onload = () => {
  const buttons = document.querySelectorAll('.original-class-1');
  buttons.forEach(button => button.setAttribute('class', 'my-styles'));
}
.original-class-1 {
  color: #000000;
  background-color: red;
  border-width: 1px;
  border-style: solid;
}

.original-class-2 {
  padding-top: 5px;
  padding-right: 5px;
  padding-bottom: 5px;
  padding-left: 5px;
}

.my-styles {
  color: #fafafa;
  background-color: #090909;
  border: 1px solid;
}
<button class="original-class-1 original-class-2">Button</button>

正如您在这里看到的那样,按钮元素现在具有您的.my-styles,而且没有原来的任何类。

我不熟悉WordPress,可能最好通过他们的工具来处理,而不是以这种方式操作您的DOM。祝好运。

参考:Element.setAttribute()


编辑: 如果你想要变得非常hacky,你总是可以做一些有趣的事情,比如以下内容:(我不建议你这样做 :-))

window.onload = () => {
    const targetClass = Object.values(document.styleSheets[0].cssRules).find((rule) => rule.selectorText == '.very-red');
    if (targetClass) {
        Object.values(targetClass.style).forEach((property) => targetClass.style.removeProperty(property));
    };
}
.very-red {
  color: #000000;
  background-color: red;
}
<button class="very-red">Very Not Red Button</button>


很遗憾,这样做行不通。插件使用现有的类名作为选择器。如果我们像这段代码一样将它们移除,那么就会破坏插件。这就是根本问题所在。 - Yogi
感谢@glennpai的回复,但是为了JavaScript的缘故,我需要保留元素上的原始类,并仅删除附加的样式。我只是希望这比逐个覆盖每个CSS属性更容易。 - Shoelaced
@Shoelaced 我明白了。我已经更新了我的帖子,提供了一种清空类中所有样式属性的方法。再次建议不要使用此方法,因为它在某些情况下可能会很耗费资源,而且老实说有点笨拙的蛮力解决方案。 - glennpai

0

使用JS重写样式表

这是一种非传统的方法,可能会产生意想不到的效果,但它使用JavaScript重新编写相关的样式表,为所有选择器留下空的规则集,除了那些您添加的选择器(这些选择器必须通过名称中包含某个常量标签来进行识别,在此示例中为.my-前缀)。

样式表与其他任何html元素一样,可以使用JavaScript访问并操纵其内容。

您需要对提取的样式元素集合中的每个元素进行一些探索性工作(通过报告到控制台),以便专注于相关的样式表。在这里,与片段工具样式面板相关的集合很容易找到是索引[0],因此在示例中使用它。

如果步骤不清楚,请留下评论,我将解释每个部分的目的。

let styleSheetCollections = document.getElementsByTagName('style');

let stylesText = styleSheetCollections[0].innerHTML;
const stylesBlockArray = stylesText.split("{");
let keepNext = false;

for (let i=1; i<stylesBlockArray.length; i++) {

if (!keepNext) {
stylesBlockArray[i]=stylesBlockArray[i].slice(stylesBlockArray[i].indexOf("}")-1);
} // end if;

if (stylesBlockArray[i].indexOf("my-") > -1) {keepNext = true;} else {keepNext = false};

} // next block;

newInnerText = stylesBlockArray.join("{");

console.log(newInnerText);

// replace style sheet innerText
// styleSheetCollections[0].innerText = newInnerText;
.original-class-1 {
        color: #000000;
        background-color: #ffffff;
        border-width: 1px;
        border-style: solid;
        ...
        ...
        etc-with-everything-but-the-kitchen-sink: killme;
     }
     
     .my-p_style {
       font-size: 12px;
       border: 0;
     }

     .my-h1_style {
       font-size: 22px;
       background: yellow;
     }
     
     .original-class-2 {
        padding-top: 5px;
        padding-right: 5px;
        padding-bottom: 5px;
        padding-left: 5px;
        ...
        ...
        etc-with-even-more-stuff: why;
     }

     .my-styles {
        color: #fafafa;
        background-color: #090909;
        border: 1px solid;
     }

You would uncomment the assignment back to the stylesheet in the last line when done.


0
使用Window.getComputedStyle()方法可以返回一个CSSStyleDeclaration对象,您可以简单地迭代键/值对并将所有内容设置为“initial”。

const button = document.querySelector("button");


const element = document.getElementsByClassName("myclass")[0];
const cssObj = window.getComputedStyle(element);




button.addEventListener('click', function(e) {
  for (x in cssObj) {
    cssObjProp = cssObj.item(x)
    let val = cssObj.getPropertyValue(cssObjProp);
    element.style.setProperty(val, "initial");
  }
});
.myclass {
  font-size: xxx-large;
  color: red;
}
<p class=myclass>Testing one two.</p>
<button>Fire JavaScript</button>


这看起来很有前途,但它似乎只是将 style="all: initial" 添加到元素中,这也覆盖了我的样式。有没有办法只复制 .my-class 的样式到内联的 style 属性中?如果我能做到这一点,它可能会起作用... - Shoelaced
当然可以。您只需使用JavaScript添加样式-在元素上使用相同的setProperty方法即可。首先将所有样式设置为“initial”,然后添加所需的任何样式。 - Ronnie Royston

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