Z-index "stacking" in creating a shadow - html

I have the following HTML structure that I'd like to keep nested:
<div class="parent">
<div class="shadow">Shadow here!</div>
</div>
CSS:
.parent {
background: blue;
z-index: 2;
height: 200px;
}
.shadow {
background: lightgrey;
z-index: 0;
opacity: 0.4;
position: relative;
top: 194px;
}
Essentially, I want the div .shadow to be underneath the div .parent. If you look at the rendering at the below link, you can see that part of the parent's blue background goes through the shadow; instead, I'd like the parent element to cover that overlapping part (stacked on top of, I guess you can say):
https://jsfiddle.net/9ya7kb67/
How could I do this? I'm fiddling around with z-index, but that isn't helping.

This is simple... give your shadow z-index property negative value like this. You can also manage z-index by giving higher value. Or you can use box-shadow property to make shadow.
.parent {
background: blue;
z-index: 2;
height: 200px;
}
.shadow {
background: lightgrey;
z-index: -1;
opacity: 0.4;
position: relative;
top: 194px;
}

You can use box shadow with CSS3 https://css-tricks.com/snippets/css/css-box-shadow/

CSS box-shadow works by creating a shadow behind an element. Thus, the element is already on top of the shadow. Here, z-index is not required.
the code:
.parent {
background: blue;
height: 200px;
box-shadow: 0 8px 0 4px light grey;
}
is doing the same thing regardless if you include z-index or not.

I'm not sure if it is the answer you are looking for, but you can always use the CSS property box-shadow on your parent to get a 'shadowy' effect.
See this fiddle here
You can find box shadow generators online to make your life easier, such as this one

.shadow requires a negative z-index value as z-index is inherited from it's parent and is comparatively displayed. z-index:0; gives it the same overall z-index the parent has, and as the child was declared after the parent, it is therefore on top. This means that by setting it to z-index:-1 you are placing the shadow behind the parent.
However, if you simply want a box-shadow I would recommend actually using CSS3 Box Shadows instead of creating additional elements.

Because the shadow is INSIDE of the parent, there is no way to make the parent appear on top of whatever is inside. This is because in CSS a child element inherits the z-index of its parent as a BASE z-index. It can have its own z-index but it can never be less than its parent.
EDIT: Box shadow solution -
https://jsfiddle.net/9ya7kb67/3/
.parent {
background: blue;
z-index: 2;
height: 200px;
box-shadow: 0 8px 0px 4px lightgrey;
}
EDIT2: I stand corrected about it being impossible to put a child below a parent. You CAN actually do this, but that is assuming that the parent does not already have a z-index set. If the parent has a z-index, THEN it is impossible to place it on top of a child.

Related

Bootstrap 3: Stacking Order in Navbar with Custom Image Styling

I have been trying to port the functionality of a simple rounded image class to work with Bootstrap v3.3.7. Essentially, I nest an img inside of a div, and apply an inset border with alpha-transparency. It works great, as seen in this simple jsFiddle:
Rounded Avatar jsFiddle
CSS:
.inset {
width: 48px;
height: 48px;
border-radius: 50%;
box-shadow:
inset 0 0 0 2px rgba(255,255,255,0.6),
0 1px 1px rgba(0,0,0,0.1);
}
.inset img {
border-radius: inherit;
width: inherit;
height: inherit;
display: block;
position: relative;
z-index: -1;
}
And the markup would look like:
<div class="inset">
<img src="http://rs775.pbsrc.com/albums/yy35/PhoenyxStar/link-1.jpg~c200">
</div>
However, when I attempt to use this inside of a navbar in Bootstrap v3.3.7, I am encountering what I presume to be a stacking issue that I just cannot resolve. As in the sample above, I had started out with the img having a z-index of -1, so that it would sit below the div. This puts it underneath the navbar. So, I had assumed that I could simply push up the z-index of the div and the img to a physical value, trying 998 for the img and 999 for the div.
When I do that, however, the div does not show. If I am to push the img below the div, however, I see the div and the border being correct - I just can't get it to display above the image. I've create a minimal example of this behavior as a Bootply.
Bootply with Avatar Rounding and Missing Inset Border
I am at a loss to explain this, (and my front-end skills leave a bit to be desired). Can only assume that there is something simple that I have to be missing. Any help would be greatly appreciated.
Thank you, in advance.
By giving it a z-index:-1, you're sending your image below the current stacking context. Because it doesn't have one, and because it doesn't have any parent with a background, it renders as you expect it to, but you shouldn't expect it to. And without giving it a z-index:-1, you can't make it render below its parent. But, again, it's not just below the parent, it's below the stacking context.
Here's what happens when I simply put your example inside: a div with background.
The problem is you want an effect applied to the parent to render above the child.
You could (and should) use either a sibling/child of the child, which could be either an unused pseudo-element of the parent or a pseudo-element of the child. But, since the child is an <img /> tag, it cannot have pseudo-elements, so we'll stick to the parent:
.inset {
width: 100px;
height: 100px;
position: relative;
border-radius: 50%;
}
.inset::after {
width: inherit;
height: inherit;
border-radius: inherit;
box-shadow:
inset 0 0 0 2px rgba(255,255,255,0.6),
0 1px 2px rgba(0,0,0,0.1);
position: absolute;
top: 0;
left: 0;
content: '';
}
.inset img {
border-radius: inherit;
width: inherit;
height: inherit;
display: block;
}
<div style="background-color: red;">
<div class="inset">
<img src="http://rs775.pbsrc.com/albums/yy35/PhoenyxStar/link-1.jpg~c200">
</div>
</div>
This will work anywhere you place it, regardless of current z-index or stacking context.
The other option, if you insist on Doing-it-wrong™ would be to wrap the current parent inside an element that would create a new stacking context
position:relative;
z-index: 0;
... but I find it harder to maintain, bloated and probably confusing for anyone not familiar with how stacking contexts work. This technique comes in handy when adding color overlays to images (instead of using an extra element, you just use the wrapper background). But, again, it confuses people so it shouldn't be used.

