Box shadow on adjacent elements with variable width - html

I'm trying to add a box shadow on two elements, each with variable width. My desired result looks like this:
I've been trying to get to this result with a pseudo element covering the overlapping box shadows, but because they need to have transparency, I can't seem to find a solution in which there are neither small overlaps at the edges of the boxes nor the pseudo element adjusts to the correct width.
The top box does also not necessarily need a top border to solve my problem.
Fiddle
HTML:
<div>
<p></p>
</div>
<div>
<p></p>
</div>
SCSS:
div {
display: inline-block;
margin: 75px;
width: 200px;
height: 50px;
position: relative;
p {
position: absolute;
top: 100%;
left: 0;
height: 300px;
width: 250px;
}
&, p {
background: #ededed;
}
}
div:last-child p {
width: 150px
}
div {
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.2);
p {
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.2);
}
}
Edit:
Normally I wouldn't consider JS for layout but since in my particular case the boxes won't be visible until a user interaction occurs, I've used a script to solve my problem.
The script figures out if the top element is bigger than the bottom one when the dom is ready and adds a "big" or "small" class to it respectively. By knowing that, we know which element the pseudo-element's width should inherit. As long as the elements don't get resized in a way that would change which element is bigger, this works fine.
There is also a much cleaner solution without the need for JS and one pseudo element less in case one only needs box-sizing blur and no spread.
Fiddles:
Blur and spread combined (JS),
Only blur, no spread (No JS)
The end result is not quite perfect as you can see in this screenshot where all the white background is replaced with black:
When you look at the left box's top left, you can see that the border shadow has a slight curve.
Anyway, it's close enough to me.
If someone finds a solution with a similar result as in the first fiddle using only css, I would really appreciate it.

You have an easy solution for this, but it is an experimental feature and it has limited support.
Using a filter: drop shadow on the base element, the drop shadow applies to the composite result of this element, and all the descendants
div {
display: inline-block;
margin: 75px;
width: 150px;
height: 50px;
position: relative;
-webkit-filter: drop-shadow(0px 0px 5px rgba(255, 0,0,0.7));
filter: drop-shadow(0px 0px 2px red);
}
div p {
position: absolute;
top: 100%;
left: 0;
height: 300px;
width: 250px;
margin: 0px;
}
div, div p {
background: #ededed;
}
#second p {
width: 100px;
}
<div>
<p></p>
</div>
<div id="second">
<p></p>
</div>
An alternate approach, that will run in any browser, using pseudo elements for the shadows:
div {
display: inline-block;
margin: 75px;
width: 150px;
height: 50px;
position: relative;
}
div p {
position: absolute;
top: 100%;
left: 0;
height: 300px;
width: 250px;
margin: 0px;
}
div, div p {
background: #ededed;
}
#second p {
width: 100px;
}
div:after, p:after {
content: "";
position: absolute;
left: 0px;
top: 0px;
right: 0px;
bottom: 0px;
box-shadow: 0px 0px 2px 6px rgba(0,255,0,0.7);
z-index: -10;
}
<div>
<p></p>
</div>
<div id="second">
<p></p>
</div>
An alternate approach is to clip the shadows. That is poorly suported, and needs lots of manual adjustements, but the end result is probably the best looking.
Demo working only in webkit
div {
display: inline-block;
margin: 75px;
width: 300px;
height: 50px;
position: absolute;
}
div p {
position: absolute;
top: 100%;
left: 0;
height: 100px;
width: 200px;
margin: 0px;
}
div, div p {
background: #ededed;
}
div:after, p:after {
content: "";
position: absolute;
left: 0px;
top: 0px;
right: 0px;
bottom: 0px;
box-shadow: 0px 0px 15px 15px rgba(255,0,0,0.2);
z-index: -10;
}
p:after {
-webkit-clip-path: polygon(0% 30px, 230px 30px, 260px 60px, 100% 100%, 0% 100%);
}
div:after {
-webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 260px 100%, 230px 80px, 0% 80px);
}
<div>
<p></p>
</div>

