【问题标题】:Sass - Manipulate inherited property?Sass - 操纵继承的财产?
【发布时间】:2013-02-01 23:14:53
【问题描述】:

是否可以在 Sass 中操作给定元素已经继承的值?

我的目标是这样的:

body
  color: blue
  .warning
    color: red

strong
  color: darken(inherit,20)

【问题讨论】:

  • 这将是一个很棒的功能,但遗憾的是没有,如果不使用变量就无法完成
  • 你试过用变量看看会发生什么吗?
  • 我今天尝试这样做。可悲的是,没有。
  • 很好的问题,我自己一直想知道如何做到这一点。如果我发现了什么,我会插话的。
  • 我的 CSS 愿望清单功能之一是内置。例如,如果一个 box-shadow 声明必须清除所有以前的 box shadow,这很愚蠢。如果您可以覆盖或附加,那就太好了。如果这被添加到规范中,有人告诉我!

标签: sass


【解决方案1】:

继承

没有。 Sass 不“知道”从哪个选择器继承颜色。它必须知道strongbody 的后代。这对你和我来说似乎是一个足够合理的假设,因为strong 不允许在身体之外,但是对于大多数选择器,不能做出这种假设。 Sass 还必须知道其他祖先元素不会发生级联。

ul {
    color: red;
}

ol {
    color: blue;
}

li {
    // which color do I inherit from ????
}

我可以指定哪个选择器我想复制吗?

Sass 也不授予以任何方式访问任何先前声明的变量的值的权限。没有办法指定“比身体的颜色更暗”。 CSS 规则不是对象或映射,不能以任何方式访问。您的案例可能很简单,但考虑一个更复杂的案例,如下所示:

.foo {
    background: mix(white, blue); // fallback for non-rgba browsers
    background: rgba(blue, .5);

    .baz & {
        background: yellow;
    }

    @media (min-width 30em) {
        background: orange;
    }

    @supports (flex-wrap: wrap) {
        background: red;
    }
}

.bar {
    // access which background color from .foo ????
}

那么可以做什么?

你要么需要使用变量,要么它必须是 vanilla CSS 的一个特性才能做你想做的事情。

老式 CSS

某些属性可能会产生使用浏览器支持的东西动态生成/继承的错觉:

ul.one {
  background: white;
}

ul.two {
  background: yellow;
}

ul {
  background: rgba(0, 120, 255, .2);
  padding: 1em;
}
<ul class="one">
  <li><ul>
    <li><ul>
      <li>Foo</li>
    </ul></li>
  </ul></li>
</ul>

<ul class="two">
  <li><ul>
    <li><ul>
      <li>Foo</li>
    </ul></li>
  </ul></li>
</ul>

CSS 变量

生成 CSS 变量几乎与您能够操作继承的属性一样接近。浏览器支持还不是很完善(检查caniuse),但看起来是这样的:

萨斯:

ul {
  --list-color: orange;
  --darker-color: darken(orange, 15%);
  color: var(--list-color);
}

ol {
  --list-color: green;
  --darker-color: darken(green, 10%);
  color: var(--list-color);
}

li {
  background: var(--darker-color);
}

输出:

ul {
  --list-color: orange;
  --darker-color: #b37400;
  color: var(--list-color);
}

ol {
  --list-color: green;
  --darker-color: #004d00;
  color: var(--list-color);
}

li {
  background: var(--darker-color);
}
<ul>
  <li>Foo</li>
</ul>

<ol>
  <li>Bar</li>
</ol>

如果您使用的浏览器支持 CSS 变量,结果应如下所示:

【讨论】:

    【解决方案2】:

    我正在寻找同样的东西,并遇到了这个。您的问题已得到解答,但并未解决问题。

    这里是解决方案:http://codepen.io/monsto/pen/tiokl

    如果你的 HTML 是这样的:

        <div class="main">
          <header class="header">
            <div class="warning">
              <p><strong>Danger,</strong> Will Robinson!</p>
            </div>
          </header>
        </div>
    

    然后使用 SASS 你可以这样做:

    $bg: #f88;
    
    @mixin colorize {
      $bg: darken($bg,15%) !global; // !global flag required for 3.4 or later, remove if using 3.3 or older
      background: $bg;
    }
    
    .warning {
      background: $bg;
      p {
        @include colorize;
        strong {
          @include colorize;
        }
      }
    }
    

    SASS 似乎不知道它的输出结果。因此,inherit 对它毫无意义。您基本上是在要求它在输出之前知道输出是什么。

    但它确实知道它是变量,因为默认情况下,它们的范围很窄。 来自文档:

    变量仅在定义它们的嵌套选择器级别内可用。如果它们是在任何嵌套选择器之外定义的,那么它们在任何地方都可用。

    在 mixins 中的 AND THEN 变量:

    传递给 mixin 的内容块在定义块的范围内进行评估,而不是在 mixin 的范围内。

    这允许上面的 mixin 获取一个在父级别中定义的已知变量,并为当前级别重新定义它并对其子级可用。这就像在多嵌套循环中执行 $x = $x + 1 一样

    TBPH,这反而改变了我对 SASS 的看法。这显然比我想象的要程序化得多。

    【讨论】:

    • 虽然这似乎可行,但我无法通过简单的整数计算来做到这一点,如答案底部所示。然后查看 codepen 示例的编译版本 (codepen.io/monsto/pen/tiokl.css),我们看到每一层都根据初始变量变暗。也许对 SASS 的更新以某种方式阻止了它的工作,但截至今天,这并不像帖子中所解释的那样工作。
    【解决方案3】:

    鉴于一个元素不能有多个相同的属性组合在一起,并且inherit 无法知道当前呈现的状态是什么,您的选择是

    1) 使用 SASS 变量自己跟踪过去的转换:Demo

    .parent {
      $firstTrans: translateX(50%);
      transform: $firstTrans;
    
      .child {
        /* Old followed by new */
        transform: $firstTrans rotate(10deg);
      }
    }
    

    2) 将转换应用到父级(如果需要,可能添加另一个容器):Demo

    3) 使用 Javascript 将当前转换与您要添加的转换相结合(这是确保删除应用于父级的转换的唯一方法):Demo

    注意:由于this meta post,此答案来自合并帖子。

    【讨论】:

    • “你可以做到这一点的唯一方法是如果你使用自定义”不等于“不可能,使用 CSS。”
    • @kilianc 您省略了第二部分:“一个元素不能有两个应用的变换”,然后是如何使用 mixin 来组合它们
    • @kilianc OP 询问为什么他的旋转会破坏初始翻译 - 这个答案表明可以将多个转换组合为一个,并且由于他是在 sass 中执行此操作,因此这是正确的答案。下次在咆哮之前三思而后行。
    • @kilianc 我用一个专门为你的用例更新了答案!也谢谢你,因为我发现了一个逗号错误
    • 我想我知道这里出现了混淆 - 是的,在我的实现中,我使用了包含应用供应商前缀的 compass 转换 mixin。但是,我能够在此答案建议的 combineTransform mixin 解决方案中包含 @include 转换指令,因此此答案与我能够实现飞跃的正确解决方案足够接近。请参阅此小提琴以获取更接近我原始案例的示例:jsfiddle.net/34vgpcrg/1
    【解决方案4】:

    此答案专门针对 darken 函数:一种可能的替代方法是使用 CSS brightness() 过滤器而不是 SASS 的(或 LESS 的)darken() 函数。您基本上需要将颜色包裹在 span 标记内,这样过滤器就不会影响其他元素。

    简单演示:

    .red {color: red}
    .blue {color: blue}
    .green {color: green}
    
    span {
      display: inline-block;
      padding: 1em;
    }
    
    .darken span {
      -webkit-filter: brightness(0.4);
      filter: brightness(0.4);
    }
    <span class="red">Red</span>
    <span class="blue">Blue</span>
    <span class="green">Green</span>
    
    <div class="darken">
      <span class="red">Red</span>
      <span class="blue">Blue</span>
      <span class="green">Green</span>
    </div>

    jsFiddle:https://jsfiddle.net/azizn/hhorhz9s/

    您需要牢记浏览器兼容性,它应该适用于 IE Edge、最新的 Firefox 和 Chrome。请参阅caniuseMDN 了解更多信息。

    在背景变暗的情况下,您可以使用具有不透明度的伪选择器或添加半透明的黑色 PNG 背景图像。

    【讨论】:

    • 这实际上是在现有答案的基础上添加什么新的吗?我们不需要为每一个可能产生变量错觉的 CSS 属性都提供新的答案。
    • @cimmanon 我想是的。我相信darken 将是“继承”中最需要的功能,而这正是 OP 提出这个问题的目的。我的解决方案有更多的浏览器支持,不需要编辑或定义任何变量,它只是动态工作。
    • 除了问题不是变暗,变暗只是给出的例子。认为颜色操作是避免使用变量的唯一可能原因是非常短视的。
    • @cimmanon 我同意你的看法,但我觉得有必要分享一个解决方法或替代方案,因为没有真正操纵 current 值,因为缺乏更好的术语。
    猜你喜欢
    • 1970-01-01
    • 2023-03-08
    • 2018-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-07
    相关资源
    最近更新 更多