Z-index below text but above background

I'm trying to get a div to show as a partial background below the inline content of is containing div but above the background of its container. If I set the z-index of just the partial background to -1 it appears behind the background. But if i set the containing divs z-index to 1 while the contained div's z-index is -1 it displays as desired.
Can someone explain to me why this is and if this is a reliable method or not?
.container {
position: relative;
width: 80%;
height: 18px;
padding: 6px 10px;
background: #666;
z-index: 1;
}
.partialbg {
position: absolute;
left: 0px;
top: 0px;
height: 30px;
width: 80%;
background: #0CC;
z-index: -1;
}
<div class="container">Text here
<div class="partialbg"></div>
</div>
The reason this is occurring, is because there is a child and a parent. If you set a z-index on the parent, the child is going to be the same, since the z-index is stacked.
Thus, by setting a z-index of 1 on the parent, the child is now also 1.
It is systematically impossible for the child to be behind the parent, as that doesn't make any sense. However, the text is a sibling of the child. By setting a z-index of -1 on the child, there is essentially no effect between the child and the parent, however since the sibling is effected, the child now goes behind the sibling.

How to keep css background image blurred inside a container?

When I blur a image it overflows the parent container, even specifying overflow to be hidden.
Is there a way to keep the blurred edges inside dimensions?
The image needs to be as css background and not inside tag
Example not working:
.box{
width: 300px;
height: 300px;
border: 1px solid red;
overflow: hidden;
}
.blur{
width: 100%;
height: 100%;
overflow: hidden;
-webkit-filter: blur(20px);
background: url("https://news.slac.stanford.edu/sites/default/files/imagecache/Img350_Scale/images/image/demag-300h.jpg");
}
http://jsfiddle.net/tMjsJ/1/
It can be achieved by applying a margin to the child element and overflow:hidden to the parent.
.box {
overflow: hidden;
margin:5px;
}
.blur {
-webkit-filter: blur(20px);
margin: -5px 0 0 -5px;
background: url("https://news.slac.stanford.edu/sites/default/files/imagecache/Img350_Scale/images/image/demag-300h.jpg");
height:300px;
width:300px;
}
See an example here: http://jsfiddle.net/n1ck/tMjsJ/5/
As Joshua pointed out, it is the same technique as used here: Defined Edges With CSS3 Filter Blur
So, apparently, this doesn't seem to work on background images. Quite interesting find :) A similar but not exact post was demonstrated here:
Defined Edges With CSS3 Filter Blur
I would imagine that if you want to accomplish the same effect, try changing from using a div with a background image to an image itself, using width / height of 100%.
Edit: Check out #N1ck's answer. Applying a negative margin (even -1px) works seems to trigger the proper effect. Nice.
Also - to avoid the bleeding background color (white), or at least manage it better, try setting a background color in addition to the image.

Is there a foreground equivalent to background-image in css?