If you really need a plain color background instead of a background image, this shall work:
I used a div to create the empty area.
<div class="shad">
<div class="cover1"></div>
<p></p>
</div>
<div class="shad">
<div class="cover2"></div>
<p></p>
</div>
The paragraphs are set to same size as div.shad.
div.shad {
display: inline-block;
margin: 75px;
width: 250px;
height: 350px;
position: relative;
background: #ededed;
p {
position: absolute;
top: 0%;
left: 0;
width: 250px;
height: 350px;
}
.cover1 {
position: relative;
float: right;
margin-top: -2px;
margin-right: -2px;
width: 50px;
height: 50px;
background-color: white;
border-left: 2px solid rgba(0, 0, 0, 0.2);
border-bottom: 2px solid rgba(0, 0, 0, 0.2);
}
.cover2 {
position: relative;
float: right;
margin-top: 50px;
margin-right: -2px;
width: 50px;
height: 300px;
background-color: white;
border-top: 2px solid rgba(0, 0, 0, 0.2);
border-left: 2px solid rgba(0, 0, 0, 0.2);
}
}
div.shad {
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.2);
}

Related

Stacking div over another div

I'm trying to achieve something like the image I've attached
And this is what I'm trying to do in css but couldn't get it to work.
#div_1 {
width: 90%;
background: #FBFBFB;
box-shadow: 1px 1px 30px rgba(0, 0, 0, .1);
}
#div_2 {
height: 110%;
width: 30%;
margin-top: -5%;
margin-left: 60%;
vertical-align: top;
background: #FBFBFB;
box-shadow: 1px 1px 30px rgba(0, 0, 0, .1);
}
<div id="div_wrapper">
<div id="div_1">
<div id="div_2"></div>
</div>
</div>
Give position: relative to the parent and position: absolute to the child element, which will make sure that the child is positioned relative to the parent element. Then you can place it wherever you want based on the appropriate top and left positioning properties which replaced the unnecessary margins:
#div_1 {
position: relative; /* added */
width: 90%;
background: #FBFBFB;
box-shadow: 1px 1px 30px rgba(0,0,0,.1);
}
#div_2 {
position: absolute; /* added */
height: 110%;
width: 30%;
top: -5%; /* modified */
left: 60%; /* modified */
background: #FBFBFB;
box-shadow: 1px 1px 30px rgba(0,0,0,.1);
}
<div id="div_wrapper">
<div id="div_1">
Div 1
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div id="div_2">
Div 2
</div>
</div>
</div>
You can try something like below snippet. You need not mention .child div's height as it will be calculated when you set top and bottom.
.parent {
position: relative;
width: 80%;
height: 80vh;
margin: 5% auto;
background: #fff;
box-shadow: 0px 0px 5px #000;
}
.child{
position: absolute;
top:-5%;
bottom:-5%;
right: 10%;
width: 30%;
background: #fff;
box-shadow: 0px 0px 5px #000;
}
<div class="parent">
<div class="child">
</div>
</div>
What you need to do is to set your wrapper div position as relative and set it's display property to block.
Now you can set your desired width and height to the wrapper.
Wrapper is marked with red dashed line.
Now you have to set the height for the child elements to expand to their wrapper div.
You can do that by providing a
height: 100%
to div1
Next is to align child items to their parent element.
Usually to align a child element to it's parent you can set the position of parent as relative and child as absolute.
You can set position: absolute to div2 and position:relative to div1
I would suggest to set the location of div2 using top and left rather than margin-top and margin-left.
Here is a very nice explanation about positions and the common mistakes:
https://css-tricks.com/absolute-relative-fixed-positioining-how-do-they-differ/
and here https://css-tricks.com/absolute-positioning-inside-relative-positioning/ you can find some tips on how to position parent and child elements.
I have modified your code a bit, have a look at it here:
#div_wrapper {
display: block;
position: relative;
height: 200px; /* Change to whatever height you like */
width: 400px; /* Change to whatever width you like */
top: 50px; /* Just for demo */
left: 10px; /* Just for demo */
}
#div_1 {
display: block;
position: relative; /* Added */
width: 90%;
height: 100%; /* Added */
background: #FBFBFB;
box-shadow: 1px 1px 30px rgba(0, 0, 0, .1);
}
#div_2 {
position: absolute; /* Added */
height: 110%;
width: 30%;
top: -5%; /* Modified */
left: 60%; /* Modified */
vertical-align: top;
background: #FBFBFB;
box-shadow: 1px 1px 30px rgba(0, 0, 0, .1);
}
<div id="div_wrapper">
<div id="div_1">
<div id="div_2"></div>
</div>
</div>
Try following code it can be work for you may be. You will see effect when "#div_1" have content or height.
#div_1 {
width: 90%;
position: relative;
background: #FBFBFB;
box-shadow: 1px 1px 30px rgba(0, 0, 0, .1);
}
#div_2 {
width: 30%;
position: absolute;
top: -5%;
bottom: -5%;
left: 60%;
vertical-align: top;
background: #FBFBFB;
box-shadow: 1px 1px 30px rgba(0, 0, 0, .1);
}
<style type="text/css">
#div_wrapper{
position: relative;
width: 100%;
}
#div_1 {
width: 90%;
background: #FBFBFB;
box-shadow: 1px 1px 30px rgba(0, 0, 0, .1);
height: 300px;
margin-top: 100px;
position: relative;
}
#div_2 {
position: absolute;
height: 120%;
width: 30%;
right: 5%;
top:-10%;
background: #FBFBFB;
box-shadow: 1px 1px 30px rgba(0, 0, 0, .1);
}
</style>
<div id="div_wrapper">
<div id="div_1"> div 1
<div id="div_2">div 2</div>
</div>
</div>
For this layout it would be good, if you use position:absolute for div_2 ID and position:relative for div_1 ID, this will let you position the child div anywhere relative to the parent and it is dependent on the height of div_1.
#div_1 {
width: 90%;
background: #FBFBFB;
display:inline-block;
position:relative;
box-shadow: 1px 1px 30px rgba(0, 0, 0, .1);
}
#div_2 {
width: 30%;
position:absolute;
right:10%;
top:-10px;
bottom:-10px;
vertical-align: top;
background: #FBFBFB;
box-shadow: 1px 1px 30px rgba(0, 0, 0, .1);
}
#div_wrapper{
text-align:center;
margin:50px 0px;
}
<div id="div_wrapper">
<div id="div_1">test
<div id="div_2">test2</div>
</div>
</div>

