除CSS变量外,CSS自定义属性用于什么?

时间:2018-03-16 22:39:33

标签: css css3 css-variables

来自CSS工作组post

  

自定义属性不仅仅用于变量[...]

与许多人的想法相矛盾(参见this),这篇文章不仅证实了变量和自定义属性不是同一个东西,而且自定义属性可以用于除变量之外的其他东西。

我的问题是关于最后一部分。有没有人遇到过一些CSS代码,其中自定义属性用于变量以外的东西?

3 个答案:

答案 0 :(得分:3)

请注意,您引用的文字的上下文是CSSWG,证明为什么使用--foovar(--foo)代替$foo。我的猜测是他们的说法“自定义属性不仅仅用于变量”,这暗示了--foo标识符语法设置为出现在其他地方,用于其他自定义事物,如自定义媒体查询最初在MQ4中,现在在MQ5中。显然,这些不是级联变量,因为媒体查询不会级联(their enclosed rules do)。 (虽然如果是这样的话,“自定义属性”应该是别的东西,但CSSWG可能还没有想到这些东西的正确集体名称。)

  

有没有人遇到过一些CSS代码,其中自定义属性用于变量之外的东西?

我没有遇到任何现实世界的例子,但我刚刚敲了一个例子,它使用JavaScript根据自定义属性切换元素上的一个类,这反过来会影响CSS中其他地方的选择器: / p>

let p = document.querySelector('p');

if (window.getComputedStyle(document.documentElement).getPropertyValue('--boolean').trim() === "'true'")
  p.classList.add('toggle');
else
  p.classList.remove('toggle');
:root {
  --boolean: 'true';
}

p.toggle {
  color: #f00;
}

p::before {
  content: 'Value of --boolean is "' var(--boolean) '"';
}
<p>

当然,需要注意的是这是CSS 和JavaScript 。除了CSS中的级联变量之外,您不能使用自定义属性,因为custom properties participate in the cascade与任何其他CSS属性非常相似,并且不存在于其之外。这就是为什么authors conflate the two terms in everyday usage - 因为它们之间的任何差异都是学术性的。样式表中任何其他想要依赖自定义属性的部分都必须使用脚本才能使用它。

您可能想知道为什么这样的事情无法在CSS中实现。考虑:

p.toggle {
  --boolean: 'false';
}

如果我们根据CSS属性值提出匹配元素的伪类,比如p:prop(--boolean: 'true')

  • 伪类是否有效且在CSS之外总是匹配,有效且永不匹配或无效?
  • 反映的价值应该是多少?指定值,计算值或使用值?请注意,由于历史原因,即使window.getComputedStyle()也不总是返回计算值。
  • 循环依赖变得不可避免:

    :root {
      --boolean: 'true';
    }
    
    /* 
     * Causes p to stop matching the selector, switching back to
     * inheriting from :root, which in turn causes it to start
     * matching the selector again, ad infinitum.
     */
    p:prop(--boolean: 'true') {
      --boolean: 'false';
    }
    

仔细观察上面的JavaScript示例,您会注意到它不健壮。只要将文档放在一起,就只评估属性值一次。再次更改自定义属性值,元素不会更新自身以反映更改。如果它听取了对自定义属性值的更改,它会立即遇到相同的循环依赖问题 - 更糟糕的是,锁定浏览器(直到它注意到并拦截无限递归)。

答案 1 :(得分:2)

您链接的Stack Overflow answer实际上错误,并且正在谈论与您要求的内容略有不同的内容。它讨论了在相关的CSS规范中,自定义属性通常被描述为易于理解的变量,尽管它们的工作方式与其他语言中的变量的工作方式不同(但这对于使用CSS的课程来说是不同的,不是是吗?)。

CSS自定义属性的可变部分实际上是您调用(或使用)自定义属性的方式:

.example {
    background: var(--custom-property);
}

正如您在the spec中看到的,完全标题为“级联变量模块级别1的CSS自定义属性”,只有一个用途:在var()的级联元素中作为值调用。因此,当他们说自定义属性不仅仅用于变量时,该wiki帖子的作者意味着什么还有点不清楚。此外,后续句子并未真正描述或备份该声明,他们只是谈论如何使用$代替-是“怪异”。