I want to add some shine to an element on webpage. I would prefer if I don't have to add additional html to the page. I want the image to appear in front of the element rather than behind. What's the best way to do this?
To achieve a "foreground image" (without extra HTML code), you can use a pseudo-element (::before / :before) plus the CSS pointer-events. The last property is needed so that the user can actually click through the layer "as if it did not exist".
Here's an example (using a colour whose alpha channel is 50% so that you can see that the real elements can actually be focused). http://jsfiddle.net/JxNdT/
#cont {
width: 200px;
height: 200px;
border: 1px solid #aaa;
/*To show the boundaries of the element*/
}
#cont:before {
position: absolute;
content: '';
background: rgba(0, 0, 0, 0.5);
width: 200px;
height: 200px;
pointer-events: none;
}
<div id="cont">
Test<br>
<input type="text" placeholder="edit">
</div>
​
PS. I picked the ::before pseudo-element, because that naturally leads to the correct positioning. If I pick ::after, then I have to add position:relative; to the real element (#cont), and top:0;left:0; to the pseudo-element (::after).
PPS. To get the foreground effect on elements without a fixed size, an additional element is needed. This wrapper element requires the position:relative;display:inline-block; styles. Set the width and height of the pseudo-element to 100%, and the pseudo-element will stretch to the width and height of the wrapper element. Demo: http://jsfiddle.net/JxNdT/1/.
If you need a white-transparent foreground
This is for future visitors like me who are considering adding a white-transparent foreground to an element to communicate that it's hidden / disabled for instance. You can often achieve your goal by simply lowering the opacity below 1:
.is-hidden {
opacity: 0.5;
}
visible
<span class="is-hidden">hidden</span>
visible
You can use this css
#yourImage
{
z-index: 1;
}
NOTE
Set the z-index to index greater the the z-index of the element over which you are putting the image.
If you have not specified any z-index then 1 would do the work.
You can also set z-index to -1,in that case the image would always be at background!
A neat solution: box-sizing + padding-left, see more at css-tricks
Somewhere in your HTML:
<img id="test_replacement" src="test.png" alt="test" />
The CSS for replacing the image (on hovering)
#test_replacement {
width: 200px; //must be the size of your image (and the replacement one)
height: 200px; //idem
display: block;
}
#test_replacement:hover {
box-sizing: border-box;
background-image: url('somewhere/other_image.png');
padding-left: 200px; //at least the size of the width
}
Use an absolutely positioned <img> element:
img {
position: absolute;
opacity: 0.3;
pointer-events: none;
}
iframe {
width: 500px;
height: 300px;
border: 0;
}
<img src="https://i.stack.imgur.com/rET57.jpg" alt="Foreground image">
<iframe src="https://example.com/"></iframe>

z-index image over backgrounds element

Back to basics, I have a situation whereby I have an image which needs to appear over the background of an element just below it. However, I do not want the image to be over the top of the content of that element, only the element (and background properties) itself:
http://jsfiddle.net/chricholson/4twr5/1/
HTML:
<img src="https://www.google.com/images/srpr/logo3w.png" />
<div>
Hello World
</div>
​
CSS:
img { position: absolute; z-index: 20; }
div { position: relative; top: 45px; z-index: 10; padding: 30px; background: red; }
a { position: relative; z-index: 30; padding: 10px; background: yellow; display: block; }
Expected behaviour would be the image to appear over the top of the div background [check], but then appear behind the yellow link, which it isn't.
Found my "answer" (more confirming my doubts) here Can't get z-index to work for div inside of another div. The key sentence being "Once you set position:relative on test_1 you are causing its z-index to be in a different world than the z-index of test_2."
It seems the reason I have a problem is because once I have set the image higher than the div, no matter what z-index value I set to the contents of the div it will always be covered. I didn't think z-indexes worked like this, I thought everything was "separate" and so long as a value was higher than a value elsewhere (regardless of parent containers) things would be fine.
img { position: absolute; z-index: 15; }
div { position: relative; top: 45px; z-index: 20; padding: 30px; background: red; }
a {z-index: 30; padding: 10px; background: yellow; display: block; }
​
You can try this code. By the way a is a child of div. You don't need to type position: relative; Because you wrote for div.
Put the image inside the div like so:
<div>
<img src="https://www.google.com/images/srpr/logo3w.png" />
Hello World
</div>
Most of the answers here are pointing out the base truth: in straight up HTML + CSS, this is probably only possible if the <img> is inside of the <div> and a sibling to <a>.
Since you've indicated that you can't change the HTML, you could instead apply a simple JavaScript that would reorder the DOM as necessary for you: $('div').prepend(​$('img')​​​​);​. (This is JQuery, by the way.) What this does is it takes the <img> and sticks it as the first child in <div>.
Of course, if you were to use this in production code, you'd want to append id's to the elements and select off that otherwise you'd have images being stuck into divs willy nilly.
Here is a JSFiddle demo. The JQuery is called onDomReady(). The HTML itself is unchanged.
http://jsfiddle.net/4twr5/21/ Look this jsfiddle
Update according to comment http://jsfiddle.net/4twr5/22/