如何调试CSS calc()值?

21

我有相对复杂的公式,例如 transform: scale(var(--image-scale)) translateY(calc((1px * var(--element-height) * (var(--image-scale) - 1)) / 2 * var(--scrolled-out-y)))

如何调试计算出的值? 此外,是否有一种方法可以验证/突出显示公式错误?

我尝试将输出放在伪元素中,但没有成功。

    position: fixed;
    display: block;
    left:0;
    right: 0;
    background: yellow;
    padding: 5px;
    z-index: 100;
    content: calc((1px * var(--element-height) * (var(--image-scale) - 1)) / 2 * var(--scrolled-out-y));

我发现的唯一方法是将计算的部分放到未使用的数值属性中,例如下面的gif中的 background-position-x,这样它将在计算选项卡中显示计算值——虽然有用,但并不是很方便(请注意,随着页面滚动,background-position-x 会发生变化):

enter image description here

var sc = ScrollOut({
    cssProps: true
  })
  const results = Splitting();

  var parallaxedElements = document.querySelectorAll('.section');

  document.addEventListener('scroll', function(e) {
    parallaxedElements
    Array.from(parallaxedElements).forEach((el) => {
      var bcr = el.getBoundingClientRect();
      if (bcr.y < 0 && Math.abs(bcr.y) <= bcr.height) {
        el.style.setProperty("--scrolled-out-y", Math.round(Math.abs(bcr.y) * 10000 / bcr.height) / 10000);
      }
    });

  })
@import url("https://fonts.googleapis.com/css?family=Roboto");
  html {
    scroll-behavior: smooth;
  }
  
  body {
    font-family: "Roboto";
    font-size: 14px;
    line-height: 1.4;
    scroll-behavior: smooth;
  }
  
  .section {
    position: relative;
    background-attachment: fixed;
    z-index: 1;
    --image-scale: 1.2;
    --scrolled-out-y: 0;
  }
  
  .section__background {
    position: -webkit-sticky;
    position: sticky;
    top: 0;
    width: 100%;
    height: 100vh;
    overflow: hidden;
  }
  
  .section__background:after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    top: 0;
    z-index: 1;
    background: linear-gradient(to bottom, black, 100% white);
    background: rgba(0, 0, 0, 0.4);
    opacity: calc(1 + ((var(--viewport-y) * 1.5)));
  }
  
  .section__background>img {
    height: 150vh;
    width: 100%;
    object-fit: cover;
    position: absolute;
    left: 0;
    top: 0px;
    user-select: none;
    transform: scale(var(--image-scale)) translateY(calc((-1px * var(--element-height) * (var(--image-scale) - 1)) * var(--scrolled-out-y)));
  }
  /* .indicator:after {
        position: fixed;
        display: block;
        left: 0;
        right: 0;
        background: pink;
        padding: 5px;
        z-index: 100;
        content: calc((1px * var(--element-height) * (var(--image-scale) - 1)) / 2 * var(--scrolled-out-y));
    } */
  
  .section__container {
    padding-bottom: 50vh;
    overflow: hidden;
    align-items: flex-start;
    position: relative;
    z-index: 4;
  }
  
  .section__heading {
    color: #fff;
    text-transform: uppercase;
    font-size: 45px;
    line-height: 1.2;
    font-weight: 800;
    letter-spacing: 8px;
    margin: 0;
    overflow: hidden;
    position: relative;
    padding-bottom: 50px;
    margin-bottom: 50px;
  }
  
  .section__heading:after {
    content: "";
    position: absolute;
    top: 200px;
    left: 0;
    right: 0;
    height: 2px;
    transform: translateX(calc(var(--scrolled-out-y) * 100% - 70%));
    background: #b38c6b;
  }
  
  .section__content {
    display: flex;
    color: white;
    flex-direction: column;
  }
  
  .section__content p+p {
    margin-top: 20px;
  }
  
  .splitting {
    --char-percent: calc(var(--char-index) / var(--char-total));
  }
  
  .splitting .char {
    display: inline-block;
    opacity: calc(1 + ((var(--viewport-y) * 1.5) - var(--char-percent)));
  }
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css'>
<link rel='stylesheet' href='https://unpkg.com/splitting/dist/splitting.css'>