How to hide shadow between two adjoined divs

I have two divs on top of each other (adjoined) and they booth as one unit shall have one box-shadow. Now the upper div gives shadow on the lower div which I don't want. I have tried to manipulate it with a "z-index:2" to be more on top but no luck.
I would like to hide the bottom shadow of the upper div and hide the top shadow of the lower div
Also I don't want the shadow to fold into the adjoined sides. The two divs should be one unit having one shadow
In my example here I have simpified the html
<div class="upper-box" style="width:100px;height:100px;">
</div>
<div class="lower-div" style="width:100px;height:100px;">
</div>
In the jsfiddle the css is all in original and here goes all the work of change.
.upper-box {
border-top: 0 none;
margin-bottom: 2px;
margin-top: -2px;
overflow: auto;
position: relative;
padding-top: 0;
/* Expanded panel gets emphasized by a shadow */
box-shadow: 0px 6px 50px 7px rgba(255,255,255,0.75),
0px 6px 50px 7px rgba(88,88,88,0.75),
0px 6px 50px 7px rgba(88,88,88,0.75),
0px 6px 50px 7px rgba(88,88,88,0.75)
;
z-index: 3;
border-style: solid;
border-color: #000000;
border-width: 0px;
position: relative;
}
.lower-div {
border-bottom: 0px;
box-shadow: 0px 6px 50px 7px rgba(88,88,88,0.75);
z-index: 2;
border-style: solid;
border-color: #000000;
border-width: 0px;
}
I would like to hide the bottom shadow of the upper div and hide the top shadow of the lower div
Also I don't want the shadow to fold into the adjoined sides. The two divs should be one unit having one shadow
Here is my live demo
https://jsfiddle.net/y289sdeb/
You could use a pseudo element, like this
.upper-box {
position: relative;
width: 100px;
height: 100px;
background: white;
}
.lower-div {
position: relative;
width: 100px;
height: 100px;
background: white;
}
.upper-box::after,
.lower-div::after {
content: '';
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
box-shadow: 0px 6px 50px 7px rgba(88, 88, 88, 0.75);
z-index: -1;
}
<div class="upper-box">
</div>
<div class="lower-div">
</div>
Based on a comment, a wrapper can be used
.wrapper {
position: relative;
display: inline-block;
}
.upper-box {
position: relative;
width: 100px;
height: 100px;
}
.lower-div {
position: relative;
width: 100px;
height: 100px;
}
.wrapper::after {
content: '';
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
box-shadow: 0px 6px 50px 7px rgba(88, 88, 88, 0.75);
z-index: -1;
}
<div class="wrapper">
<div class="upper-box">
</div>
<div class="lower-div">
</div>
</div>

