Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

compute box-shadow width for an element

Tags:

css

As you may know that box-shadow is not a part of box-model. so what could be a good way to compute the width of box-shadow that adds to an element?

Update: I need to know the total width of an element, including the shadow width.

like image 945
bingjie2680 Avatar asked May 01 '26 07:05

bingjie2680


2 Answers

well you could simply add a margin equal to the box-shadow. For example:

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

in the case you use the X and Y offsets on the box-shadow use add that value to the length of the shadow. Example:

box-shadow: 5px 5px 10px #080;
margin: 5px 15px 15px 5px;

here the offset is 5px, plus the 10px length. In the case of the spread we can continue to add to the margin values to take this into consideration.

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

using the margin will keep the shadow from overlapping other objects on the page.

Exact width will differ from browser to browser. Each renders the shadows different. If i have to give a hard calculation for the object I guess it would be the something like this (the css property for reference)

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

The box model offsets would be

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)

The coefficient of the blur is a estimate, it may need to be adjusted slightly. Personally I prefer to not use the offset, but is here to show where it would be used

here is a jsfiddle to see it in action http://jsfiddle.net/YvqZV/4/

like image 94
samuel.molinski Avatar answered May 02 '26 20:05

samuel.molinski


Just extending @samuel.molinski's answer by creating a complete function that takes a box shadow and returns the widths.

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 };
}
like image 30
Joey Grisafe Avatar answered May 02 '26 22:05

Joey Grisafe



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!