<section data-scroll class="section section-1">
  <div class="section__background">
    <div class="indicator"></div>
    <img src="https://picsum.photos/1920/1079" alt="placeholder image" />
  </div>
  <div class="container section__container">
    <div class="row">
      <div class="title-block col-md-6 d-flex">
        <h1 data-scroll data-splitting class="section__heading">
          Why <br>CSS <br>matters
        </h1>
      </div>
      <div class="col-md-6 d-flex">
        <div class="section__content">
          <p>
            MThe ability to use variables in CSS is a useful and powerful feature that web developers have long been asking for. Well, it has finally arrived, and it’s awesome!
          </p>
          <p>
            In this article we’ll look at the history, importance, and use of CSS variables, and how you can leverage them to make your CSS development and maintenance faster and easier.
          </p>
          <p>
            Keep reading and you will understand why.
          </p>
          <div>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>

<section data-scroll class="section section-2">
  <div class="section__background">
    <img src="https://picsum.photos/1920/1081" alt="placeholder image" />
  </div>
  <div class="container section__container">
    <div class="row">
      <div class="title-block col-md-6 d-flex">
        <h1 data-scroll data-splitting class="section__heading">
          Why <br>CSS <br>matters
        </h1>
      </div>
      <div class="col-md-6 d-flex">
        <div class="section__content">
          <p>
            MThe ability to use variables in CSS is a useful and powerful feature that web developers have long been asking for. Well, it has finally arrived, and it’s awesome!
          </p>
          <p>
            In this article we’ll look at the history, importance, and use of CSS variables, and how you can leverage them to make your CSS development and maintenance faster and easier.
          </p>
          <p>
            Keep reading and you will understand why.
          </p>
          <div>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>

<section data-scroll class="section section-3">
  <div class="section__background">
    <img src="https://picsum.photos/1920/1082" alt="placeholder image" />
  </div>
  <div class="container section__container">
    <div class="row">
      <div class="title-block col-md-6 d-flex">
        <h1 data-scroll data-splitting class="section__heading">
          Why <br>CSS <br>matters
        </h1>
      </div>
      <div class="col-md-6 d-flex">
        <div class="section__content">
          <p>
            MThe ability to use variables in CSS is a useful and powerful feature that web developers have long been asking for. Well, it has finally arrived, and it’s awesome!
          </p>
          <p>
            In this article we’ll look at the history, importance, and use of CSS variables, and how you can leverage them to make your CSS development and maintenance faster and easier.
          </p>
          <p>
            Keep reading and you will understand why.
          </p>
          <div>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>


<section data-scroll class="section section-4">
  <div class="section__background">
    <img src="https://picsum.photos/1920/1083" alt="placeholder image" />
  </div>
  <div class="container section__container">
    <div class="row">
      <div class="title-block col-md-6 d-flex">
        <h1 data-scroll data-splitting class="section__heading">
          Why <br>CSS <br>matters
        </h1>
      </div>
      <div class="col-md-6 d-flex">
        <div class="section__content">
          <p>
            MThe ability to use variables in CSS is a useful and powerful feature that web developers have long been asking for. Well, it has finally arrived, and it’s awesome!
          </p>
          <p>
            In this article we’ll look at the history, importance, and use of CSS variables, and how you can leverage them to make your CSS development and maintenance faster and easier.
          </p>
          <p>
            Keep reading and you will understand why.
          </p>
          <div>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>

<section data-scroll class="section section-5">
  <div class="section__background">
    <img src="https://picsum.photos/1920/1084" alt="placeholder image" />
  </div>
  <div class="container section__container">
    <div class="row">
      <div class="title-block col-md-6 d-flex">
        <h1 data-scroll data-splitting class="section__heading">
          Why <br>CSS <br>matters
        </h1>
      </div>
      <div class="col-md-6 d-flex">
        <div class="section__content">
          <p>
            MThe ability to use variables in CSS is a useful and powerful feature that web developers have long been asking for. Well, it has finally arrived, and it’s awesome!
          </p>
          <p>
            In this article we’ll look at the history, importance, and use of CSS variables, and how you can leverage them to make your CSS development and maintenance faster and easier.
          </p>
          <p>
            Keep reading and you will understand why.
          </p>
          <div>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>