Make rectangle with one side curved

Is it possible to make a div same as this shape, if yes could you please share the code
I would use SVG: http://codepen.io/anon/pen/JdMVXY
<svg>
<path d="M260 150, 0 150, 0 0, 300 0 Q260 75, 260 150"
stroke="transparent" fill="#bd9" />
</svg>
When you have defined the correct aspect ratio of the box, you can also scale the SVG element with a simple CSS transformation (as shown in the example)
Result
This is possible within CSS using a single element with pseudo-elements with border-radius and background-shadow to create the curve.
div {
height: 100px;
width: 300px;
position: relative;
overflow: hidden;
}
div:before {
content: '';
position: absolute;
top: -150%;
left: 50%;
width: 200%;
padding-bottom: 200%;
border-radius: 100%;
background: none;
-webkit-box-shadow: 0px -10px 5px 300px #F15723;
box-shadow: 0px -10px 5px 300px #F15723;
z-index: -1;
}
<div></div>
Try this to make 'div' element:
<div id="test">
<div class="oposite-radius"></div>
<style>
#test {
position: relative;
margin: 30px;
width: 200px;
height: 100px;
border: 1px solid #333;
}
.oposite-radius {
position: absolute;
height: 100px;
width: 20px;
border: 1px solid #333;
background-color: #fff;
left: 180px;
border-radius: 100% 0 0 0;
border-width: 1px 0 0 1px;
}
</style>

Box-shadow side-effect blur not smooth. inner square in shadow

I have a slider on my page to change the box-shadow values. At some high blurring values there is an unwanted box-like breaking the shadow, when it is supposed to be a smooth shadow all the way. Is there anyway to avoid this easily? Thanks for the help.
P. S.
I actually need it to work with 'inset' too.
div
{
width:200px;
height:200px;
border-radius: 100px;
background-color:blue;
-webkit-box-shadow: 169px 129px 300px -15px rgba(0,0,0,1);
-moz-box-shadow: 169px 129px 300px -15px rgba(0,0,0,1);
box-shadow: 169px 129px 300px -15px rgba(0,0,0,1);
}
<div></div>
For circular box-shadows the blur cannot go above the width & height of the element. The spread can though.
Since your element is 200px * 200px, the maximum for the blur value is 200px.
Have a look below at the example which doesn't go above 200px and you will see that it creates the box-shadow as expected
div {
width: 200px;
height: 200px;
border-radius: 100px;
background-color: blue;
box-shadow: 169px 129px 200px -15px rgba(0, 0, 0, 1);
}
<div></div>
The spread value can alternatively go above the element width and height and therefore you can make bigger spreads.
div {
width: 200px;
height: 200px;
border-radius: 100px;
background-color: blue;
box-shadow: 169px 129px 0 250px rgba(0, 0, 0, 1);
}
<div></div>
You also didn't really need the prefixes since CSS3 Box-shadows are very well supported now. CanIUse
You can read more about CSS Box shadows in the MDN Documentation
If you want to go outside its dimensions on the shape to be blurred:
The code creates a copy of the circle then colours it black and uses the filter:blur(length);
.circle {
border-radius: 50%;
width: 100px;
height: 100px;
position: relative;
}
.circle::after {
position: absolute;
display: block;
content: " ";
border-radius: 50%;
width: 100%;
height: 100%;
background-color: blue;
}
.circle::before {
position: absolute;
display: block;
content: " ";
border-radius: 50%;
width: 100%;
height: 100%;
background-color: black;
top: 50%;
left: 50%;
-webkit-filter: blur(50px);
filter: blur(50px);
}
<div class="circle"></div>
You can also create inset shadows this way.
How it works:
1. The initial shape is the shadow-color
2. Set overflow:hidden so nothing goes outside the shape.
3. Put a shape on top
4. Blur the shape on top
By doing this the shape under shines through creating the inner shadow effect
.circle {
border-radius: 50%;
width: 100px;
height: 100px;
position: relative;
background-color: black;
overflow: hidden;
}
.circle::before {
position: absolute;
display: block;
content: " ";
border-radius: 50%;
width: calc(100%);
height: calc(100%);
background-color: blue;
transform: translate(-50%, -50%);
top: 50%;
left: 50%;
-webkit-filter: blur(20px);
filter: blur(20px);
}
<div class="circle"></div>

