I am trying to replicate canvas frame effect on paintings on images using CSS.
I can do shadows and rounded corners but I couldn't figure out how to do the 3D effect of "rounded/wrapping sides".
My actual is left image while I am trying to replicate the effect of the right one. Please ignore the background of the expected image.
Any help?
Thanks.
.image{
display:flex;
justify-content:space-evenly;
}
#actual {
border-radius: 4px;
box-shadow: 20px 4px 10px rgba(0,0,0,0.35), 40px 8px 10px rgba(0,0,0,0.15);
}
<div class="image">
<img id="actual" src="http://lorempixel.com/output/cats-q-c-640-480-10.jpg">
<img id="expected" src="https://i.imgur.com/XD8Vdvv.jpg">
</div>
You can approximate it using inset shadow:
.image{
display:inline-block;
border-radius: 4px;
box-shadow:
-2px -2px 1px rgba(0,0,0,0.5) inset,
20px 4px 10px rgba(0,0,0,0.35),
40px 8px 10px rgba(0,0,0,0.15);
width:320px;
height:240px;
margin:10px;
background:url(http://lorempixel.com/output/cats-q-c-640-480-10.jpg) center/cover;
}
<div class="image">
</div>
Just want to get creative with box-shadow layering... Cheers;
figure {
display: block;
margin: 1rem auto;
height: 10rem;
width: 10rem;
border: gray 1px solid;
border-radius: 3px;
background: lightgray url('https://i.stack.imgur.com/BVW9D.jpg') no-repeat center center;
background-size: cover;
box-shadow: 2px 2px 0 gray,
3px 3px 4px rgba(0,0,0,.9),
6px 6px 12px 4px rgba(0,0,0,.25),
0 0 14px 4px rgba(0,0,0,.15);
}
<figure></figure>
I have two divs next to the each other which background color is white. http://jsfiddle.net/J5ZXt/ is link to code. I want that two divs look like one element, so I need to remove a part of shadow. Any ideas?
Yes, it is possible. Simply cover it up with :before:
/* Add relative positioning */
#two {
position:relative;
}
/* Add :before element to cover up shadow */
#two:before {
background:white;
display:block;
content:".";
font-size:0;
width:4px;
height:100px;
position:absolute;
left:-4px;
top:0;
}
/* Existing styles */
#one {
width: 100px;
height: 100px;
background: #FFF;
-moz-box-shadow: 0 0 3px 1px rgba(0,0,0,0.3);
-webkit-box-shadow: 0 0 3px 1px rgba(0,0,0,0.3);
box-shadow: 0 0 3px 1px rgba(0,0,0,0.3);
float:left;
}
#two {
width: 100px;
height: 300px;
background: #FFF;
-moz-box-shadow: 0 0 3px 1px rgba(0,0,0,0.3);
-webkit-box-shadow: 0 0 3px 1px rgba(0,0,0,0.3);
box-shadow: 0 0 3px 1px rgba(0,0,0,0.3);
float:left;
}
<div id="one"></div>
<div id="two"></div>
This is the best I could get within a couple of minutes, I think it does the job. The best thing is its simplicity (only 3 edits to your css)
Position D1's shadow so the right edge has a negative value (-4px is enough to hide it)
Give both divs relative positioning so we can control their stacking order.
Give D1 a higher z-index than D2 so it masks the top part of D2's shadow.
#one {
width: 100px;
height: 100px;
background: #FFF;
-moz-box-shadow: -4px 0 3px 1px rgba(0,0,0,0.3);
-webkit-box-shadow: -4px 0 3px 1px rgba(0,0,0,0.3);
box-shadow: -4px 0px 3px 1px rgba(0,0,0,0.3);
float:left;
position: relative;
z-index: 20;
}
#two {
width: 100px;
height: 300px;
background: #FFF;
-moz-box-shadow: 0 0 3px 1px rgba(0,0,0,0.3);
-webkit-box-shadow: 0 0 3px 1px rgba(0,0,0,0.3);
box-shadow: 0 0 3px 1px rgba(0,0,0,0.3);
float:left;
z-index: 5;
position: relative;
}
Pure CSS - no
You could always try absolutely position a div above it, as in this example
The ::before solution does not work in all browsers
Because I hate to be outdone and tend to be a perfectionist, I came up with an answer that doesn't rely on a specific height for #one--it just has to be shorter than #two (which is also the case for the currently accepted answer). It also does not have the downside of a gap or larger shadow on one side of #one.
Note: This answer also gives the possibility for a curved corner via border-radius. Simply add border-radius:4px; to #one:after to see the result.
jsFiddle Example
New CSS
<style type="text/css">
#one {
width: 100px;
height: 200px;
background: #fff;
float:left;
position:relative;
overflow:hidden;
}
#one:after {
display:block;
content:".";
font-size:0;
color:transparent;
height:8px;
width:100%;
padding-left:4px;
position:absolute;
bottom:-4px;
left:-4px;
background:#fff;
z-index:2;
-moz-box-shadow: inset 0 0 3px 1px rgba(0,0,0,0.3);
-webkit-box-shadow: inset 0 0 3px 1px rgba(0,0,0,0.3);
box-shadow: inset 0 0 3px 1px rgba(0,0,0,0.3);
}
#two {
width: 100px;
height: 300px;
background: #FFF;
-moz-box-shadow: 0 0 3px 1px rgba(0,0,0,0.3);
-webkit-box-shadow: 0 0 3px 1px rgba(0,0,0,0.3);
box-shadow: 0 0 3px 1px rgba(0,0,0,0.3);
float:left;
}
</style>
Is there a way to drop the shadow only on the bottom?. I have a menu with 2 images next to each other. I don't want a right shadow because it overlaps the right image. I don't like to use images for this so is there a way to drop it only on the bottom like:
box-shadow-bottom: 10px #FFF; or similar?
-moz-box-shadow: 0px 3px 3px #000;
-webkit-box-shadow: 0px 3px 3px #000;
box-shadow-bottom: 5px #000;
/* For IE 8 */
-ms-filter: "progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=180, Color='#000000')";
/* For IE 5.5 - 7 */
filter: progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=180, Color='#000000');
UPDATE 4
Same as update 3 but with modern css (=fewer rules) so that no special positioning on the pseudo element is required.
#box {
background-color: #3D6AA2;
width: 160px;
height: 90px;
position: absolute;
top: calc(10% - 10px);
left: calc(50% - 80px);
}
.box-shadow:after {
content:"";
position:absolute;
width:100%;
bottom:1px;
z-index:-1;
transform:scale(.9);
box-shadow: 0px 0px 8px 2px #000000;
}
<div id="box" class="box-shadow"></div>
UPDATE 3
All my previous answers have been using extra markup to get create this effect, which is not necessarily needed. I think this is a much cleaner solution... the only trick is playing around with the values to get the right positioning of the shadow as well as the right strength/opacity of the shadow. Here's a new fiddle, using pseudo-elements:
http://jsfiddle.net/UnsungHero97/ARRRZ/2/
HTML
<div id="box" class="box-shadow"></div>
CSS
#box {
background-color: #3D6AA2;
width: 160px;
height: 90px;
margin-top: -45px;
margin-left: -80px;
position: absolute;
top: 50%;
left: 50%;
}
.box-shadow:after {
content: "";
width: 150px;
height: 1px;
margin-top: 88px;
margin-left: -75px;
display: block;
position: absolute;
left: 50%;
z-index: -1;
-webkit-box-shadow: 0px 0px 8px 2px #000000;
-moz-box-shadow: 0px 0px 8px 2px #000000;
box-shadow: 0px 0px 8px 2px #000000;
}
UPDATE 2
Apparently, you can do this with just an extra parameter to the box-shadow CSS as everyone else just pointed out. Here's the demo:
http://jsfiddle.net/K88H9/821/
CSS
-webkit-box-shadow: 0 4px 4px -2px #000000;
-moz-box-shadow: 0 4px 4px -2px #000000;
box-shadow: 0 4px 4px -2px #000000;
This would be a better solution. The extra parameter that is added is described as:
The fourth length is a spread
distance. Positive values cause the
shadow shape to expand in all
directions by the specified radius.
Negative values cause the shadow shape
to contract.
UPDATE
Check out the demo at jsFiddle: http://jsfiddle.net/K88H9/4/
What I did was to create a "shadow element" that would hide behind the actual element that you would want to have a shadow. I made the width of the "shadow element" to be exactly less wide than the actual element by 2 times the shadow you specify; then I aligned it properly.
HTML
<div id="wrapper">
<div id="element"></div>
<div id="shadow"></div>
</div>
CSS
#wrapper {
width: 84px;
position: relative;
}
#element {
background-color: #3D668F;
height: 54px;
width: 100%;
position: relative;
z-index: 10;
}
#shadow {
background-color: #3D668F;
height: 8px;
width: 80px;
margin-left: -40px;
position: absolute;
bottom: 0px;
left: 50%;
z-index: 5;
-webkit-box-shadow: 0px 2px 4px #000000;
-moz-box-shadow: 0px 2px 4px #000000;
box-shadow: 0px 2px 4px #000000;
}
Original Answer
Yes, you can do this with the same syntax you have provided. The first value controls the horizontal positioning and the second value controls the vertical positioning. So just set the first value to 0px and the second to whatever offset you'd like as follows:
-webkit-box-shadow: 0px 5px #000000;
-moz-box-shadow: 0px 5px #000000;
box-shadow: 0px 5px #000000;
For more info on box shadows, check out these:
http://www.css3.info/preview/box-shadow/
https://developer.mozilla.org/en/css/-moz-box-shadow#Browser_compatibility
http://www.w3.org/TR/css3-background/#the-box-shadow
Just use the spread parameter to make the shadow smaller:
.shadow {
-webkit-box-shadow: 0 6px 4px -4px black;
-moz-box-shadow: 0 6px 4px -4px black;
box-shadow: 0 6px 4px -4px black;
}
<div class="shadow">Some content</div>
Live demo: http://dabblet.com/gist/a8f8ba527f5cff607327
To not see any shadow on the sides, the (absolute value of the) spread radius (4th parameter) needs to be the same as the blur radius (3rd parameter).
If you have a fixed color on the background, you can hide the side-shadow effect with two masking shadows having the same color of the background and blur = 0, example:
box-shadow:
-6px 0 white, /*Left masking shadow*/
6px 0 white, /*Right masking shadow*/
0 7px 4px -3px black; /*The real (slim) shadow*/
Note that the black shadow must be the last, and has a negative spread (-3px) in order to prevent it from extendig beyond the corners.
Here the fiddle (change the color of the masking shadows to see how it really works).
div{
width: 100px;
height: 100px;
border: 1px solid pink;
box-shadow: -6px 0 white, 6px 0 white, 0 7px 5px -2px black;
}
<div></div>
You could also use clip-path to clip (hide) all overflowing edges but the one you want to show:
.shadow {
box-shadow: 0 4px 4px black;
clip-path: polygon(0 0, 100% 0, 100% 200%, 0 200%);
}
See clip-path (MDN). The arguments to polygon are the top-left point, the top-right point, the bottom-right point, and the bottom-left point. By setting the bottom edge to 200% (or whatever number bigger than 100%) you constrain your overflow to only the bottom edge.
Examples:
.shadow {
box-shadow: 0 0 8px 5px rgba(200, 0, 0, 0.5);
}
.shadow-top {
clip-path: polygon(0% -20%, 100% -20%, 100% 100%, 0% 100%);
}
.shadow-right {
clip-path: polygon(0% 0%, 120% 0%, 120% 100%, 0% 100%);
}
.shadow-bottom {
clip-path: polygon(0% 0%, 100% 0%, 100% 120%, 0% 120%);
}
.shadow-left {
clip-path: polygon(-20% 0%, 100% 0%, 100% 100%, -20% 100%);
}
.shadow-bottom-right {
clip-path: polygon(0% 0%, 120% 0%, 120% 120%, 0% 120%);
}
/* layout for example */
.box {
display: inline-block;
vertical-align: top;
background: #338484;
color: #fff;
width: 4em;
height: 2em;
margin: 1em;
padding: 1em;
}
<div class="box">none</div>
<div class="box shadow shadow-all">all</div>
<div class="box shadow shadow-top">top</div>
<div class="box shadow shadow-right">right</div>
<div class="box shadow shadow-bottom">bottom</div>
<div class="box shadow shadow-left">left</div>
<div class="box shadow shadow-bottom-right">bottom right</div>
I think this is what you're after?
.shadow {
-webkit-box-shadow: 0 0 0 4px white, 0 6px 4px black;
-moz-box-shadow: 0 0 0 4px white, 0 6px 4px black;
box-shadow: 0 0 0 4px white, 0 6px 4px black;
}
<div class="shadow">wefwefwef</div>
Another idea based on the answer of #theengineear where I will use inset instead of polygon. It's easier since it works the same way as margin or padding. I will also rely on CSS variable to easily define all the different cases.
.shadow {
box-shadow: 0 0 8px 5px rgba(200, 0, 0, 0.5);
clip-path:inset(var(--t,0) var(--r,0) var(--b,0) var(--l,0))
}
.top { --t:-100%; }
.right { --r:-100%;}
.bottom { --b:-100%; }
.left { --l:-100%;}
/* layout for example */
.box {
display: inline-block;
vertical-align: top;
background: #338484;
color: #fff;
width: 4em;
height: 2em;
margin: 1em;
padding: 1em;
}
<div class="box">none</div>
<div class="box shadow top right left bottom">all</div>
<div class="box shadow top">top</div>
<div class="box shadow right">right</div>
<div class="box shadow bottom">bottom</div>
<div class="box shadow left">left</div>
<div class="box shadow bottom right">bottom right</div>
<div class="box shadow bottom top">top bottom</div>
<div class="box shadow left top right">top left right</div>
<div class="box shadow left right"> left right</div>
It's always better to read the specs. There is no box-shadow-bottom property, and as Lea points out you should always place the un-prefixed property at the bottom, after the prefixed ones.
So it's:
.shadow {
-webkit-box-shadow: 0px 2px 4px #000000;
-moz-box-shadow: 0px 2px 4px #000000;
box-shadow: 0px 2px 4px #000000;
}
<div class="shadow">Some content</div>
How about just using a containing div which has overflow set to hidden and some padding at the bottom? This seems like much the simplest solution.
Sorry to say I didn't think of this myself but saw it somewhere else.
Using an element to wrap the element getting the box-shadow and a overflow: hidden on the wrapper you could make the extra box-shadow disappear and still have a usable border.
This also fixes the problem where the element is smaller as it seems, because of the spread.
Like this:
#wrapper { padding-bottom: 10px; overflow: hidden; }
#elem { box-shadow: 0 0 10px black; }
Content goes here
Still a clever solution when it has to be done in pure CSS!
As said by Jorgen Evens.
I also needed a shadow but only under an image and set in slightly left and right. This worked for me:
.box-shadow {
-webkit-box-shadow: 5px 35px 30px -25px #888888;
-moz-box-shadow: 5px 35px 30px -25px #888888;
box-shadow: 5px 35px 30px -25px #888888;
}
The element this is applied to is a page-wide image (980px x 300px).
If it helps when fiddling with the settings, they run as follows:
horizontal shadow, vertical shadow, blur distance, spread (i.e. shadow size), and color.
It is better to look up shadow:
.header{
-webkit-box-shadow: 0 -8px 73px 0 rgba(0,0,0,0.2);
-moz-box-shadow: 0 -8px 73px 0 rgba(0,0,0,0.2);
box-shadow: 0 -8px 73px 0 rgba(0,0,0,0.2);
}
this code is currently using on stackoverflow web.
If your background is solid (or you can reproduce it using CSS), you can use linear gradient that way:
div {
background-image: linear-gradient(to top, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.3) 5px, #fff 5px, #fff 100%)
}
<div>
<p>Foobar</p>
<p>test</p>
</div>
This will generate a 5px gradient at the bottom of the element, from black at 30% opacity to completely transparent. The rest of the element has white background. Of course, changing the last 2 color stops of the linear gradient, you could make the background completely transparent.
This code pen (not by me) demonstrates a super simple way of doing this and the other sides by themselves quite nicely:
box-shadow: 0 5px 5px -5px #333;
https://codepen.io/zeckdude/pen/oxywmm
You could also just do a gradient on the bottom - this was helpful for me because the shadow I wanted was on an element that was already semi-transparent, so I didn't have to worry about any clipping:
&:after {
content:"";
width:100%;
height: 8px;
position: absolute;
bottom: -8px;
left: 0;
background: linear-gradient(to bottom, rgba(0,0,0,0.65) 0%,rgba(0,0,0,0) 100%);
}
Just make the "bottom" and "height" properties match and set your rgba values to whatever you want them to be at the top / bottom of the shadow
You can do that like this:
General syntax:
selector {
box-shadow: topBoxShadow, bottomBoxShadow, rightBoxShadow, leftBoxShadow
}
Example: we want to make only a bottom box shadow with red color,
so to do that we have to set all the sides options where we have to set the bottom box shadow options and set all the others as empty as follow:
.box {
-moz-box-shadow: 0 0 0 transparent ,0 0 10px red, 0 0 0 transparent, 0 0 0 transparent
-o-box-shadow: 0 0 0 transparent ,0 0 10px red, 0 0 0 transparent, 0 0 0 transparent
-webkit-box-shadow: 0 0 0 transparent ,0 0 10px red, 0 0 0 transparent, 0 0 0 transparent
box-shadow: 0 0 0 transparent ,0 0 10px red, 0 0 0 transparent, 0 0 0 transparent
}
You need fist to know each value is for what:
/* offset-x | offset-y | blur-radius | spread-radius | color */
box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
To apply a shadow effect only on one side of an element set the blur value to a positive number and set the spread value to the same size but with a negative sign. Depending on which side you want the shadow on, set the offset value as follows:
Top shadow: offset-x: 0 and offset-y: -5px
Right shadow: offset-x: 5px and offset-y: 0
Bottom shadow: offset-x: 0 and offset-y: 5px
Left shadow: offset-x: -5px and offset-y: 0
.box{
margin: 2rem;
padding: 1rem;
}
.shadow-all{
box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
}
.shadow-top {
box-shadow: 0 -5px 3px -3px #00000030;
}
.shadow-right {
box-shadow: 5px 0 3px -3px #00000030;
}
.shadow-bottom {
box-shadow: 0 5px 3px -3px #00000030;
}
.shadow-left {
box-shadow: -5px 0 3px -3px #00000030;
}
<div class="box shadow-all">
Shadow All
</div>
<div class ="box shadow-top">
Shadow Top
</div>
<div class ="box shadow-right">
Shadow Right
</div>
<div class ="box shadow-bottom">
Shadow Bottom
</div>
<div class ="box shadow-left">
Shadow left
</div>
Read more here and here
inset top and bottom box-shadow
.cont{
position: relative;
border: 1px solid black;
margin: 0 auto;
width: 200px;
height: 200px;
overflow: hidden;
}
.shadow {
position: absolute;
width: 100%;
height:100%;
box-shadow: inset gray 0px 50px 15px 0px,inset gray 0px -50px 15px 0px;
padding-right: 30px;
margin-left: -15px;
}
<div class=cont>
<div class=shadow></div>
</div>
update on someone else his answer transparant sides instead of white so it works on other color backgrounds too.
body {
background: url(http://s1.picswalls.com/wallpapers/2016/03/29/beautiful-nature-backgrounds_042320876_304.jpg)
}
div {
background: url(https://www.w3schools.com/w3css/img_avatar3.png) center center;
background-size: contain;
width: 100px;
height: 100px;
margin: 50px;
border: 5px solid white;
box-shadow: 0px 0 rgba(0, 0, 0, 0), 0px 0 rgba(0, 0, 0, 0), 0 7px 7px -5px black;
}
<div>
</div>
inner shadow
.shadow {
-webkit-box-shadow: inset 0 0 9px #000;
-moz-box-shadow: inset 0 0 9px #000;
box-shadow: inset 0 0 9px #000;
}
<div class="shadow">wefwefwef</div>