你能在CSS中使用if/else条件吗?

Hai*_*vgi 107 css stylesheet conditional-statements

我想在我的CSS中使用条件.

我的想法是,当运行站点以生成正确的样式表时,我有一个我替换的变量.

我想要它,以便根据这个变量样式表改变!

看起来像:

[if {var} eq 2 ]
    background-position : 150px 8px;
[else]
    background-position : 4px 8px; 
Run Code Online (Sandbox Code Playgroud)

可以这样做吗?你怎么做到这一点?

Bol*_*wyn 125

不是传统意义上的,但如果您可以访问HTML,则可以使用类.考虑一下:

<p class="normal">Text</p>

<p class="active">Text</p>
Run Code Online (Sandbox Code Playgroud)

并在您的CSS文件中:

p.normal {
  background-position : 150px 8px;
}
p.active {
  background-position : 4px 8px;
}
Run Code Online (Sandbox Code Playgroud)

这是CSS的方式.


然后是像Sass这样的CSS预处理器.你可以在那里使用条件,看起来像这样:

$type: monster;
p {
  @if $type == ocean {
    color: blue;
  } @else if $type == matador {
    color: red;
  } @else if $type == monster {
    color: green;
  } @else {
    color: black;
  }
}
Run Code Online (Sandbox Code Playgroud)

缺点是,您必须预先处理样式表,并且在编译时评估条件,而不是运行时.


CSS本身的一个新功能是自定义属性(也就是CSS变量).它们在运行时进行评估(在支持它们的浏览器中).

有了他们,你可以做一些事情:

:root {
  --main-bg-color: brown;
}

.one {
  background-color: var(--main-bg-color);
}

.two {
  background-color: black;
}
Run Code Online (Sandbox Code Playgroud)

最后,您可以使用自己喜欢的服务器端语言预处理样式表.如果您使用的是PHP,请提供一个style.css.php类似于以下内容的文件:

p {
  background-position: <?php echo (@$_GET['foo'] == 'bar')? "150" : "4"; ?>px 8px;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您将对性能产生影响,因为缓存这样的样式表将很困难.

  • 很好的答案,我只想补充一点关于缓存:由于浏览器缓存样式表并且通常不会为每个页面重新下载它们,因此很难依赖PHP/[编程语言选择]生成的"动态"样式表.这不是它应该工作的方式.如果您需要更改CSS,您可以将其嵌入页面当然,但这开始违背内容/表示分离. (9认同)
  • 关于deceze所说的,这并不意味着你不能拥有一个动态变化的网站.样式表可以保持静态,您可以使用带有或不带有jquery或PHP的javascript来更改元素类,这样可以改变元素样式. (2认同)

Pet*_*ter 18

我很惊讶没有人提到 CSS 伪类,它们也是 CSS 中的一种条件。你可以用它做一些非常高级的事情,而无需一行 JavaScript。

一些伪类:

  • :active - 元素是否被点击?
  • :checked - 是否选中了单选框/复选框/选项?(这允许通过使用复选框进行条件样式!)
  • :empty - 元素是否为空?
  • :fullscreen - 文档是否处于全屏模式?
  • :focus - 元素是否有键盘焦点?
  • :focus-within - 元素或其任何子元素是否具有键盘焦点?
  • :has([selector]) - 元素是否包含与 [selector] 匹配的子元素?(遗憾的是,任何主要浏览器都不支持。)
  • :hover - 鼠标悬停在这个元素上吗?
  • :in-range/:out-of-range - 输入值是否在最小和最大限制之间/之外?
  • :invalid/:valid - 表单元素是否包含无效/有效内容?
  • :link - 这是一个未访问的链接吗?
  • :not() - 反转选择器。
  • :target - 这个元素是 URL 片段的目标吗?
  • :visited - 用户以前访问过这个链接吗?

例子:

div { color: white; background: red }
input:checked + div { background: green }
Run Code Online (Sandbox Code Playgroud)
<input type=checkbox>Click me!
<div>Red or green?</div>
Run Code Online (Sandbox Code Playgroud)

  • 很棒的列表,但不涵盖自定义状态...因为我在根 html 元素上设置了一些自定义属性,所以我添加了 `html[style*="--playerState:PAUSED"]` 来补充一些自定义状态,也可能只是已使用数据集代替,但是哦,好吧。 (2认同)

mar*_*kus 15

以下是我的旧答案仍然有效,但我今天有一个更加自以为是的方法:

CSS糟透了的原因之一就是它没有条件语法.CSS本身在现代Web堆栈中完全无法使用.使用SASS一会儿,你会知道我为什么这么说.SASS具有条件语法......以及与原始CSS相比还有很多其他优点.


旧答案(仍然有效):

一般来说,它无法在CSS中完成!

您有浏览器条件,例如:

/*[if IE]*/ 
body {height:100%;} 
/*[endif]*/
Run Code Online (Sandbox Code Playgroud)

但没有人阻止您使用Javascript来动态更改DOM或动态分配类,甚至连接各自编程语言中的样式.

我有时将css类作为字符串发送到视图并将它们回显到代码中(php):

<div id="myid" class="<?php echo $this->cssClass; ?>">content</div>
Run Code Online (Sandbox Code Playgroud)

  • 没有人表示CSS中不存在条件语法.条件注释仅存在于HTML中. (10认同)

vsy*_*ync 10

更新:

我写了一篇关于CSS-Tricks 中的以下独特方法的文章,其中详细介绍了


我设计了下面的演示,使用混合技巧,允许模拟 某些属性的if/else场景。本质上是数字的任何属性都是此方法的容易目标,但具有文本值的属性是。

这段代码有 3 个if/else场景, for opacity, background color& width。所有 3 都由两个布尔变量bool及其相反的notBool.

这两个布尔值是此方法的关键,要从非布尔动态值中实现布尔值,需要一些数学运算,幸运的是 CSS 允许使用min&max函数。

显然,最近的浏览器版本支持这些函数(最小值/最大值),这些版本也支持 CSS 自定义属性(变量)。

var elm = document.querySelector('div')

setInterval(()=>{
  elm.style.setProperty('--width', Math.round(Math.random()*80 + 20))
}, 1000)
Run Code Online (Sandbox Code Playgroud)
:root{
   --color1: lightgreen;
   --color2: salmon;
   --width: 70;  /* starting value, randomly changed by javascript every 1 second */
}

div{
 --widthThreshold: 50;
 --is-width-above-limit: Min(1, Max(var(--width) - var(--widthThreshold), 0));
 --is-width-below-limit: calc(1 - var(--is-width-above-limit));
 
 --opacity-wide: .4;     /* if width is ABOVE 50 */
 --radius-narrow: 10px;  /* if width is BELOW 50 */
 --radius-wide: 60px;    /* if width is ABOVE 50 */
 --height-narrow: 80px;  /* if width is ABOVE 50 */
 --height-wide: 160px;   /* if width is ABOVE 50 */
 
 --radiusToggle: Max(var(--radius-narrow), var(--radius-wide) * var(--is-width-above-limit));
 --opacityToggle: calc(calc(1 + var(--opacity-wide)) - var(--is-width-above-limit));
 --colorsToggle: var(--color1) calc(100% * var(--is-width-above-limit)), 
                 var(--color2) calc(100% * var(--is-width-above-limit)), 
                 var(--color2) calc(100% * (1 - var(--is-width-above-limit)));
  
 --height: Max(var(--height-wide) * var(--is-width-above-limit), var(--height-narrow));
 
 height: var(--height);
 text-align: center;
 line-height: var(--height);

 width: calc(var(--width) * 1%);
 opacity: var(--opacityToggle);
 border-radius: var(--radiusToggle);
 background: linear-gradient(var(--colorsToggle));

 transition: .3s;
}

/* prints some variables */
div::before{
  counter-reset: aa var(--width);
  content: counter(aa)"%";
}

div::after{
  counter-reset: bb var(--is-width-above-limit);
  content: " is over 50% ? "counter(bb);
}
Run Code Online (Sandbox Code Playgroud)
<div></div>
Run Code Online (Sandbox Code Playgroud)

另一种简单的使用方法clamp

label{ --width: 150 }
input:checked + div{ --width: 400 }

div{
  --isWide: Clamp(0,   (var(--width) - 150) * 99999, 1);
  width: calc(var(--width) * 1px);
  height: 150px;
  border-radius: calc(var(--isWide) * 20px); /* if wide - add radius */
  background: lightgreen;
}
Run Code Online (Sandbox Code Playgroud)
<label>
<input type='checkbox' hidden> 
<div>Click to toggle width</div>
</label>
Run Code Online (Sandbox Code Playgroud)

迄今为止最好的:

我想出了一个完全独特的方法,它更简单!

这个方法很酷,因为它很容易实现,也很容易理解。它基于animation step()功能。

由于bool可以很容易地计算为01,因此可以在step! 如果只定义了一个步骤,那么if/else问题就解决了。

使用关键字forwards持久化更改。

var elm = document.querySelector('div')

setInterval(()=>{
  elm.style.setProperty('--width', Math.round(Math.random()*80 + 20))
}, 1000)
Run Code Online (Sandbox Code Playgroud)
:root{
   --color1: salmon;
   --color2: lightgreen;
}

@keyframes if-over-threshold--container{
  to{ 
     --height: 160px;
     --radius: 30px;
     --color: var(--color2);
     opacity: .4; /* consider this as additional, never-before, style */
  }
}

@keyframes if-over-threshold--after{
  to{ 
    content: "true"; 
    color: green; 
  }
}

div{
 --width: 70;           /* must be unitless */
 --height: 80px;
 --radius: 10px;
 --color: var(--color1);
 --widthThreshold: 50;
 --is-width-over-threshold: Min(1, Max(var(--width) - var(--widthThreshold), 0));

 
 text-align: center;
 white-space: nowrap;
 transition: .3s;
 
 /* if element is narrower than --widthThreshold */
 width: calc(var(--width) * 1%);
 height: var(--height);
 line-height: var(--height);
 border-radius: var(--radius);
 background: var(--color);

 /* else */
 animation: if-over-threshold--container forwards steps(var(--is-width-over-threshold));
}

/* prints some variables */
div::before{
  counter-reset: aa var(--width);
  content: counter(aa)"% is over 50% width ? ";
}

div::after{
  content: 'false'; 
  font-weight: bold; 
  color: darkred;
  
  /* if element is wider than --widthThreshold */
  animation: if-over-threshold--after forwards steps(var(--is-width-over-threshold)) ;
}
Run Code Online (Sandbox Code Playgroud)
<div></div>
Run Code Online (Sandbox Code Playgroud)


我发现了一个Chrome 错误,我已报告该错误会在某些需要特定类型计算的情况下影响此方法,但有一种解决方法。


RaY*_*ell 8

您可以创建两个单独的样式表,并根据比较结果包含其中一个样式表

在其中一个你可以把

background-position : 150px 8px;
Run Code Online (Sandbox Code Playgroud)

在另一个

background-position : 4px 8px;
Run Code Online (Sandbox Code Playgroud)

我认为你可以在CSS中执行的唯一检查是浏览器识别:

条件CSS


beg*_*ggs 6

将服务器设置为将css文件解析为PHP,然后使用简单的PHP语句定义变量变量.

当然这假设您正在使用PHP ...

  • 您可以将"PHP"替换为"您选择的编程或模板语言" (2认同)
  • 是的,但你可以提取需要动态的部分,并通过`@import url('dynamic.css.php')`重新包含它们. (2认同)

yee*_*dle 6

您可以calc()结合使用与var()模拟条件句:

:root {
--var-eq-two: 0;
}

.var-eq-two {
    --var-eq-two: 1;
}

.block {
    background-position: calc(
        150px * var(--var-eq-two) +
        4px * (1 - var(--var-eq-two))
    ) 8px;
}
Run Code Online (Sandbox Code Playgroud)

概念


Kur*_*ula 5

您可以使用not代替if

.Container *:not(a)
{
    color: #fff;
}
Run Code Online (Sandbox Code Playgroud)


Ond*_*žka 5

CSS 是一个设计精美的范式,它的许多功能都没有被广泛使用。

如果条件和变量是指将某个值的更改分发到整个文档或某个元素的范围内的机制,那么这是如何做到的:

var myVar = 4;
document.body.className = (myVar == 5 ? "active" : "normal");
Run Code Online (Sandbox Code Playgroud)
body.active .menuItem {
  background-position : 150px 8px;
  background-color: black;
}
body.normal .menuItem {
  background-position : 4px 8px; 
  background-color: green;
}
Run Code Online (Sandbox Code Playgroud)
<body>
<div class="menuItem"></div>
</body>
Run Code Online (Sandbox Code Playgroud)

这样,您就可以在整个 CSS 样式中分配变量的影响。这类似于@amichai 和@SeReGa 的提议,但更通用。

另一个这样的技巧是在整个文档中分发某个活动项目的 ID,例如再次突出显示菜单时:(使用 Freemarker 语法)

var chosenCategory = 15;
document.body.className = "category" + chosenCategory;
Run Code Online (Sandbox Code Playgroud)
<#list categories as cat >
    body.category${cat.id} .menuItem { font-weight: bold; }
</#list>
Run Code Online (Sandbox Code Playgroud)
<body>
<div class="menuItem"></div>
</body>
Run Code Online (Sandbox Code Playgroud)

当然,这仅适用于有限的项目集,例如类别或状态,而不是像电子商店商品那样的无限集,否则生成的 CSS 会太大。但是在生成静态离线文档时特别方便。

将 CSS 与生成平台结合起来做“条件”的另一个技巧是:

.myList {
   /* Default list formatting */
}
.myList.count0 {
   /* Hide the list when there is no item. */
   display: none;
}
.myList.count1 {
   /* Special treatment if there is just 1 item */
   color: gray;
}
Run Code Online (Sandbox Code Playgroud)
<ul class="myList count${items.size()}">
<!-- Iterate list's items here -->
<li>Something...</div>
</ul>
Run Code Online (Sandbox Code Playgroud)