我可以通过 ":hover" 和 ":active" 以外的选择器触发 CSS 转换吗?

Posted

技术标签:

【中文标题】我可以通过 ":hover" 和 ":active" 以外的选择器触发 CSS 转换吗?【英文标题】:Can I trigger CSS transitions via selectors other than ":hover" and ":active"? 【发布时间】:2018-05-22 22:56:18 【问题描述】:

我正在通过 sololearn.com 了解 CSS3 中的过渡,其中给出的使用过渡的唯一示例是与 :hover 选择器结合使用。

我能找到的所有其他东西都使用那个或:active,没有解释可以使用哪些其他选择器,或者为什么没有将这两个选择器以外的选择器作为示例显示。

有没有办法在没有用户交互的情况下开始转换?或者这需要 javascript 吗?

【问题讨论】:

转换仅在 state 发生变化时实现。除非用户更改某些内容,否则这不会发生。您可能会问 animations 相关但不同 这要求提供有关初始化过渡/动画的教程,根据help center 中概述的站点指南,范围过于广泛 这个问题很好,只是需要一个不那么贴切的标题。但答案是,您实际上并不需要选择器来进行转换。 @charlietfl 我认为我的问题没有违反任何规则,我相信我的问题符合“建设性主观问题”according to the help center 的所有要求。 @Paulie:如果我们使用术语 state,我们需要对其进行定义。并且为它找到一个完整且适当的定义(在 DOM 元素的上下文中)可能具有挑战性。更安全地说,transitions 指的是transition-property 中指定的动画属性的值变化 【参考方案1】:

tl;博士

您可以使用任何选择器来启动transition,但您实际上并不需要它。您只需要:

在元素上设置transition 属性 更改要转换的属性的值。

您可以在不使用 CSS 选择器的情况下完成上述两种操作,这不过是一种用于设置 DOM 元素属性的便捷方法。


初步回答

transitions 适用于任何选择器。但它们与任何选择器都没有关系,而且您实际上并不需要选择器来执行 CSS 转换。

transition 工作所需的只是设置以下转换属性:

transition-duration, transition-delay, transition-timing-function transition-property。 (必须是动画才能过渡到工作)。

此后,每当transition-property 中命名的属性在两个可动画值之间更改其值时,初始值和设置值之间的更改将根据设置的transition 属性发生。 p>

无论究竟是什么触发了已转换属性的值更改,都会发生这种情况

它可以:

更改,因为特定的 CSS 选择器(您定义的)开始或停止应用(匹配元素); 使用 JavaScript 直接更改。

或者,当然,通过两者的结合(即使用 JavaScript 应用一个类,这会改变正在转换的属性的值)

因此,实际上,您的问题的答案是:transitions 可以与任何选择器一起使用,但它们也可以在没有选择器的情况下使用。它们基于 DOM 元素属性值工作,与任何选择器无关

演示transition 的常用方法是使用:hover 状态,因为在选择器之间切换(即控制/演示/观察转换)所需要做的就是。嗯,...悬停!


开启:

例如,有没有一种方法可以在没有用户交互的情况下开始转换?

当然有!一个非常基本的示例是在所有页面资源完成加载后在<body> 上添加一个类。 当<body> 元素被创建时它没有类并且当所有资源都完成加载时,Windowonload 事件触发。我们可以使用这个事件来添加类。如果在body 上正确定义了过渡,并且由于现在在元素上应用了更强大的选择器,transitioned 属性发生了变化,那么过渡将会发生。无需任何用户交互。

看看它的工作原理:

window.onload = function() 
  document.querySelector('body').classList.add('loaded')
body 
  background-color: #fff;
  transition: background-color 1s linear;

.loaded  background-color: #212121;

您还可以设置一个递归函数,该函数切换元素的状态并在设定的时间后调用自身,在设定的时间后有效地在连续循环中切换状态:

对于上面的例子,这意味着:

window.onload = toggleBodyClass;
function toggleBodyClass() 
  document.querySelector('body').classList.toggle('loaded');
  setTimeout(toggleBodyClass, 1234);
body 
  background-color: #fff;
  transition: background-color 1s linear;

.loaded  background-color: #212121;

如果问题是:“选择器可以在不使用 JavaScript 和/或用户交互的情况下开始/停止应用吗?” 它实际上可以转化为:“是否有过渡由通常触发transition的其他东西触发?”,可能的答案有: “你为什么想知道?”“是否有没有 JavaScript 和/或用户交互的网页浏览?”

