计算一个元素的阴影宽度

3

您可能知道,box-shadow不是box-model的一部分。那么计算添加到元素的box-shadow宽度的好方法是什么?

更新:我需要知道元素的总宽度,包括阴影宽度。


为什么你需要知道这个宽度? - BoltClock
3个回答

4

你可以简单地添加一个与 box-shadow 相等的 margin。例如:

box-shadow: 0 0 10px #008800;
margin: 10px;

如果您在盒子阴影中使用X和Y偏移量,请将该值添加到阴影的长度中。例如:
box-shadow: 5px 5px 10px #080;
margin: 5px 15px 15px 5px;

这里的偏移量是5像素,再加上10像素的长度。在扩展的情况下,我们可以继续添加边距值来考虑这一点。

box-shadow: 5px 5px 10px 7px #080;
margin: 12px 21px 21px 12px;

使用边距可以避免阴影与页面上其他对象重叠。

精确的宽度会因浏览器而异。每个浏览器呈现的阴影都不同。如果必须为对象提供硬计算,我猜它可能是这样的(参考CSS属性)

box-shadow: h-shadow v-shadow blur spread color;

盒模型偏移将会是:
top = (spread - v_shadow + 0.5*blur)
right = (spread + h_shadow + 0.5*blur)
bottom = (spread + v_shadow + 0.5*blur)
left = (spread - h_shadow + 0.5*blur)

模糊系数是一个估计值,可能需要稍作调整。个人建议不要使用偏移量,但此处仅为演示其使用位置。

这里有一个jsfiddle示例,以查看它的效果http://jsfiddle.net/YvqZV/4/


嗨,谢谢。但是模糊大小并不是围绕元素扩展的实际大小。请参阅此文章:http://msdn.microsoft.com/en-us/hh867550.aspx。 - bingjie2680
是的,我们可以包括展开值。再次,这将是简单的加法。模糊大约是给定值的50%。由于它因浏览器而异,因此没有确切的计算方法。至于您最初的问题,我认为将计算添加到边距是修改框模型的最佳方法。您是否还有其他更具体的问题需要回答? - samuel.molinski
我需要知道一个元素的总宽度,包括阴影宽度。 - bingjie2680
看看这些更改是否满足了你的疑虑。 - samuel.molinski
嗨,谢谢。最终我把它们加在一起了,所以对我来说可以工作了。我不需要精确的总长度,但需要知道最小长度。感谢您的帮助。 - bingjie2680

1

我只是在扩展@samuel.molinski的答案,创建一个完整的函数,该函数接受一个框阴影并返回宽度。

function getBoxShadowWidths(boxShadow) {
  // not supporting multiple box shadow declarations for now
  if ((boxShadow.match(/(rgb|#)/g) || []).length > 1) {
    return false;
  }

  const regEx = /(\d(?=(px|\s)))/g;
  const matches = [];

  // box-shadow can have anywhere from 2-4 values, including horizontal offset, vertical offset,
  // blur, and spread. Below finds each one and pushes it into an array (regEx.exec when used in succession
  // with a global regex will find each match.
  let match = regEx.exec(boxShadow);
  while (match != null) {
    matches.push(match[0]);
    match = regEx.exec(boxShadow);
  }

  // default blur & spread to zero px if not found by the regex
  const [hOffset = 0, vOffset = 0, blur = 0, spread = 0] = matches.map(parseFloat);

  // calculate approximate widths by the distance taken up by each side of the box shadow after normalizing
  // the offsets with the spread and accounting for the added distance resulting from the blur
  // See https://msdn.microsoft.com/en-us/hh867550.aspx - "the blurring effect should approximate the
  // Gaussian blur with a standard deviation equal to HALF of the blur radius"
  const top = spread - vOffset + 0.5 * blur;
  const right = spread + hOffset + 0.5 * blur;
  const bottom = spread + vOffset + 0.5 * blur;
  const left = spread - hOffset + 0.5 * blur;

  return { top, right, bottom, left };
}

0

感谢 @Joey 提供的函数。我增加了对多个值的支持:

function getBoxShadowWidths(boxShadowValues) {
  const regEx = /(\d(?=(px|\s)))/g
  const widths = { top: 0, right: 0, bottom: 0, left: 0 }

  boxShadowValues.split(/\s*,\s*/).forEach(boxShadowValue => {
    const matches = []

    // box-shadow can have anywhere from 2-4 values, including horizontal offset, vertical offset, blur, and spread.
    // Below finds each one and pushes it into an array (regEx.exec when used in succession with a global regex will find each match.
    let match = regEx.exec(boxShadowValue)
    while (match != null) {
      matches.push(match[0])
      match = regEx.exec(boxShadowValue)
    }

    // default blur & spread to zero px if not found by the regex
    const [hOffset = 0, vOffset = 0, blur = 0, spread = 0] = matches.map(parseFloat)

    // calculate approximate widths by the distance taken up by each side of the box shadow after normalizing
    // the offsets with the spread and accounting for the added distance resulting from the blur
    // See https://msdn.microsoft.com/en-us/hh867550.aspx - "the blurring effect should approximate the
    // Gaussian blur with a standard deviation equal to HALF of the blur radius"
    const actualWidths = {
      top: spread - vOffset + 0.5 * blur,
      right: spread + hOffset + 0.5 * blur,
      bottom: spread + vOffset + 0.5 * blur,
      left: spread - hOffset + 0.5 * blur,
    }

    Object.keys(actualWidths).forEach(side => {
      widths[side] = Math.max(widths[side], actualWidths[side])
    })
  })

  return widths
}

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