也许他们意味着您可以声明一个仅在JavaScript读取时才有效的自定义属性?或者在JS中声明一个随后应用于CSS的自定义属性。自定义变量语法支持CSS解析器无法正确读取的方程式,但可以在JavaScript中正确读取。但是,结果仍然是使用var()声明的元素的属性值

为了解决这个问题,如果他们在属性中使用以外的,那么将它们称为自定义属性是没有意义的。规范没有提到在CSS或JS中调用或使用属性的替代方法,而不使用级联选择器的属性值部分中的var(){}之间的代码位)。

答案 2 :(得分:2)

其他问题解释了自定义属性和CSS变量,但如果我们简单说明自定义属性只是为了允许我们添加除CSS默认属性之外的更多属性。当然,单独的自定义属性是无用的,因为浏览器不会对它做任何事情,这就是为什么在99%的情况下它们与CSS变量一起使用。

另一个事实是,在做CSS时我们会直观地考虑使用默认的CSS属性来做我们想要的事情。当我们面对复杂的情况时,我们会尝试将很多属性,伪元素等组合在一起。为了实现我们的需求。但是如果我们以不同的方式思考并且为此目的开始使用自定义属性呢?如果不是复杂的CSS代码,我们只需编写一个自定义属性并实现一个JS / jQuery代码,它将为我们完成工作。

我们来看一个简单而常见的例子。你有一个你想要绝对位置的元素,以便将它用作他的父元素的叠加。使用CSS,我们将执行以下操作:

.block {
  height:100px;
  width:100px;
  margin:20px; 
  border:1px solid red;
  position:relative; /* we usually forget this !*/
}

.overlay {
  position:absolute;
  top:0;
  right:0;
  left:0; /*sometimes we use width:100% but it won't work with padding!*/
  bottom:0;
  padding:5px;
  z-index:1; /* we can forget this sometimes*/
  background:rgba(0,0,0,0.5);
}
<div class="block">
<span class="overlay"></span>
  some text here
</div>

这很简单,如果我们想拥有相同的东西,我们可以在任何地方使用同一个类。但我们可以考虑一个自定义属性,它将减少CSS代码并使其更容易:

$('*').each(function() {
  if ($.trim($(this).css('--overlay')) === "top") {
    $(this).css({
      'position': 'absolute',
      'top': 0,
      'bottom': 0,
      'left': 0,
      'right': 0,
      'z-index':2
    });
    $(this).parent().css('position','relative');
  } else {
    //we test the other values and we do the necessary changes
  }
})
.block {
  height: 100px;
  width: 100px;
  margin: 20px;
  border: 1px solid red;
}

.overlay {
  --overlay: top;
  background: rgba(0, 0, 0, 0.5);
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<div class="block">
  <span class="overlay"></span> 
  some text here
</div>

我知道第一个想法是“为什么要使用所有这些代码来解决我们可以用CSS做的那么简单的事情?”和“如果财产发生变化怎么办?如果父母已经设置了一个职位怎么办?”这是真的,但这是一个非常简单的例子。想象一下,你构建了一个JS或jQuery库,你可以为复杂的东西提供许多自定义属性(创建常见的CSS形状,在难以计算值的情况下进行复杂的转换等),并为每个库提供各自值的文档。 / p>

它就像一个JS / jQuery库,它告诉你为你的元素添加一个类并调用一个函数然后你有一个响应滑块,一个交互式地图,一个推特小部件等。为什么不对自定义属性做同样的事情?我们要求人们包含库并简单地编写CSS,然后看看魔术。

我们还可以将此视为升级,方法是添加更多有用的属性以简化操作。完全像CSS制造商一样,但我们自己做,不要等到有新的规格,直到它被批准。

我们以flexbox为例。在flexbox之前,如果我们想在容器内部有N个div,这个容器具有完全相同的大小并填充所有容器,我们就必须编写一些复杂的代码,每次添加新元素时我们都必须调整这些代码。现在使用flexbox,我们只需设置flex:1就可以了!浏览器将为我们完成所有复杂的工作。

我们可以做同样的事情。我们创建自定义属性以简化操作,并将其分享给社区。人们将开始使用它们并且可能发现它们有用然后它们可以成为常见问题的参考。也许某些浏览器甚至会考虑实现它们的集成。

因此,自定义属性也可以成为增强CSS的一种方式。