如何调试 CSS calc() 值?

Posted

技术标签:

【中文标题】如何调试 CSS calc() 值?【英文标题】:How do I debug CSS calc() value? 【发布时间】:2019-04-21 04:41:35 【问题描述】:

我有相对复杂的公式,例如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));

我发现的唯一方法是将部分计算放到未使用的数字属性中,例如background-position-x 在下面的 gif 上,因此它将在计算选项卡上显示计算值 - 有用但不是很方便(注意 background-position-x 在页面滚动时更改):

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"  />
  </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"  />
  </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"  />
  </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"  />
  </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"  />
  </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"  />
  </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>

【问题讨论】:

你能发布一些更真实的css和html代码吗?这并不是让它运行所需的全部代码.. 除了使用脚本选择值并检查它是否正确计算之外,没有办法(今天)进行调试。请注意,CSS 不是一种编程语言。 分享你是如何定义变量的......并且在内容中这样使用是错误的 @TemaniAfif 添加了完整代码,以便您进行实验 它目前让我有点发疯,没有办法调试这个.. 【参考方案1】:

所以要实际调试 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 

【讨论】:

【参考方案2】:

有没有办法验证/突出显示公式错误?

在定义公式时,您需要检查是否违反了任何规则。来自the specification:

在每个运算符处,检查左右参数的类型是否存在这些限制。如果兼容,则类型解析如下所述(为简单起见,以下忽略运算符的优先规则):

+-,检查两侧是否具有相同的类型,或者一侧是&lt;number&gt;,另一侧是&lt;integer&gt;。如果双方是同一类型,则解析为该类型。如果一侧是&lt;number&gt;,另一侧是&lt;integer&gt;,请解析为&lt;number&gt;。 在*,检查至少一侧是&lt;number&gt;。如果双方都是&lt;integer&gt;,则解析为&lt;integer&gt;。否则,解析为对方的类型。 在/,检查右侧是否为&lt;number&gt;。如果左侧是&lt;integer&gt;,则解析为&lt;number&gt;。否则,解析为左侧的类型。

如果运算符没有通过上述检查,则表达式无效

一开始可能听起来有点复杂,但规则很简单,我们可以用简单的话重写如下:

不能加/减两种不同的类型(5px + 5s 没有意义)。 只能与数字相乘(5px * 5px 没有意义,不等于25px)。 只能用不是0 的数除(5px / 5px 没有意义,不等于11px)。

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

此外,+ 和 - 运算符的两边都需要空格。 (可以使用 * 和 / 操作符,它们周围没有空格。)


考虑到这一点,您只需要确定您的 CSS 变量是数字/整数还是使用类型(长度、频率、角度或时间)定义。如果未定义或包含字符串值,则 calc() 将无效。

查看规范以获取更多详细信息和更准确的解释:https://drafts.csswg.org/css-values-3/#calc-type-checking


如何调试计算值?

要检查计算的值,我认为没有办法,因为 calc() 的计算值可能会有所不同,具体取决于您使用它的位置(哪个属性)。换句话说,final 值直到在属性中使用后才存在。

我们可能认为有些公式是微不足道的,例如 calc(5px + 5px),它总是会计算到 10px,但其他公式会更难。就像calc(5px + 50%) 一样,% 的行为会因属性而异。考虑到这一点,浏览器将永远不会计算该值,直到它在属性中使用。

即使使用 JS,你也无法获得想要调试的 final 值;你只能得到属性的计算值:

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);
&lt;div class="box"&gt;&lt;/div&gt;

【讨论】:

这个答案解释了如何不创建无效的CSS,它没有显示如何实际“调试计算值”,也没有告诉是否有”一种验证/突出显示公式错误的方法”,所以恕我直言,它没有回答问题。 @LGSon 我正在专门回答这部分验证/突出显示公式错误的方法 ...通过给出我们的方式规则看看公式是否有效。所以如果 cacl() 无效则公式错误,否则正确 “遵循语法指南”和“突出其错误”有很大的不同。别误会我的意思,虽然没有回答问题,但这是一本好书。 @LGSon 我没有误会你的意思;)但我认为这可能有助于调试,因为对于某些人来说规则并不总是直观的。我总是看到人们在做height/width 认为它会直观地工作在没有逻辑将像素与像素相除或像素与像素相乘的情况下。所以知道这将有助于识别微不足道的错误......我还添加了另一个问题的答案(如何调试计算值?) @LGSon 这与 CSS 无法做到这一点 无关。这是关于理解 CSS 不是 C++ 或任何类似语言。因此,像我们对其他语言所做的那样考虑调试值是一种错误的想法,因为它的行为方式并非如此。为了理解在 CSS 变量中单独定义的 calc() 在与属性一起使用之前没有任何意义,我们需要了解这一点。 [将尝试编辑这样说]

以上是关于如何调试 CSS calc() 值?的主要内容,如果未能解决你的问题,请参考以下文章

css3 calc()

如何将 CSS calc() 与继承一起使用?

如何在 calc() 表达式中获取 CSS 变量的负值?

如何防止 Less 尝试编译 CSS calc() 属性?

css中计算值width: calc()

CSS3 calc() 验证:值错误:宽度解析错误 [重复]