52

I'm working on a project that needs to use CSS3 box-shadow property. That's fine, but I have found out that spread size of shadow can't be set to a percentage of parent object.

I fully understand that box-shadow is not additive, thus it doesn't take the size of a parent as a reference.

But given the fact that I need to have a fully responsive site with objects scaling fluidly (not only on breakpoints), but this also poses a problem – I can set shadow to spread property only in absolute units (em or px).

Is there any solution to this? I thought about using inner container (for content) within container (for "shadow" – it's without blur), but this creates another problem – vertical centering of inner container.

Any solution? No jQuery please, just pure CSS.

Vadim Ovchinnikov
  • 13,327
  • 5
  • 62
  • 90
Jozko Remen
  • 591
  • 1
  • 5
  • 5

5 Answers5

24

I have found out that spread size of shadow can't be set to percentage of parent object

True. But you can set font-size on the parent object, then define the object size in ems, and use the same ems to define the box-shadow size.

Or, if your parent object happens to be the window, you can use viewport units: vw and vh.

mik01aj
  • 11,928
  • 15
  • 76
  • 119
  • Great solution (hack really) I usee it like this: (inline) font-size = (ball-radius / 10) and class-css box-shadow:inset -2em -5em 5em rgba(0,0,0,.6) – T4NK3R Sep 17 '17 at 18:07
  • 1
    This should be the accepted answer IMO. Others do not fulfil the requests. – RSinohara Nov 26 '18 at 13:17
  • this is such a horribly messy solution. I mean, I guess I'll do this, but it absoutely should not be the case that box-shadow sizes are being controlled by font size. Sometimes I wish we could replace css with something made by humans, not aliens from a strange planet that have no sense of human psychology – John Miller Sep 09 '22 at 03:08
  • Well, sure, just in 2015 it was literally the only workable solution. There might be better options now. – mik01aj Sep 27 '22 at 02:48
8

If you're after an inset box-shadow you could use a radial-gradient background to mimic the behaviour. So instead of -

box-shadow: inset 0 0 100% #000;

You would use -

background: radial-gradient(ellipse at center, rgba(0,0,0,0) 0,rgba(0,0,0,1) 100%);

Support: FF16+, IE10+, Safari 5.1+

I can't find any definitive answer on when Chrome started supporting the property, but my current version (39.0.2171.65) definitely supports it.

ColorZilla is a pretty useful tool for generating radial (among other) gradients along with the necessary prefixes if you decide to go down this route.

shakyjake
  • 357
  • 4
  • 10
4

Have you tried using the rem unit (root em unit)? I believe you can use this to make it scale fluidly.

The rem unit is always relative to the root html element, so it will scale accordingly and you don't have to worry about inner containers or anything like that. It also has pretty broad browser support at this point.

I use it on my projects to make them more responsive, but always follow a parameter already defined by px or em so that it fails gracefully just in case. For example:

font-size: 14px; font-size: 1.4rem;

Here's a great article explaining everything you need to know about this unit: http://snook.ca/archives/html_and_css/font-size-with-rem

alex
  • 954
  • 2
  • 9
  • 11
2

If the element has a defined width (except for a percentage width), you can create a custom property for the width and then use the custom property with the calc() function for box shadow.

For example, the CSS code below makes the "spread radius" of box shadow 20% of the div's width:

div {
    --width: 100px;
    width: var(--width);
    box-shadow: 0 0 0 calc(var(--width) * 0.2) #aaa;
}
Ian Y.
  • 2,293
  • 6
  • 39
  • 55
1

Do you want the box-shadow to scale with the width of the container or with the height of the container? You can't really specify a height and width of your shadow, only a spread. So if your container shrinks by 10% in width but does not shrink in height then your shadow will shrink by 10% (if it were possible), i.e. your shadow's height would scale even though it probably shouldn't.

If you want the box-shadow to actually scale correctly with regards to height and width, you would have to create multiple shadows - one for height, one for width.

However, you will never be able to scale the actual shadow, only the container of the shadow. So you would create a container inside your main container and then give it negative margins and attach the box-shadow. However, you will soon notice that your shadow actually grows instead of shrinking when you scale the container down.

Seems a bit overkill to try and scale something which isn't scalable without using media queries or jQuery.

However, if you're looking for scalable borders, i.e. box-shadow without blur :P, then look no further:

http://jsfiddle.net/925r2/3/

<style>
    * {
        margin: 0;
        padding: 0;
        border: 0;
        box-sizing: border-box;
    }

    .wrapper {
        position: relative;
        margin: 100px auto 0;
        width: 80%;         /* .content width */
        height: 400px;      /* .content height */
    }

    .content {
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        background: #fff;   /* .content background */
    }

    .shadow {
        position: absolute;
        top: -10%;          /* .content shadow top height */
        right: -5%;         /* .content shadow right width */
        bottom: -10%;       /* .content shadow bottom height */
        left: -5%;          /* .content shadow left width */
        background: #000;   /* .content shadow, unfortuntely no blur effect */
    }
</style>

<div class="wrapper">
    <div class="shadow"></div>
    <div class="content">This is your content</div>
</div>
caweidmann
  • 396
  • 2
  • 12
  • 1
    This does not answer the question of using `box-shadow` with percentage units – Zach Saucier Jul 11 '14 at 22:52
  • 5
    Simply, you cannot use percentages on `box-shadow`. Pretty much any answer will be a hack that uses some other containers to achieve the effect. So either the question should be posted to W3C and browser vendors or if the poster is looking for a solution this is a solution that is a shadow, percentage based without a blur effect. – caweidmann Jul 12 '14 at 08:07