Overlap an img completely with another div

I am trying to achieve this effect where a photo gets a repeating pattern overlayed over the entire photo when the user place his mouse over the photo.
Problem: I do not seem to be able to make the overlay div overlay the photo completely. How should this be done?
JSfiddle: http://jsfiddle.net/KDyKH/2/
Edit: Updated the fiddle
CSS
#container {
position: relative;
padding: 10px;
width: 1000px;
height: 500px;
background: blue;
}
.photo_box {
padding: 8px 10px 11px 10px;
background: #fff;
-webkit-box-shadow: 1px 1px 6px rgba(50, 50, 50, 0.25);
-moz-box-shadow: 1px 1px 6px rgba(50, 50, 50, 0.25);
box-shadow: 1px 1px 6px rgba(50, 50, 50, 0.25);
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
display: inline-block;
position: relative;
}
.photo {
position: absolute;
z-index: 0;
margin-bottom: 13px;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
.photo_tint {
width: 100%;
height: 100%;
position: absolute;
z-index: 100;
background: red;
-moz-opacity: 0.70;
opacity: 0.70;
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha"(Opacity=70);
}​
HTML
<div id="container">
<div class="photo_box">
<img src='http://www.kurzweilai.net/images/Google-logo.jpg' class="photo">
<div class="photo_tint"></div>
</img>
</div>
</div>​
In addition to adding left and top properties to .photo_tint, you also need to make .photo_box relatively positioned (it wasn't before you edited your question).
.photo_box {
position: relative;
}
.photo_tint {
left:0;
right:0;
}​
http://jsfiddle.net/KDyKH/5/
The absolute position's left/top/right/bottom attributes work off the last element higher in the hierarchy with position set to relative or absolute. If no parent elements have position set to relative/absolute, the body is used. In your case, the closest relatively positioned element was #container, so when left and top were set on .photo_tint it used #container's origin and not .photo_box's origin as needed to achieve the desired effect.
Additionally, if an element is set to position:absolute, and no left/top/right/right properties are set, the element will not behave as absolute (see this question).
.photo_tint {
position: absolute;
z-index: 100;
background: red;
top:0; left:0;
width:100%; height:100%;
}​
???
http://jsfiddle.net/tFbbM/1/
Just position the photo_tint div using top and left. http://jsfiddle.net/OhMrBigshot/gEdJu/
z-index:-1 on the image or z-index:2 on the div
#container {
position: relative;
width: 500px;
height: 500px;
background: blue;
}
.photo {
position: relative;
width: 300px;
height: 100px;
background: green;
}
.photo_tint {
position: absolute;
z-index: 1;
background: red;
width: 300px;
height: 100px;
top:0px;
}​