【问题标题】:Why does the scale CSS transformation function not affect margin?为什么缩放 CSS 变换功能不影响边距?
【发布时间】:2018-07-18 20:19:03
【问题描述】:

我有一个包含其他几个 div 和元素的 div。

现在我想使用transform: scale(n)

但是当我使用它时,一切看起来都很好,除了 inner div 的边距保持相同大小 但 内部元素宽度改变了


如您所见,div 的大小减半... 但边距是一样的:/

例如代码,您在父级中有一个 div。 此子 div 的边距顶部为 100 像素

如果我更改父级的比例,子级的边距保持不变,但大小不一样。您可以看到孩子在改变比例时没有移动。

.holder {
  background: pink;
  transform: scale(0.5);
}

#son {
  margin-top: 100px;
  padding: 20px;
  background: green;
}
<div class="holder">
  <div id="son">
    dontcare
  </div>
</div>

【问题讨论】:

  • 这对我来说似乎不一样......你能不能把你的代码弄脏
  • 你能分享你的代码吗
  • 谢谢大家添加了一个例子
  • 更新了我的答案,希望现在很清楚;)

标签: css scale margin css-transforms


【解决方案1】:

您的第一个屏幕截图似乎显示transform-orginin 存在问题,默认情况下为50% 50% 0(元素的中心)。将其更改为top left,您的元素将被缩放到左上角,因此 margin 将减小。


关于您共享的代码,这与规模无关,但您面临 ma​​rgin-collapses 问题。儿子的边距与其父级的边距一起折叠,同样的事情会发生,直到这个边距用body 边距折叠。换句话说,边距不再属于缩放元素。

这是带有边距折叠的初始代码:

body {
  background:linear-gradient(to bottom,#000 50%,transparent 0) 0 0/100% 100px;
}

.holder {
  animation:anim 3s infinite linear;
  transform-origin:top;
}

#son {
  margin-top: 100px;
  padding: 20px;
  background: green;
}

@keyframes anim {
  from {
    transform:scale(1);
  }
  to {
    transform:scale(0.3);
  }

}
<div class="holder">
  <div id="son">
    dontcare
  </div>
</div>

如果我们通过添加一个小填充来删除边距折叠,则代码相同:

body {
  background:linear-gradient(to bottom,#000 50%,transparent 0) 0 0/100% 100px;
}

.holder {
  padding-top:1px;
  animation:anim 3s infinite linear;
  transform-origin:top;
}

#son {
  margin-top: 100px;
  padding: 20px;
  background: green;
}

@keyframes anim {
  from {
    transform:scale(1);
  }
  to {
    transform:scale(0.3);
  }

}
<div class="holder">
  <div id="son">
    dontcare
  </div>
</div>

您可以清楚地看到两者之间的区别。在第二个示例中,边距被认为是与第一个不同的比例。


这里有一些有用的链接了解更多详情:

CSS margin terror; Margin adds space outside parent element

https://stackoverflow.com/a/9519933/8620333

What is the point of CSS collapsing margins?

https://css-tricks.com/what-you-should-know-about-collapsing-margins/

【讨论】:

    【解决方案2】:

    tl;博士

    转换与reference box 相关,transform-box property 设置默认为border-box。边框框以边框为界。因此,缩放转换将缩放包括边框在内的所有内容(边框、填充、内容框)。

    长答案

    我将从以下示例开始我的回答:

    button {
      padding: 10px;
      margin: 10px;
    }
    
    .scaled {
      transform: scale(2);
    }
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
    </head>
    <body>
      <button class="default">Button</button>
      <button class="scaled">Button</button>
    </body>
    </html>

    有两个按钮。两者都有 10 像素的填充和 10 像素的边距(以及默认浏览器样式)。第二个按 2 倍缩放。

    在 Firefox 58 中,第一个按钮使用以下属性呈现:

    我们将关注横轴的属性和值:

            34.7167   // Content box width
            10        // Padding left
            10        // Padding right
             7        // Border left
             7     +  // Border right
        ------------
            68.7167
        ------------
    
            10         // Margin left
            10         // Margin right
    

    如果您将除边距之外的所有内容加起来,您将获得元素宽度。保证金不包括在内。这是由于浏览器将元素框定义为内部的所有内容,包括边框。此行为由设置为border-boxbox-sizing 规则指定。

    那么这如何影响scale 变换函数而不缩放边距?

    相对于reference box 发生转换。引用框由transform-box property 定义,默认情况下其值为border-box。因此边框、内边距和内容框尺寸将按 2 缩放,而边距则不会。

    可以在第二个按钮中观察到这种行为,该按钮被缩放:

    再次查看横轴的属性和值:

        34.7167 * 2  =   69.4334   // Content box width
        10      * 2  =   20        // Padding left
        10      * 2  =   20        // Padding right
         7      * 2  =   14        // Border left
         7      * 2  =   14     +  // Border right
    -----------------------------
        68.7167 * 2  =  137.4334
    -----------------------------
    
        10                         // Margin left
        10                         // Margin right
    

    进一步阅读

    【讨论】:

    • 对不起,但这有什么关系?,顺便说一句,这很好解释......但如果你检查他的例子,你会看到边距属于子元素而不是它自己的元素......所以问题是为什么不考虑应该包含在转换中的内边距
    • 顺便检查一下devtools并使用非常小的比例,你会看到maring也被考虑了
    • @TemaniAfif:啊,我没有看到父级上声明的转换规则。谢谢提升。但是我相信我的答案仍然成立,因为“转换是累积的。也就是说,元素在其父坐标系内建立其局部坐标系”,并且局部坐标系“其原点位于由指定的参考框的左上角transform-box 属性。”引用自drafts.csswg.org/css-transforms/#transform-rendering
    • 试试看效果 :) 如果缩放两个元素的容器,内边距会减小。他在我的答案下方有两个主要问题检查以获取更多详细信息;)
    • 如果您点击链接,您会看到transform-box 是一项实验性功能,无法在旧版浏览器上更改。
    【解决方案3】:

    转换确实会影响视觉呈现,但除了影响溢出外,对 CSS 布局没有影响。

    来自W3.org《The Transform Rendering Model》标准

    这里有演示:

    console.log('getComputedStyle:height: ' + getComputedStyle(box).height);
    console.log('getComputedStyle:width: ' + getComputedStyle(box).width);
    #box {
      width: 100px;
      height: 100px;
      background: pink;
      transform: scale(2, 2);
    }
    <div id="box">
      box
    </div>

    但是当我使用它时,一切看起来都很好,除了边距 内部 div 的大小保持相同但内部元素的宽度是 改变了

    你可以使用getComputedStyle发现内部元素宽度没有变化;

    【讨论】:

    • @Bart 就是,实际大小还是和你设置前一样,我试着找文件
    • 但在视觉上它们会改变,这就是问题的目的......你的意思是什么都没有改变,但他说宽度在改变而不是边距所以他在谈论视觉我猜
    • 我猜他认为变换改变了宽度,实际上并没有,一切都保持在原来的位置,只是改变了视觉渲染,这意味着你认为像宽度这样的变化,实际上没有跨度>
    • 是的,但我们正在谈论视觉宽度..我们都知道初始不会改变......但正如你在他的屏幕截图中看到的那样,它会发生变化,因此问题
    • 当然是视觉变化,,,, 你设置了 transform: scale 然后对视觉变化感到惊讶。不知道有什么好惊讶的。
    猜你喜欢
    • 2018-01-23
    • 1970-01-01
    • 2012-05-30
    • 1970-01-01
    • 2013-06-12
    • 2014-09-23
    • 2015-08-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多