【讨论】:

【参考方案2】:

正如 Paulie_D 所说,转换是状态的变化。这个“状态”指的是任何样式属性的值(无论如何都可以动画)。甚至spec 也是这样描述的:

通常,当 CSS 属性的值发生变化时,渲染结果会立即更新,受影响的元素会立即从旧属性值更改为新属性值。本节描述了一种使用新 CSS 属性指定转换的方法。这些属性用于随着时间的推移从旧状态平滑地动画到新状态。

这意味着您实际上不需要选择器来启动转换。可以通过 CSS、JavaScript 或内联 style 属性更改样式。所有这些都受到转换的影响,因为它们都修改了样式属性值。选择器恰好是最常见的实现方式,因为选择器和声明块是构成样式规则的两个基本组件,它们本身就是 CSS 的构建块。

在有或没有用户交互的情况下使用过渡的大多数其他方式实际上都涉及 JavaScript,因为 CSS 不支持在不需要用户交互的情况下进行大量状态更改(除了动画,这是与过渡不同的野兽),但那不这并不意味着 JavaScript 本质上是转换工作所必需的,因为转换是关于状态更改的,而不管如何调用状态更改(JS 与否)。

大多数教程使用:hover:active 来演示转换,因为用户交互是读者查看转换的最简单和最直观的方式,并了解元素改变状态的含义(尽管different kind of state,但原理是一样的)。它也是迄今为止最常见的过渡用例:根据用户交互对状态变化进行动画处理。

但您实际上并不需要使用用户交互伪类更改属性值才能使转换生效。您可以使用任何选择器更改它们,即使用户交互由不同的元素处理(并且该元素不必使用 :hover:active 开始转换)...

label 
  transition: color 1s linear;


:checked + label 
  color: #f00;
<p><input type=checkbox id=check><label for=check>Label</label>

...或页面本身...

h1 
  transition: color 1s linear;


:target 
  color: #f00;
<p><a href=#sec1>Section 1</a> <a href=#sec2>Section 2</a>
<h1 id=sec1>Section 1</h1>
<h1 id=sec2>Section 2</h1>

将 JavaScript 添加到组合中后,您可以直接设置属性值(即不使用选择器)...

setTimeout(function() 
  document.querySelector('p').style.color = '#f00';
, 1000);
p 
  transition: color 1s linear;
&lt;p&gt;Wait for it...

...更改元素的类、ID 或其他属性...

setTimeout(function() 
  document.querySelector('p.foo').className = 'bar';
, 1000);

setTimeout(function() 
  document.getElementById('foo').id = 'bar';
, 2000);

setTimeout(function() 
  document.querySelector('p[data-attr]').dataset.attr = 'bar';
, 3000);
p 
  transition: color 1s linear;


p.bar  color: #f00; 
p#bar  color: #090; 
p[data-attr=bar]  color: #00f; 
<p class=foo>Wait for it...
<p id=foo>Wait for it...
<p data-attr=foo>Wait for it...

... 甚至在 DOM 树中移动元素(尽管这个 确实 有 limitations - 请注意 Foo 项无法开始其转换,因为它在重新连接之前已经分离,而一旦 Bar 项目注意到它现在是第一个,它就能够开始它的转换,因为它永远不会离开 DOM 树)...

setTimeout(function() 
  var ul = document.querySelector('ul');
  ul.appendChild(ul.firstChild);
, 1000);
li 
  transition: color 1s linear;


li:first-child  color: #f00; 
&lt;ul&gt;&lt;li&gt;Foo&lt;li&gt;Bar&lt;/ul&gt;

... 并且能够开始所有相同的转换。请注意,所有 JavaScript 示例都会自动开始转换,无需用户交互。

因此,总而言之,转换是关于状态变化的,并且所述状态变化与样式属性值的变化有关。它们独立于选择器或 JavaScript,尽管选择器是 CSS 的基本组成部分,并且您确实需要 JavaScript 来处理大多数事情。

【讨论】:

以上是关于我可以通过 ":hover" 和 ":active" 以外的选择器触发 CSS 转换吗?的主要内容,如果未能解决你的问题,请参考以下文章

jQuery `[jQuery created Element].is(":hover")` 似乎只在 Chrome 中工作

css 的area标签支持hover吗?

javascript 如何防止多次触发hover事件

如何查看网页上元素的 ":hover" 和 ":active" 属性? [复制]

tapmode="hover"属性

为啥 Qt 样式表 "Foo:hover * " 总是适用?