<section data-scroll class="section section-6">
  <div class="section__background">
    <img src="https://picsum.photos/1920/1085" alt="placeholder image" />
  </div>
  <div class="container section__container">
    <div class="row">
      <div class="title-block col-md-6 d-flex">
        <h1 data-scroll data-splitting class="section__heading">
          Why <br>CSS <br>matters
        </h1>
      </div>
      <div class="col-md-6 d-flex">
        <div class="section__content">
          <p>
            MThe ability to use variables in CSS is a useful and powerful feature that web developers have long been asking for. Well, it has finally arrived, and it’s awesome!
          </p>
          <p>
            In this article we’ll look at the history, importance, and use of CSS variables, and how you can leverage them to make your CSS development and maintenance faster and easier.
          </p>
          <p>
            Keep reading and you will understand why.
          </p>
          <div>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>
<script src='https://unpkg.com/scroll-out/dist/scroll-out.min.js'></script>
<script src='https://unpkg.com/splitting@1.0.0/dist/splitting.js'></script>


1
你能发布更多真实的CSS和HTML代码吗?这不是所有运行所需的代码。 - Raymond Nijland
2
除了使用脚本选择值并检查其是否正确计算,今天没有其他调试方法。请注意,CSS不是一种编程语言。 - Asons
分享一下你是如何定义变量的...并且在内容中使用它是错误的。 - Temani Afif
@TemaniAfif已添加完整代码,以便您进行实验。 - godblessstrawberry
1
目前这让我有点疯狂,没有办法调试这个问题。 - Damon
显示剩余2条评论
3个回答

8

有没有一种方法可以验证/突出公式错误?

您需要检查是否在定义公式时违反了任何规则。这是来自规范的内容:

在每个运算符处,左侧和右侧参数的类型都会检查这些限制。如果兼容,则类型解析如下所述(以下为简单起见忽略运算符的优先级规则):
- 在 +- 中,请检查两侧是否具有相同的类型,或者一侧是 <number>,另一侧是 <integer>。如果两侧都是相同的类型,则解析为该类型。如果一侧是 <number>,另一侧是 <integer>,则解析为 <number>。 - 在 * 中,请检查至少一侧是否为 <number>。如果两侧都是 <integer>,则解析为 <integer>。否则,解析为另一侧的类型。 - 在 / 中,请检查右侧是否为 <number>。如果左侧为 <integer>,则解析为 <number>。否则,解析为左侧的类型。
如果运算符未通过上述检查,则表达式无效。
起初听起来可能有点复杂,但规则很简单,我们可以用简单的话来重新表述它们:
  • 你不能添加/减去两种不同类型(5px + 5s没有意义)。
  • 你只能用数字相乘(5px * 5px没有意义,也不等于25px)。
  • 你只能用不为0的数字相除(5px / 5px没有意义,也不等于11px)。

如果你没有违反这些规则,那么你的公式是正确的。让我们不要忘记另一个重要的语法规则:

此外,在+和-操作符的两侧需要空格。(*和/操作符可以在它们周围使用而不需要空格。)


考虑以下情况,您只需要确定您的CSS变量是数字/整数还是使用类型(长度、频率、角度或时间)定义的。如果未定义或包含字符串值,则calc()将无效。
有关更多详细信息和更精确的解释,请查看规范:https://drafts.csswg.org/css-values-3/#calc-type-checking

如何调试计算值?

要检查计算值,我认为没有办法,因为calc()的计算值取决于使用它的属性(即位置)而可能不同。换句话说,在属性中使用之前,最终值是不存在的。

我们可能认为有些公式很简单,比如calc(5px + 5px),将始终计算为10px,但其他公式则更加困难。例如calc(5px + 50%),其中%会根据属性而表现得不同。考虑到这一点,浏览器在使用属性之前永远不会计算该值。

即使使用JS,您也无法获得您想要调试的最终值;您只能获取属性的计算值:

var elem = document.querySelector(".box");
var prop = window.getComputedStyle(elem,null).getPropertyValue("--variable");
var height = window.getComputedStyle(elem,null).getPropertyValue("height");
console.log(prop);
console.log(height);
.box {
  --variable: calc(5px + 5px);
  height:var(--variable);
}
<div class="box"></div>


21
这个回答解释了如何避免创建无效的CSS,但没有展示如何实际“调试计算值”,也没有说明是否有“验证/突出显示公式错误”的方法,所以我认为它并没有回答问题。 - Asons
1
@LGSon 我特别回答这部分“验证/突出显示公式错误的方法”...通过给出我们的规则,我们有方法来判断公式是否有效。因此,如果cacl()无效,则公式是错误的,否则它是正确的。 - Temani Afif
4
“遵循语法准则”和“强调其错误”之间存在很大的区别。不要误解我,这是一篇不错的文章,但它没有回答问题。 - Asons
@LGSon 我没有误解你的意思 ;) 但我认为这可能有助于调试,因为规则并不总是对某些人直观。我经常看到人们做 height/width,认为它会在没有逻辑将像素除以像素或将像素乘以像素的情况下直观地工作。因此,了解这一点将有助于识别微不足道的错误...我还为另一个问题(如何调试计算值?)添加了答案。 - Temani Afif
1
@LGSon,这不是关于“CSS无法做到那样”的问题。而是要理解CSS不是C++或任何类似的语言。因此,像我们在其他语言中调试值一样思考是错误的,因为它不会以同样的方式运行。这就是我们需要理解的,以便理解在CSS变量中单独定义calc()没有意义,直到它与属性一起使用。[我将尝试编辑并表达这个意思] - Temani Afif
显示剩余5条评论

2

所以要实际调试 CSS 变量,您可以使用我下面添加的助手类。

然后在控制台中,您可以这样设置和读取变量:

CssVariables.setRootVar('--column-max-width', 'calc((90vw - var(--zoomer-width)) / (var(--columns-shown) + 1))');
console.log('width:', CssVariables.getRootVar("--column-max-width"));

请注意,当您读取一个变量var(--)时,它已经被解析。
当公式无效时,您可能会在控制台上收到警告。
CssVariables.setRootVar('--column-max-width', 'calc(123px - var(123))');
// -> invalid value, declaration skipped

当你例如使用不存在的变量时,读取时将获得空字符串。

CssVariables.setRootVar('--column-max-width', 'calc(123px - var(--wtf))');
console.log('width:', CssVariables.getRootVar("--column-max-width"));
// -> width: <empty string>

CssVariables助手

/**
 * CSS variables helper.
 */
class CssVariables {
    /**
     * Get :root variable.
     * @param {String} name Name of CSS var. e.g. "--columns-shown".
     * @returns {String} Current value.
     */
    static getRootVar(name) {
        return this.getVar(document.documentElement, name);
    }
    /**
     * @see #getRootVar
     */
    static getVar(element, name) {
        return window.getComputedStyle(element, null).getPropertyValue(name);
    }
    /**
     * Set :root variable.
     * @param {String} name Name of CSS var. e.g. "--columns-shown".
     * @param {String} value New value. Should be a strin, but numbers would work as well.
     */
    static setRootVar(name, value) {
        this.setVar(document.documentElement, name, value);
    }
    /**
     * @see #setRootVar
     */
    static setVar(element, name, value) {
        element.style.setProperty(name, value);
    }
}

// if you are working with modules
//export { CssVariables }

这个答案的核心非常有用:window.getComputedStyle(element, null).getPropertyValue(name) - Gabriel Grant

0
获取完全展开的CSS calc值,您可以执行以下操作

window.getComputedStyle(element).getPropertyValue(name)

(在您的具体示例中,name = 'transform'
请注意,这并不会实际进行计算,而是展开各种CSS变量,以便您可以看到正在计算的内容。当中间变量在不同上下文中可能设置不同时,这非常有帮助。
请注意,如果您要访问的属性位于伪元素上,您可以执行以下操作: window.getComputedStyle(baseElement, nameOfPseudoElementAsString).getPropertyValue(name)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接