使用字符串设置内联css过渡样式会更改真值.奇异的

Mic*_*ley 5 html javascript css css3

我有一个样式表,设置像这样的css过渡属性(为简洁省略了前缀版本):

transition: opacity 1s;
Run Code Online (Sandbox Code Playgroud)

然后我在页面上有许多元素,我希望transition-delay通过JavaScript 修改每个元素的属性,以产生交错效果.我正在使用jQuery:

$(element).css('transition-delay', delay + 's');
Run Code Online (Sandbox Code Playgroud)

然而,上述代码并没有内嵌添加transition-delay: Xs到元素.相反,它导致:

<div style="transition: Xs;">
Run Code Online (Sandbox Code Playgroud)

但这很好,因为它按预期工作.不知何故,浏览器知道这transition: Xs真的意味着只需设置transition-delay为Xs并保持其余部分不变.

然而:

如果我现在获得该元素的内联样式$(element).attr('style'),然后将其重新应用于元素,$(element).attr('style', style)则HTML看起来完全相同,但现在转换完全覆盖了其他属性,并且基本上将元素的转换值设置为all Xs ease 0s.

// HTML before - working
<div style="transition: Xs">

// then I do this
var style = $(el).attr('style');
$(el).attr('style', style);

// HTML after - broken!
<div style="transition: Xs">
Run Code Online (Sandbox Code Playgroud)

演示

正是我所描述的JSFiddle:http://jsfiddle.net/7vp8m/4/

到底是怎么回事?

Mic*_*ley 5

我想只是写出问题并编写该演示真的帮助我找到答案:

HTML style属性不是实际样式.我们需要使用CSSStyleDeclaration对象

尽管似乎内联样式与style="..."HTML属性中包含的内容一样简单(正如我所假设的),但事实证明并非如此.在幕后,内联样式(以及所有其他样式)实际上由一个名为CSSStyleDeclaration的对象定义.style属性中包含的字符串仅表示此对象,但不包含定义样式所需的所有信息.

这就是设置`el.style ="width:100px;"的原因.也没有工作.来自HTMLElement.styleMDN文章:

除Opera中外,无法通过为(只读)样式属性指定字符串来设置样式,如elt.style ="color:blue;".这是因为style属性返回CSSStyleDeclaration对象.相反,您可以像这样设置样式属性:

elt.style.color = "blue";  // Directly

var st = elt.style;
st.color = "blue";  // Indirectly
Run Code Online (Sandbox Code Playgroud)

所以这说明我们为什么这样做$(el).attr('style', 'transition: Xs');不会达到预期效果-而这正是我跑进去.这样做修改底层的CSSStyleDeclaration对象,但并不总是按照我们想要的方式(因此我原来的问题).

因此,解决方案是使用CSSStyleDeclaration提供的API.以下SO问题对我理解这个问题至关重要:JavaScript和复制风格

复制CSSStyleDeclaration:

var originalStyle = el.cloneNode().style;
Run Code Online (Sandbox Code Playgroud)

这里我们使用了cloneNode()方法,因为否则(如果我们只得到el.style)CSSStyleDeclaration对象是通过引用复制的,这不是我想要的,因为我将更改元素的内联样式然后我想恢复原来的风格以后.首先克隆元素允许我们获得CSSStleDeclaration的"新"副本,当我们改变元素的内联样式时,副本不会改变el.

使用保存的CSSStyleDeclaration替换当前内联样式

// first we need to delete all the style rules
// currently defined on the element
for (var i = el.style.length; i > 0; i--) {
    var name = el.style[i];
    el.style.removeProperty(name);
}

// now we loop through the original CSSStyleDeclaration 
// object and set each property to its original value

for (var i = originalStyle.length; i > 0; i--) {
    var name = originalStyle[i];
    el.style.setProperty(name,
        originalStyle.getPropertyValue(name),
        priority = originalStyle.getPropertyPriority(name));
}
Run Code Online (Sandbox Code Playgroud)

演示

这是我原始演示的更新,它实现了上述方法:http://jsfiddle.net/7vp8m/11/